@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
JavaScript
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;
}
}