/** * The key must be composed of alpha characters with periods seperating them. */ const KEY_REGEX = /^(?:[A-Za-z][A-Za-z\.]*[A-Za-z])?(?:[A-Za-z]*)$/; /** * Allows metadata properties to be set/unset from specific models. It is the * expecatation of this API that the metadata field is either accessed later * directly, or accessed as a result of another database load rather than * this service providing an interface to do so. * * @class MetadataService */ class MetadataService { /** * Parses a key by ensuring that if it is either a string, or an array with * only characters defined in the `KEY_REGEX` * * @static * @param {String|Array} key * @returns {String} string form of the key * * @memberOf Metadata */ static parseKey(key) { if (Array.isArray(key)) { key = key.join('.'); } if ((typeof key !== 'string') || !KEY_REGEX.test(key) || key.length === 0) { throw new Error(`${key} is not valid, only a-zA-Z. allowed`); } return ['metadata', key].join('.'); } /** * Sets an object on the metadata field of an object. An example could be: * * @example * const MetadataService = require('services/metadata'); * const CommentModel = require('models/comment'); * * // Sets the property `loaded` on the comment with `id=1`. * MetadataService.set(CommentModel, '1', 'loaded', true); * * @static * @param {mongoose.Model} model the mongoose model for the object * @param {String} id the value for the field `id` of the model * @param {String|Array} key key for the metadata field * @param {any} value javascript object to set the value of the metadata to * @returns {Promise} resolves when the update is complete * * @memberOf Metadata */ static async set(model, id, key, value) { key = MetadataService.parseKey(key); return model.update({id}, { $set: { [key]: value } }); } /** * Removes the value for the metadata field as the specific key. * * @example * const MetadataService = require('services/metadata'); * const CommentModel = require('models/comment'); * * // Removes the property `loaded` on the comment with `id=1`. * MetadataService.unset(CommentModel, '1', 'loaded'); * * @static * @param {mongoose.Model} model the mongoose model for the object * @param {String} id the value for the field `id` of the model * @param {String|Array} key key for the metadata field * @returns * * @memberOf Metadata */ static async unset(model, id, key) { key = MetadataService.parseKey(key); return model.update({id}, { $unset: {[key]: ''} }); } } module.exports = MetadataService;