UNPKG

@sprucelabs/schema

Version:

Static and dynamic binding plus runtime validation and transformation to ensure your app is sound. 🤓

80 lines (79 loc) • 2.77 kB
import AbstractEntity from './AbstractEntity.js'; import SpruceError from './errors/SpruceError.js'; import FieldFactory from './factories/FieldFactory.js'; import normalizeFieldValue from './utilities/normalizeFieldValue.js'; export default class DynamicSchemaEntityImplementation extends AbstractEntity { constructor(schema, values) { super(schema); this.values = {}; if (!schema.dynamicFieldSignature) { throw new Error(`DynamicSchemaEntity only works with with schemas with dynamicFieldSignature set.`); } this.values = values || {}; this.dynamicField = FieldFactory.Field('dynamicField', schema.dynamicFieldSignature); } set(fieldName, value, options = {}) { const localValue = normalizeFieldValue(this.schemaId, this.name, {}, this.dynamicField, value, options); this.values[fieldName] = localValue; return this; } validate(options = {}) { const errors = []; const originalName = this.dynamicField.name; this.getNamedFields(options).forEach((namedField) => { const { name, field } = namedField; const value = this.values[name]; field.name = name; const fieldErrors = field.validate(value, { schemasById: {}, }); if (fieldErrors.length > 0) { errors.push(...fieldErrors); } }); this.dynamicField.name = originalName; if (errors.length > 0) { throw new SpruceError({ code: 'VALIDATION_FAILED', schemaId: this.schemaId, schemaName: this.name, errors, }); } } isValid(options = {}) { try { this.validate(options); return true; } catch { return false; } } get(fieldName, options) { const value = this.values[fieldName]; return normalizeFieldValue(this.schemaId, this.name, {}, this.dynamicField, value, options || {}); } getValues(options) { const values = {}; this.getNamedFields().forEach((namedField) => { const { name } = namedField; const value = this.get(name, options); //@ts-ignore values[name] = value; }); return values; } setValues(values) { this.values = { ...this.values, ...values }; return this; } getNamedFields(options = {}) { const namedFields = []; const { fields = Object.keys(this.values) } = options; fields.forEach((name) => { namedFields.push({ name, field: this.dynamicField }); }); return namedFields; } }