happn-commons
Version:
109 lines (108 loc) • 3.3 kB
JavaScript
const _ = require('lodash');
module.exports = class BaseBuilder {
constructor(options) {
this.options = options;
this.__data = {};
this.__typeKeys = Object.keys(BaseBuilder.Types);
}
static get Types() {
return {
STRING: 0,
NUMERIC: 1,
OBJECT: 2,
DATE: 3,
INTEGER: 4,
ARRAY: 5,
BOOLEAN: 6,
};
}
buildValue(prop) {
if (prop == null) return prop;
if (Array.isArray(prop))
return prop.map((value) => {
return this.buildValue(value);
});
return typeof prop.build === 'function' ? prop.build() : prop;
}
build(obj) {
const fieldNames = Object.keys(this.__data);
if (this.__required) this.checkRequired();
return fieldNames.reduce((json, key) => {
return _.set(json, key, this.buildValue(this.__data[key]));
}, obj || {});
}
push(fieldName, value, type, max) {
if (type != null) this.checkType(value, type, fieldName);
if (!Array.isArray(this.__data[fieldName])) this.__data[fieldName] = [];
if (this.__data[fieldName].length === max)
throw new Error(`maximum allowed items for field[${fieldName}]`);
this.__data[fieldName].push(value);
return this;
}
set(fieldName, value, type) {
if (type != null) this.checkType(value, type, fieldName);
if (fieldName === '.') {
this.__data = value;
} else {
this.__data[fieldName] = value;
}
return this;
}
required(arrPropertyNames) {
if (!Array.isArray(arrPropertyNames))
throw new Error(`argument [arrPropertyNames] at position 0 must be a string array`);
this.__required = arrPropertyNames;
}
checkRequired() {
for (let fieldName of this.__required) {
if (_.get(this.__data, fieldName) == null)
throw new Error(`required field [${fieldName}] cannot be null`);
}
}
checkType(value, type, fieldName) {
const typeName = this.__typeKeys.find((typeKey) => {
return BaseBuilder.Types[typeKey] === type;
});
if (!typeName) throw new Error(`unknown type [${type}] specified for field [${fieldName}]`);
const errMsg = `[${fieldName}] must be of type [${typeName}]`;
switch (type) {
case BaseBuilder.Types.ARRAY:
if (!Array.isArray(value)) throw new Error(errMsg);
break;
case BaseBuilder.Types.OBJECT:
if (typeof value !== 'object') throw new Error(errMsg);
break;
case BaseBuilder.Types.STRING:
if (typeof value !== 'string') throw new Error(errMsg);
break;
case BaseBuilder.Types.NUMERIC:
if (typeof this.tryParseFloat(value) !== 'number') throw new Error(errMsg);
break;
case BaseBuilder.Types.NUMBER:
if (!Number.isInteger(this.tryParseFloat(value))) throw new Error(errMsg);
break;
case BaseBuilder.Types.DATE:
if (!this.tryParseDate(value)) throw new Error(errMsg);
break;
case BaseBuilder.Types.BOOLEAN:
if (value !== true && value !== false) throw new Error(errMsg);
break;
default:
break;
}
}
tryParseFloat(value) {
try {
return parseFloat(value);
} catch (e) {
return value;
}
}
tryParseDate(value) {
try {
return new Date(value);
} catch (e) {
return false;
}
}
};