dobo
Version:
DBMS for Bajo Framework
68 lines (66 loc) • 3.24 kB
JavaScript
/**
* Sanitize record to conform with the model's definition
*
* @method
* @async
* @param {Object} [record] - Record object
* @param {Array} [options.fields] - Array of field names to be picked
* @param {Object} [options.hidden=[]] - Additional fields to be hidden in addition the one defined in model
* @param {boolean} [options.forceNoHidden] - Force ALL fields to be picked, thus ignoring hidden fields
* @returns {Object}
*/
async function sanitizeRecord (record = {}, opts = {}) {
const { fields = [], hidden = [], forceNoHidden } = opts
const { isEmpty, map, without, isArray, isFunction, isString, get, cloneDeep } = this.app.lib._
const { fillObject } = this.app.lib.aneka
const { callHandler, format } = this.app.bajo
let allHidden = without([...this.hidden, ...hidden], 'id')
if (forceNoHidden === true) allHidden = []
else if (isArray(forceNoHidden)) allHidden = without(allHidden, ...forceNoHidden)
let newFields = [...fields]
if (isEmpty(newFields)) newFields = map(this.properties, prop => prop.name)
if (!newFields.includes('id')) newFields.unshift('id')
newFields = without(newFields, ...allHidden)
const body = fillObject(record, newFields, null)
const newRecord = await this.sanitizeBody({ body, partial: true, noDefault: true, allProps: true })
if (record._ref) newRecord._ref = cloneDeep(record._ref)
for (const key in newRecord) {
const prop = this.getProperty(key)
if (!prop) continue
const val = ['object', 'array'].includes(prop.type) ? cloneDeep(newRecord[key]) : newRecord[key]
if (isFunction(prop.getValue)) newRecord[key] = await prop.getValue.call(this, val, newRecord, opts)
else if (isString(prop.getValue)) newRecord[key] = await callHandler(this.plugin, this, val, newRecord, opts)
}
if (opts.fmt) {
newRecord._fmt = cloneDeep(newRecord)
delete newRecord._fmt._ref
for (const key in newRecord) {
const prop = this.getProperty(key)
if (!prop) continue
let value = ['object', 'array'].includes(prop.type) ? cloneDeep(newRecord[key]) : newRecord[key]
if (prop.values) {
const values = await this.buildPropValues(prop, opts)
if (isArray(value)) value = value.map(v => (values.find(opt => opt.value === v) ?? {}).text ?? v)
else value = (values.find(v => v.value === value) ?? {}).text ?? value
}
if (prop.format === false) newRecord._fmt[key] = value + ''
else if (isFunction(prop.format)) newRecord._fmt[key] = await prop.format.call(this, value, newRecord, opts)
else if (isString(prop.format)) newRecord._fmt[key] = await callHandler(this.plugin, this, value, newRecord, opts)
else {
const options = {
lang: get(opts, 'req.lang'),
datetime: {
dateStyle: get(opts, 'req.site.setting.sumba.dateStyle'),
timeStyle: get(opts, 'req.site.setting.sumba.timeStyle'),
timeZone: get(opts, 'req.site.setting.sumba.timeZone')
},
latitude: ['lat', 'latitude'].includes(key),
longitude: ['lon', 'lng', 'longitude'].includes(key)
}
newRecord._fmt[key] = format(value, prop.type, options)
}
}
}
return newRecord
}
export default sanitizeRecord