UNPKG

@backland/schema

Version:

TypeScript schema declaration and validation library with static type inference

153 lines 6.11 kB
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); } import { customError, EmailRegex, entries, getTypeName, IndexCursor, inspectObject, isPlainObject, joinPathsCamelCase, stringCase } from '@backland/utils'; import { CircularDeps } from './CircularDeps'; import { createType } from './GraphType/GraphType'; import { createObjectType } from './ObjectType'; import { ULID_REGEX } from './fields/UlidField'; var record = CircularDeps.record({ keyType: 'string', type: 'any' }); export var JSONFieldCase = Object.keys(stringCase).concat('camelCase'); export var JSONToSchemaOptions = createObjectType({ fieldCase: { enum: JSONFieldCase, optional: true }, examples: 'boolean?', name: 'string?', json: { record: { type: 'any', keyType: 'string' } } }); export function jsonToType(init) { var { name } = init; var definition = valueToTypeDef(_objectSpread(_objectSpread({}, init), {}, { value: init.json })); var type = createType(definition); if (name) { type.identify(name); } return type; } export function jsonToSchemaDefinition(options) { record.parse(options.json, 'jsonToSchema: Invalid input.'); var res = valueToTypeDef(_objectSpread(_objectSpread({}, options), {}, { value: options.json })); if ('object' in res && typeof res.object === 'object') { return res.object; } throw customError({ message: 'Invalid field', details: res, stackFrom: jsonToSchemaDefinition }); } export function isCursorString(value) { if (!value || typeof value !== 'string') return false; try { IndexCursor.parse(value, { destination: 'document' }); return true; } catch (e) { return false; } } var phoneType = CircularDeps.phone({}); export var valuesToBacklandTypeRecord = { null: value => value === null, undefined: function (_undefined) { function undefined(_x) { return _undefined.apply(this, arguments); } undefined.toString = function () { return _undefined.toString(); }; return undefined; }(value => value === undefined), string: value => typeof value === 'string', boolean: value => typeof value === 'boolean', float: value => getTypeName(value) === 'Number' && !!"".concat(value).match(/^\d*\.\d*$/), int: value => getTypeName(value) === 'Number' && !!"".concat(value).match(/^\d*$/), array: Array.isArray, object: value => isPlainObject(value), cursor: isCursorString, date: value => getTypeName(value) === 'Date', email: value => Boolean(value && typeof value === 'string' && EmailRegex.test(value)), ID: value => !!value && typeof value === 'string' && ULID_REGEX.test(value), phone: phoneType.is, record: value => !!value && typeof value === 'object' && !isPlainObject(value), ulid: value => typeof value === 'string' && ULID_REGEX.test(value), union: () => false, unknown: () => false, alias: () => false, any: () => false, literal: () => false, meta: () => false, enum: () => false }; export var backlandValueTypeCheckEntries = entries(valuesToBacklandTypeRecord); export function valueToTypeDef(options) { var { fieldCase = 'keep', examples, value } = options; var typename = function iifeTypename() { var _backlandValueTypeChe; return ((_backlandValueTypeChe = backlandValueTypeCheckEntries.find(_ref => { var [, check] = _ref; return check(value); })) === null || _backlandValueTypeChe === void 0 ? void 0 : _backlandValueTypeChe[0]) || 'unknown'; }(); var field = { [typename]: {} }; if (examples && typename !== 'object') { field.description = "Eg: ".concat(inspectObject(value).trim()); } if ('array' in field) { var child = value.map(el => { return valueToTypeDef(_objectSpread(_objectSpread({}, options), {}, { value: el })); }); field.array.of = function iife() { if (!child.length) return 'unknown'; return child.length === 1 ? child[0] : { union: child }; }(); } if (typename === 'object') { field[typename] = entries(value).reduce((acc, _ref2) => { var [key, subValue] = _ref2; if (fieldCase) { if (fieldCase === 'camelCase') { key = joinPathsCamelCase(key); } else { key = stringCase[fieldCase](key); } } return _objectSpread(_objectSpread({}, acc), {}, { [key]: valueToTypeDef(_objectSpread(_objectSpread({}, options), {}, { value: subValue })) }); }, {}); } return field; } //# sourceMappingURL=jsonToType.js.map