fogine/couchbase-odm

View on GitHub
lib/key/refDocKey.js

Summary

Maintainability
A
1 hr
Test Coverage
const util     = require('util');
const Promise  = require("bluebird");
const Key      = require("./key.js");
const _        = require('lodash');
const KeyError = require("../error/keyError.js");


module.exports = RefDocKey;

/**
 *
 * RefDocKey
 *
 * @constructor
 * @extends Key
 *
 * @throws KeyError
 *
 * @param {Object}         options
 * @param {string|integer} options.id
 * @param {string}         options.prefix
 * @param {string}         options.postfix=""
 * @param {string}         options.delimiter="_"
 * @param {Boolean}        options.caseSensitive=true
 * @param {Array}          options.ref=[] - array of document's properties from refDoc definition object
 */
function RefDocKey(options) {
    Key.call(this, options);

    /**
     * Array ref
     * properties which make up index (= refDoc key)
     * = property names from schema definition
     * eg.: username, email etc.
     */
    this._setRef(options.ref || []);
}

util.inherits(RefDocKey, Key);
RefDocKey.prototype.super = Key.prototype;

/**
 * @throws {KeyError}
 * @private
 * @param Array ref
 *
 */
RefDocKey.prototype._setRef = function(ref) {
    if (!Array.isArray(ref) || !ref.length) {//TODO check this in schema validation function
        throw new KeyError("RefDocKey - index reference type/s must be non-empty Array");
    }

    this.ref = ref;
};

/**
 * @param string|Array id
 *
 */
RefDocKey.prototype.setId = function(id) {
    if (id instanceof Array) {
        id = id.join(this.delimiter);
    }

    this.super.setId.call(this, id);
};

/**
 * @typedef RefDocKeyOptionsObject
 * @type Object
 * @property {mixed} id - dynamic part of a key
 * @property {string} prefix - static string value preceding **`id`** value
 * @property {string} postfix - static string value which comes after **`id`** value
 * @property {string} delimiter - the key string `User_username_happiecat` - has the **`_`** character as delimiter value
 * @property {boolean} caseSensitive - determines whether **`id`** value is case sensitive or not
 * @property {Array} ref - array of document's properties from refDoc definition object
 */

/**
 * @return {RefDocKeyOptionsObject}
 */
RefDocKey.prototype.getOptions = function() {
    let options = this.super.getOptions.call(this);
    options.ref = _.cloneDeep(this.ref);
    return options;
};

/**
 * generates new key
 * This method is called before inserting new document to a bucket
 * The method must return a prosime
 *
 * @param Instance instance
 * @function
 * @return Promise<RefDocKey>
 */
RefDocKey.prototype.generate = Promise.method(function(instance) {

    let id = "";
    let instanceData = instance.getData();

    for (let i = 0, len = this.ref.length; i < len; i++) {
        let propertyPath = this.ref[i];

        let propValue = _.get(instanceData, propertyPath);
        if (propValue === null || propValue === undefined || propValue === "") {
            return Promise.reject(new KeyError("RefDocKey - Failed to get index value from data of Instance"));
        }

        if (id !== "") {
            id += this.delimiter;
        }
        id += (this.caseSensitive === false ? propValue.toLowerCase() : propValue);
    }
    this.setId(id);
    return this;
});


/**
 * @param {string} key - whole key of a document
 *
 * @return {RefDocKey} - self
 */
RefDocKey.prototype.parse = function(key) {
    if (typeof key !== 'string') {
        throw new Error('Expected `key` to be a string but got ' + typeof key);
    }
    let prePart = this.prefix + this.delimiter + this.ref.join(this.delimiter) + this.delimiter;
    let postPart = this.delimiter + this.postfix;
    let till = undefined;
    if (this.postfix.length) {
        till = -postPart.length;
    }

    this.setId(key.slice(prePart.length, till));
    return this;
};

/**
 * returns the key
 *
 * @return string
 */
RefDocKey.prototype.toString = function() {
    let key = this.prefix + this.delimiter + this.ref.join(this.delimiter) + this.delimiter + this.id;
    if (this.postfix) {
        key += this.delimiter + this.postfix;
    }
    return key;
};

/**
 * @return string
 */
Object.defineProperty(RefDocKey.prototype, 'inspect', {
    writable: true,
    value: function() {
        return '[object RefDocKey: "' + this.toString() + '" ]';
    }
});