all files / lib/offshore/core/ index.js

97.01% Statements 65/67
90.91% Branches 40/44
100% Functions 5/5
98.36% Lines 60/61
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148                        410×     410× 410× 410×   410×     410× 410× 410×       410× 410× 410×   410×   410×       410×   410×                 410×   410×     410×     410×     410× 410× 410× 410×     410×   410× 410× 407×     410×     410× 410× 410×     410× 2230× 403×         410×     410×     410× 411× 411×       410×                               410×       401× 398×     398× 194×       204× 204×        
/**
 * Dependencies
 */
 
var _ = require('lodash');
var schemaUtils = require('../utils/schema');
var COLLECTION_DEFAULTS = require('../collection/defaults');
var Model = require('../model');
var Cast = require('./typecast');
var Schema = require('./schema');
var Validator = require('./validations');
var Transformer = require('./transformations');
var hasOwnProperty = require('../utils/helpers').object.hasOwnProperty;
 
/**
 * Core
 *
 * Setup the basic Core of a collection to extend.
 */
 
var Core = module.exports = function(options) {
 
  options = options || {};
 
  // Set Defaults
  this.adapter = this.adapter || {};
  this._attributes = this.attributes;
  this.connections = this.connections || {};
 
  this.defaults = _.merge(COLLECTION_DEFAULTS, this.defaults);
 
  // Construct our internal objects
  this._cast = new Cast();
  this._schema = new Schema(this);
  this._validator = new Validator(this);
 
  // Normalize attributes, extract instance methods, and callbacks
  // Note: this is ordered for a reason!
  this._callbacks = schemaUtils.normalizeCallbacks(this);
  this._instanceMethods = schemaUtils.instanceMethods(this.attributes);
  this._attributes = schemaUtils.normalizeAttributes(this._attributes);
 
  this.hasSchema = Core._normalizeSchemaFlag.call(this);
 
  this.migrate = Object.getPrototypeOf(this).hasOwnProperty('migrate') ?
    this.migrate : this.defaults.migrate;
 
  // Initalize the internal values from the Collection
  Core._initialize.call(this, options);
 
  return this;
};
 
/**
 * Initialize
 *
 * Setups internal mappings from an extended collection.
 */
 
Core._initialize = function(options) {
  var self = this;
 
  options = options || {};
 
  // Extend a base Model with instance methods
  this._model = new Model(this, this._instanceMethods);
 
  // Cache the attributes from the schema builder
  var schemaAttributes = this.offshore.schema[this.identity].attributes;
 
  // Remove auto attributes for validations
  var _validations = _.clone(this._attributes);
  if (this.autoPK) delete _validations.id;
  if (this.autoCreatedAt) delete _validations.createdAt;
  if (this.autoUpdatedAt) delete _validations.updatedAt;
 
  // If adapter exposes any reserved attributes, pass them to the schema
  var connIdx = Array.isArray(this.connection) ? this.connection[0] : this.connection;
 
  var adapterInfo = {};
  if (this.connections[connIdx] && this.connections[connIdx]._adapter) {
    adapterInfo = this.connections[connIdx]._adapter;
  }
 
  var reservedAttributes = adapterInfo.reservedAttributes || {};
 
  // Initialize internal objects from attributes
  this._schema.initialize(this._attributes, this.hasSchema, reservedAttributes);
  this._cast.initialize(this._schema.schema);
  this._validator.initialize(_validations, this.types, this.defaults.validations, this.offshore.schema[this.identity].criteria);
 
  // Set the collection's primaryKey attribute
  Object.keys(schemaAttributes).forEach(function(key) {
    if (hasOwnProperty(schemaAttributes[key], 'primaryKey') && schemaAttributes[key].primaryKey) {
      self.primaryKey = key;
    }
  });
 
  // Build Data Transformer
  this._transformer = new Transformer(schemaAttributes, this.offshore.schema);
 
  // Transform Schema
  this._schema.schema = this._transformer.serialize(this._schema.schema, 'schema');
 
  // Add this collection to the connection
  Object.keys(this.connections).forEach(function(conn) {
    self.connections[conn]._collections = self.connections[conn]._collections || [];
    self.connections[conn]._collections.push(self.identity);
  });
 
  // Remove remnants of user defined attributes
  delete this.attributes;
};
 
/**
 * Normalize Schema Flag
 *
 * Normalize schema setting by looking at the model first to see if it is defined, if not look at
 * the connection and see if it's defined and if not finally look into the adapter and check if
 * there is a default setting. If not found anywhere be safe and set to true.
 *
 * @api private
 * @return {Boolean}
 */
 
Core._normalizeSchemaFlag = function() {
 
  // If schema is defined on the collection, return the value
  if (hasOwnProperty(Object.getPrototypeOf(this), 'schema')) {
    return Object.getPrototypeOf(this).schema;
  }
 
  // Grab the first connection used
  if (!this.connection || !Array.isArray(this.connection)) return true;
  var connection = this.connections[this.connection[0]];
 
  // Check the user defined config
  if (hasOwnProperty(connection, 'config') && hasOwnProperty(connection.config, 'schema')) {
    return connection.config.schema;
  }
 
  // Check the defaults defined in the adapter
  Iif (!hasOwnProperty(connection, '_adapter')) return true;
  Eif (!hasOwnProperty(connection._adapter, 'schema')) return true;
 
  return connection._adapter.schema;
};