UNPKG

@backland/schema

Version:

TypeScript schema declaration and validation library with static type inference

228 lines (226 loc) 6.35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _exportNames = { FieldsTypeCache: true, FieldType: true, isFieldInstance: true }; exports.FieldsTypeCache = exports.FieldType = void 0; exports.isFieldInstance = isFieldInstance; var _utils = require("@backland/utils"); var _CircularDeps = require("../CircularDeps"); var _applyValidator = require("../applyValidator"); Object.keys(_applyValidator).forEach(function (key) { if (key === "default" || key === "__esModule") return; if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; if (key in exports && exports[key] === _applyValidator[key]) return; Object.defineProperty(exports, key, { enumerable: true, get: function () { return _applyValidator[key]; } }); }); var _ArrayFieldParse = require("./ArrayFieldParse"); var _FieldTypeErrors = require("./FieldTypeErrors"); var _Infer = require("./Infer"); const FieldsTypeCache = new Map(); exports.FieldsTypeCache = FieldsTypeCache; class FieldType { get definition() { return this.asFinalFieldDef; } constructor(config) { const { name, id, def, options = {} } = config; this.id = id; this.typeName = name; this.type = name; this.options = options; const defKeys = def ? Object.keys(def).sort() : undefined; if (defKeys !== null && defKeys !== void 0 && defKeys.length) { this.def = def; } if (id) { const existing = FieldsTypeCache.get(id); if (existing) { var _existing$defKeys; const existingKeys = (_existing$defKeys = existing.defKeys) === null || _existing$defKeys === void 0 ? void 0 : _existing$defKeys.join(', '); if (existing.fieldType.typeName !== this.typeName) { throw new Error(`Field with id "${id}" already registered with different type:\n "${(0, _utils.inspectObject)({ old: existing.fieldType.asFinalFieldDef, current: this.asFinalFieldDef }, { depth: 2 })}"`); } if ((defKeys === null || defKeys === void 0 ? void 0 : defKeys.join(', ')) !== existingKeys) { throw new Error(`Field with id "${id}" already registered with different fields:\n "${existingKeys}"`); } } FieldsTypeCache.set(id, { fieldType: this, defKeys }); } } validate(input) { try { this.parse(input); return true; } catch (e) { return false; } } is(input) { return this.validate(input); } describe = description => { this.description = description; return this; }; describeField = () => { return this.asFinalFieldDef; }; toOptional() { // @ts-ignore this.optional = true; return this; } toRequired() { // @ts-ignore this.optional = false; return this; } toList(options) { // @ts-ignore this.list = true; if (options && typeof options === 'object') { this.options = { ...this.options, ...options }; } return this; } setDefaultValue(value) { // @ts-ignore this.defaultValue = value; return this; } applyParser = parser => { return (input, _options) => { let options = {}; if (typeof _options === 'function') { options = { customErrorMessage: _options }; } if (typeof _options === 'string') { options = { customErrorMessage: _options }; } if (typeof _options === 'object') { options = _options; } const { customErrorMessage: customMessage, includeHidden = true } = options; // keep it secret if (this.hidden && !includeHidden) return undefined; if (parser.preParse) { input = parser.preParse(input); } if ((input === undefined || input === null) && this.defaultValue !== undefined) { input = this.defaultValue; } if (this.type === 'null' && input === undefined) { return null; } if (this.type !== 'null' && input === null && this.optional) { return undefined; } if (input === undefined && this.optional) { return undefined; } if (input === undefined && !this.optional) { throw (0, _FieldTypeErrors.createFieldTypeError)('requiredField'); } if (this.asFinalFieldDef.list) { return (0, _ArrayFieldParse.arrayFieldParse)({ arrayOptions: {}, // since is the shot definition (list:true) there is no options input, parser: input => parser.parse(input, options), parserOptions: options }); } try { return parser.parse(input, options); } catch (originalError) { if (!customMessage && (0, _FieldTypeErrors.isFieldError)(originalError)) { throw originalError; } throw (0, _applyValidator.parseValidationError)(input, customMessage, originalError); } }; }; get asFinalFieldDef() { const res = { def: this.def, defaultValue: this.defaultValue, description: this.description, hidden: this.hidden, list: this.list, optional: this.optional, type: this.type }; Object.entries(res).forEach(([k, v]) => { if (v === undefined || v === false) { delete res[k]; } }); return res; } __isFieldType = true; static create(..._args) { throw new Error('not implemented in abstract class.'); } clone = () => { const { def, defaultValue, ...rest } = this.asFinalFieldDef; let field; if (rest.type === 'literal') { field = { ...(0, _utils.simpleObjectClone)(rest), def, defaultValue }; } else { field = (0, _utils.simpleObjectClone)(rest); if (def !== undefined) { field.def = (0, _utils.simpleObjectClone)(def); } if (defaultValue !== undefined) { field.defaultValue = (0, _utils.simpleObjectClone)(def); } } return _CircularDeps.CircularDeps.fieldInstanceFromDef(field); }; } exports.FieldType = FieldType; function isFieldInstance(t) { return (t === null || t === void 0 ? void 0 : t.__isFieldType) === true; } //# sourceMappingURL=FieldType.js.map