UNPKG

uniforms-bridge-simple-schema

Version:
135 lines (134 loc) 4.89 kB
import { __rest } from "tslib"; import invariant from 'invariant'; import cloneDeep from 'lodash/cloneDeep'; import memoize from 'lodash/memoize'; // @ts-ignore -- This package _is_ typed, but not in all environments. import { SimpleSchema } from 'meteor/aldeed:simple-schema'; import { Bridge, joinName } from 'uniforms'; const propsToRemove = ['optional', 'uniforms', 'allowedValues']; export default class SimpleSchemaBridge extends Bridge { constructor({ schema }) { super(); this.schema = schema; // Memoize for performance and referential equality. this.getField = memoize(this.getField.bind(this)); this.getInitialValue = memoize(this.getInitialValue.bind(this)); this.getProps = memoize(this.getProps.bind(this)); this.getSubfields = memoize(this.getSubfields.bind(this)); this.getType = memoize(this.getType.bind(this)); } // TODO: Get rid of this `any`. getError(name, error) { const details = error === null || error === void 0 ? void 0 : error.details; if (!Array.isArray(details)) { return null; } return details.find(error => error.name === name) || null; } // TODO: Get rid of this `any`. getErrorMessage(name, error) { const scopedError = this.getError(name, error); return !scopedError ? '' : this.schema.messageForError(scopedError.type, scopedError.name, null, scopedError.details && scopedError.details.value); } // TODO: Get rid of this `any`. getErrorMessages(error) { if (!error) { return []; } const { details } = error; return Array.isArray(details) ? details.map(error => this.schema.messageForError(error.type, error.name, null, error.details && error.details.value)) : [error.message || error]; } getField(name) { const definition = this.schema.getDefinition(name); invariant(definition, 'Field not found in schema: "%s"', name); return definition; } getInitialValue(name) { const field = this.getField(name); const defaultValue = field.defaultValue; if (defaultValue !== undefined) { return cloneDeep(defaultValue); } if (field.type === Array) { const item = this.getInitialValue(joinName(name, '$')); if (item === undefined) { return []; } const length = field.minCount || 0; return Array.from({ length }, () => item); } if (field.type === Object) { const value = {}; this.getSubfields(name).forEach(key => { const initialValue = this.getInitialValue(joinName(name, key)); if (initialValue !== undefined) { value[key] = initialValue; } }); return value; } return undefined; } getProps(name) { const _a = this.getField(name), { type: fieldType } = _a, props = __rest(_a, ["type"]); props.required = !props.optional; if (typeof props.uniforms === 'function' || typeof props.uniforms === 'string') { props.component = props.uniforms; } else { Object.assign(props, props.uniforms); } let options = props.options; let allowedValues = props.allowedValues; if (typeof options === 'function') { options = options(); } if (!options && typeof allowedValues === 'function') { allowedValues = allowedValues(); } if (!options && Array.isArray(allowedValues)) { options = allowedValues.map(value => ({ value })); } else if (fieldType === Array) { try { const itemProps = this.getProps(`${name}.$`); if (itemProps.options) { options = itemProps.options; } } catch (_) { // It's fine. } } propsToRemove.forEach(key => { if (key in props) { delete props[key]; } }); return Object.assign(props, { options }); } getSubfields(name) { return this.schema.objectKeys(SimpleSchema._makeGeneric(name)); } getType(name) { return this.getField(name).type; } getValidator(options = { clean: true }) { const validator = this.schema.validator(options); return (model) => { try { // Clean mutate its argument. validator(options.clean ? cloneDeep(Object.assign({}, model)) : model); return null; } catch (error) { return error; } }; } }