UNPKG

@backland/schema

Version:

TypeScript schema declaration and validation library with static type inference

285 lines 11.2 kB
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } import { setByPath } from '@backland/utils'; import { BJSON } from '@backland/utils'; import { RuntimeError } from '@backland/utils'; import { expectedType } from '@backland/utils'; import { getByPath } from '@backland/utils'; import { getKeys } from '@backland/utils'; import { getTypeName } from '@backland/utils'; import { nonNullValues } from '@backland/utils'; import { __getCachedFieldInstance, createObjectType, isObject, parseField, parseObjectField } from './ObjectType'; import { AliasField } from './fields/AliasField'; import { LiteralField } from './fields/LiteralField'; import { E164_PHONE_REGEX } from './fields/PhoneField'; import { isHiddenFieldName } from './isHiddenFieldName'; import { parseTypeName } from './parseTypeName'; /** * Converts an object to a json-schema format * @param parentName * @param object * @param options */ export function objectToJSON(parentName, object) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { ignoreDefaultValues: true }; var definition; if (isObject(object)) { definition = object.definition; } else { // @ts-ignore definition = createObjectType(object).definition; } var description = isObject(object) ? object.description : undefined; var topProperties = {}; var required = []; var topJSON = { additionalProperties: false, properties: topProperties, required: required, title: parentName, type: 'object' }; if (description) { topJSON.description = description; } var composers = []; getKeys(definition).forEach(function (fieldName) { if (isHiddenFieldName(fieldName)) return; var field = definition[fieldName]; if (field.hidden) return; var parsedField = parseGraphQLField({ field: field, fieldName: fieldName, options: options, parentName: parentName }); if (parsedField.required) { required.push(fieldName); } topProperties[fieldName] = parsedField.jsonItem; composers.push.apply(composers, _toConsumableArray(parsedField.composers)); }); composers.forEach(function (composer) { var value = composer.compose(topProperties); setByPath(topProperties, composer.key, value); }); return topJSON; } function parseGraphQLField(params) { var field = params.field, fieldName = params.fieldName, parentName = params.parentName, options = params.options; field = parseField(field); var ignoreDefaultValues = options.ignoreDefaultValues; var _field = field, type = _field.type, list = _field.list, optional = _field.optional, description = _field.description, defaultValue = _field.defaultValue; var composers = []; nonNullValues({ type: type }); var required = !optional && type !== 'undefined'; var jsonItem = { // title, // will generate extra types in typescript }; if (ignoreDefaultValues) { defaultValue = undefined; } if (defaultValue !== undefined) { required = false; jsonItem.default = defaultValue; } if (description) { jsonItem.description = description; } if (type === 'array' || list) { var parsedListItem = parseGraphQLField({ field: type === 'array' ? parseObjectField(fieldName, field.def.of) : _objectSpread(_objectSpread({}, field), {}, { list: false }), fieldName: fieldName, options: options, parentName: parentName }); return { composers: composers, jsonItem: { items: parsedListItem.jsonItem, type: 'array' }, required: !optional }; } var typeParsers = { ID: function ID() { jsonItem.type = 'string'; jsonItem.tsType = 'ID'; }, alias: function alias() { var type = __getCachedFieldInstance(field); AliasField.assert(type); composers.push({ compose: function compose(parent) { if (typeof type.def === 'string') { return getByPath(parent, type.def); } else { return parseGraphQLField({ field: type.utils.fieldType.asFinalFieldDef, fieldName: fieldName, options: options, parentName: parentName }).jsonItem; } }, key: fieldName }); }, any: function any() { jsonItem.type = 'any'; }, array: function array() { // handled above }, boolean: function boolean() { jsonItem.type = 'boolean'; }, cursor: function cursor() { jsonItem.type = 'object'; jsonItem.tsType = 'Cursor'; }, date: function date() { jsonItem.type = 'string'; jsonItem.format = 'date-time'; jsonItem.tsType = 'Date'; }, email: function email() { jsonItem.type = 'string'; jsonItem.tsType = 'Email'; }, enum: function _enum() { var def = field.def; expectedType({ def: def }, 'array'); if (def.length == 1) { jsonItem.const = def[0]; } else { jsonItem.type = 'string'; jsonItem.enum = def; } }, float: function float() { jsonItem.type = 'number'; }, int: function int() { jsonItem.type = 'integer'; }, literal: function literal() { if (!LiteralField.isFinalTypeDef(field)) throw 'err'; var parsed = field.def['__o.proto__'] === 'String' ? field.def.value : BJSON.parse(field.def.value); jsonItem.const = parsed; var tsType = BJSON.stringify(parsed, { handler: function handler(_ref) { var _serializer$formatter; var serializer = _ref.serializer, value = _ref.value; var typeName = getTypeName(value); if (['Object', 'Array'].includes(typeName)) return; if (typeName === 'String') return JSON.stringify(value); if (typeName === 'Number') return value; return (serializer === null || serializer === void 0 ? void 0 : (_serializer$formatter = serializer.formatter) === null || _serializer$formatter === void 0 ? void 0 : _serializer$formatter.tsName(value)) || typeName; }, quoteValues: function quoteValues(str) { return "".concat(str); } }); jsonItem.tsType = tsType; }, meta: function meta() {}, null: function _null() { jsonItem.type = 'null'; }, object: function object() { var objectName = parseTypeName({ field: field, fieldName: '', parentName: parentName || '' }); Object.assign(jsonItem, objectToJSON(objectName, field.def, options), { title: '' }); }, phone: function phone() { Object.assign(jsonItem, { maxLength: 20, minLength: 10, pattern: E164_PHONE_REGEX.toString() }); jsonItem.tsType = 'Phone'; }, record: function record() { if (field.type !== 'record' || !field.def) { throw new RuntimeError("invalid record field definition.", { fieldDef: field }); } jsonItem.type = 'object'; }, string: function string() { jsonItem.type = 'string'; }, ulid: function ulid() { jsonItem.type = 'string'; jsonItem.tsType = 'Ulid'; }, undefined: function undefined() { jsonItem.type = 'null'; }, union: function union() { var def = field.def; expectedType({ def: def }, 'array'); jsonItem.anyOf = def.map(function (type) { return parseGraphQLField({ field: type, fieldName: fieldName, options: options, parentName: parentName }).jsonItem; }); }, unknown: function unknown() { jsonItem.type = 'any'; jsonItem.tsType = 'unknown'; } }; if (!typeParsers[type]) { throw new RuntimeError("invalid field type ".concat(type), { field: field }, 0, 20); } typeParsers[type](); return { composers: composers, jsonItem: jsonItem, required: required }; } //# sourceMappingURL=objectToJSON.js.map