@backland/schema
Version:
TypeScript schema declaration and validation library with static type inference
439 lines (435 loc) • 17.4 kB
JavaScript
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = 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 _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure 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 _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; }
function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
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); }
import { RuntimeError } from '@backland/utils';
import { isProduction } from '@backland/utils';
import { getKeys } from '@backland/utils';
import { getTypeName } from '@backland/utils';
import { inspectObject } from '@backland/utils';
import { GraphType } from './GraphType/GraphType';
import { isObject } from './ObjectType';
import { fieldInstanceFromDef } from './fieldInstanceFromDef';
import { isFieldInstance } from './fields/FieldType';
import { LiteralField } from './fields/LiteralField';
import { createEmptyMetaField, isMetaField, objectMetaFieldKey } from './fields/MetaFieldField';
import { types } from './fields/fieldTypes';
import { isStringFieldDefinition, parseStringDefinition } from './parseStringDefinition';
export var _parserHooks = [];
export function setParserHook(hook) {
_parserHooks.push(hook);
function remove() {
_parserHooks.find(function (el, index) {
if (el !== hook) return false;
delete _parserHooks[index];
return true;
});
return _parserHooks;
}
return remove;
}
export function parseObjectField(fieldName, definition) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
var _ref = options === true ? {
returnInstance: true
} : options,
returnInstance = _ref.returnInstance,
asString = _ref.asString,
deep = _ref.deep,
omitMeta = _ref.omitMeta;
if (deep !== null && deep !== void 0 && deep.omitMeta) omitMeta = true;
if (deep !== null && deep !== void 0 && deep.asString) asString = true;
var parsed = parseFieldDefinitionConfig(definition, {
deep: deep,
omitMeta: omitMeta
});
if (_parserHooks.length) {
_parserHooks.forEach(function (cb) {
return cb(parsed);
});
}
if (typeof parsed === 'string') {
return parsed;
} else {
if (asString) return parsed;
}
var instanceFromDef = fieldInstanceFromDef(parsed);
setCachedFieldInstance(parsed, instanceFromDef);
if (instanceFromDef.def) {
parsed.def = instanceFromDef.def;
}
if (returnInstance) {
return instanceFromDef;
}
if (parsed) return parsed;
throw new RuntimeError("field \"".concat(fieldName, "\": invalid definition."), {
definition: definition,
parsed: parsed
});
}
export function parseField(definition) {
return parseObjectField('__parseField__', definition);
}
var stringifiableDefKeys = new Set(['type', 'list', 'optional' //
]);
export function parseFieldDefinitionConfig(definition, options) {
var _ref2 = options || {},
deep = _ref2.deep,
asString = _ref2.asString;
if (deep !== null && deep !== void 0 && deep.asString) {
asString = true;
}
function _parseField() {
if (LiteralField.isFinalTypeDef(definition)) {
return {
def: definition.def,
defaultValue: definition.defaultValue,
description: definition.description,
hidden: definition.hidden,
list: !!definition.list,
optional: !!definition.optional,
type: 'literal'
};
}
if (GraphType.is(definition)) {
var def = parseFieldDefinitionConfig(definition.definition, {
deep: deep
});
def.hidden = def.hidden || definition.hidden;
return def;
}
if (GraphType.isTypeDefinition(definition)) {
var _definition$list = definition.list,
list = _definition$list === void 0 ? false : _definition$list,
_definition$optional = definition.optional,
optional = _definition$optional === void 0 ? false : _definition$optional,
description = definition.description,
defaultValue = definition.defaultValue,
hidden = definition.hidden,
_definition$type$defi = definition.type.definition,
type = _definition$type$defi.type,
_def = _definition$type$defi.def,
_defaultValue = _definition$type$defi.defaultValue;
return {
def: _def,
defaultValue: defaultValue === undefined ? _defaultValue : defaultValue,
description: description,
hidden: hidden,
list: list,
optional: optional,
type: type
};
}
if (isStringFieldDefinition(definition)) {
return parseStringDefinition(definition);
}
if (isFieldInstance(definition)) {
return definition.asFinalFieldDef;
}
if (isFinalFieldDefinition(definition)) {
if (definition.type === 'object') {
if (_typeof(definition.def) !== 'object' || !definition.def) {
throw new RuntimeError("Missing def for object field.", {
definition: definition
});
}
if (isObject(definition.def)) {
definition.def = definition.def.definition;
} else {
definition.def = parseObjectDefinition(definition.def, {
deep: deep
}).definition;
}
}
if (definition.type === 'union') {
var isOptionalUnion = definition.optional;
definition.def = definition.def.map(function (el) {
var parsed = parseFieldDefinitionConfig(el, {
deep: deep
});
if (parsed.optional) isOptionalUnion = true;
return parsed;
});
definition.optional = isOptionalUnion;
}
if (definition.type === 'alias') {
if (_typeof(definition.def) === 'object') {
definition.def.type = parseFieldDefinitionConfig(definition.def.type, {
deep: deep
});
validFlattenDefinitionKeysList.forEach(function (k) {
if (definition[k] !== undefined) {
// @ts-ignore
definition.def.type[k] = definition[k];
}
});
}
}
return definition;
}
if (isListDefinition(definition)) {
var parsed = parseFieldDefinitionConfig(definition[0], {
deep: deep
});
parsed.list = true;
parsed.optional = false;
return parsed;
}
if (isObject(definition)) {
return {
def: deep ? parseObjectDefinition(definition.definition, {
deep: deep
}) : definition.definition,
defaultValue: undefined,
description: definition.description,
hidden: definition.hidden,
type: 'object'
};
}
if (isObjectAsTypeDefinition(definition)) {
return {
def: deep ? parseObjectDefinition(definition.type.definition, {
deep: deep
}) : definition.type.definition,
defaultValue: undefined,
description: definition.type.description,
hidden: definition.hidden || definition.type.hidden,
list: !!definition.list,
name: definition.name,
optional: !!definition.optional,
type: 'object'
};
}
var keyObjectDefinition = parseFlattenFieldDefinition(definition, {
deep: deep
});
if (keyObjectDefinition) {
return keyObjectDefinition;
}
throw new Error("Unexpected field definition: ".concat(inspectObject(definition)));
}
try {
var result = _parseField();
if (definition && _typeof(definition) === 'object') {
if ('name' in definition && definition.name && typeof definition.name === 'string') {
result.name = definition.name;
}
}
var hasNotStringifiableKeys = false;
var hasDef = false;
Object.entries(result).forEach(function (_ref3) {
var _ref4 = _slicedToArray(_ref3, 2),
k = _ref4[0],
v = _ref4[1];
if (v === undefined || v === false) {
delete result[k]; // deleting nullish values
return;
}
if (k === 'def') {
hasDef = true;
return;
}
if (hasNotStringifiableKeys || !stringifiableDefKeys.has(k)) {
hasNotStringifiableKeys = true;
}
});
if (asString && !hasNotStringifiableKeys) {
var type = result.type,
list = result.list,
optional = result.optional,
def = result.def;
var _type = type;
if (list) _type = "[".concat(_type, "]");
if (optional) _type = "".concat(_type, "?");
if (hasDef) {
// @ts-ignore
return _defineProperty({}, _type, def);
} else {
// @ts-ignore
return _type;
}
}
// return simpleObjectClone(result);
return result;
} catch (e) {
debugger;
console.error(e, definition);
throw e;
}
}
export function parseObjectDefinition(input) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var deep = options.deep,
omitMeta = options.omitMeta;
if (deep !== null && deep !== void 0 && deep.omitMeta) {
omitMeta = true;
}
var result = {};
var meta = undefined;
var keys = getKeys(input);
keys.forEach(function (fieldName) {
try {
var _field = input[fieldName];
if (isMetaField(_field, fieldName)) {
return meta = _field;
}
var cached = hasCachedFieldInstance(_field);
if (cached) {
return result[fieldName] = cached;
}
return result[fieldName] = parseObjectField(fieldName, _field, {
deep: deep
});
} catch (err) {
debugger;
throw new RuntimeError("Failed to process object field \"".concat(fieldName, "\":\n").concat(err.message), {
err: err.stack,
input: input
});
}
});
meta = meta || createEmptyMetaField();
if (!omitMeta) {
result[objectMetaFieldKey] = meta;
}
return {
definition: result,
meta: meta
};
}
function isFinalFieldDefinition(input) {
return typeof (input === null || input === void 0 ? void 0 : input.type) === 'string';
}
function isListDefinition(input) {
if (Array.isArray(input) && input.length === 1) return true;
if (!isProduction()) {
var _input$forEach;
// verify against old enum definition
input === null || input === void 0 ? void 0 : (_input$forEach = input.forEach) === null || _input$forEach === void 0 ? void 0 : _input$forEach.call(input, function (el) {
if (typeof el === 'string' && !isStringFieldDefinition(el)) {
throw new Error("Plain array is used only for union definitions.\n" + " \"".concat(el, "\" is not valid as union item.\n") + " You can use { enum: ['".concat(el, "'] } instead of ['").concat(el, "']."));
}
});
}
return false;
}
/**
* Object as field['type'] is deprecated
* @param input
*/
export function isObjectAsTypeDefinition(input) {
return input && _typeof(input) === 'object' && isObject(input.type);
}
var validFlattenDefinitionKeys = {
defaultValue: 'any',
description: 'string',
hidden: 'boolean',
list: 'boolean',
name: 'string',
optional: 'boolean'
};
var validFlattenDefinitionKeysList = getKeys(validFlattenDefinitionKeys);
export function parseFlattenFieldDefinition(input) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var deep = options.deep;
if (getTypeName(input) !== 'Object') return false;
if (input.type !== undefined) return false;
var type;
var def;
for (var k in input) {
var valueOfDefOrOptionalOrListOrDescription = input[k];
if (types[k]) {
type = k;
def = valueOfDefOrOptionalOrListOrDescription;
if (k !== 'object' && def && _typeof(def) === 'object') {
for (var defKey in def) {
if (defKey === 'def' || validFlattenDefinitionKeys[defKey]) {
console.warn("using field def as type definition?\n", {
def: def,
type: k
});
return false;
}
}
}
} else {
if (valueOfDefOrOptionalOrListOrDescription !== undefined) {
var acceptAny = validFlattenDefinitionKeys[k] === 'any';
if (!acceptAny &&
// checking if the de `optional` or `list` or `description`
// has the expected types
_typeof(valueOfDefOrOptionalOrListOrDescription) !== validFlattenDefinitionKeys[k]) {
return false;
}
}
}
}
var description = input.description,
_input$optional = input.optional,
optional = _input$optional === void 0 ? false : _input$optional,
_input$list = input.list,
list = _input$list === void 0 ? false : _input$list,
defaultValue = input.defaultValue,
name = input.name,
hidden = input.hidden;
return parseFieldDefinitionConfig({
def: def,
defaultValue: defaultValue,
description: description,
hidden: hidden,
list: list,
name: name,
optional: optional,
type: type
}, {
deep: deep
});
}
export var CACHED_FIELD_INSTANCE_KEY = '__cachedFieldInstance';
export function __getCachedFieldInstance(field) {
if (field !== null && field !== void 0 && field[CACHED_FIELD_INSTANCE_KEY]) {
return field[CACHED_FIELD_INSTANCE_KEY];
}
var parsed = parseFieldDefinitionConfig(field);
var instanceFromDef = fieldInstanceFromDef(parsed);
setCachedFieldInstance(parsed, instanceFromDef);
return instanceFromDef;
}
function hasCachedFieldInstance(field) {
return !!(field !== null && field !== void 0 && field[CACHED_FIELD_INSTANCE_KEY]) ? field : null;
}
function setCachedFieldInstance(field, instanceFromDef) {
if (hasCachedFieldInstance(field)) return;
Object.defineProperty(field, CACHED_FIELD_INSTANCE_KEY, {
configurable: false,
enumerable: false,
value: instanceFromDef,
writable: false
});
}
export function deleteCachedFieldInstance(def) {
if (!def || _typeof(def) !== 'object') return def;
var _ref6 = def,
_ = _ref6[CACHED_FIELD_INSTANCE_KEY],
rest = _objectWithoutProperties(_ref6, [CACHED_FIELD_INSTANCE_KEY].map(_toPropertyKey));
return rest;
// if (currentDepth > depth) return def;
//
// Object.entries(rest).reduce((acc, [key, value]) => {
// return {
// ...acc,
// [key]: value,
// };
// }, rest);
//
// return rest;
}
//# sourceMappingURL=parseObjectDefinition.js.map