<commit_before>/*jshint eqeqeq:false*/

/**
 * State class.
 */
define([
    'dejavu/Class',
    './StateInterface',
    'mout/object/keys',
    'mout/object/values',
    'mout/object/mixIn',
    'mout/lang/deepClone',
    'mout/array/remove',
    'has'
], function (Class, StateInterface, keys, values, mixIn, deepClone, remove, has) {

    'use strict';

    var State = Class.declare({
        $name: 'State',
        $implements: StateInterface,

        _name: null,
        _params: null,
        _parts: null,
        _nrParts: 0,
        _cursor: 0,

        /**
         * Constructor.
         *
         * @param {String} name      The state name
         * @param {Object} [$params] The state parameters
         */
        initialize: function (name, $params) {
            this.setFullName(name);
            this.setParams($params);
        },

        /**
         * {@inheritDoc}
         */
        getFullName: function () {
            return this._name;
        },

        /**
         * {@inheritDoc}
         */
        setFullName: function (name) {
            if (has('debug') && !this.$static.isValid(name)) {
                throw new Error('State name "' + name + '" has an invalid format.');
            }

            this._name = name;
            this._parts = name.split('.');
            this._nrParts = this._parts.length;
            this.setCursor(this._cursor);

            return this;
        },

        /**
         * {@inheritDoc}
         */
        getName: function () {
            return this._cursor < this._nrParts ? this._parts[this._cursor] : null;
        },

        /**
         * {@inheritDoc}
         */
        getParams: function () {
            return this._params;
        },

        /**
         * {@inheritDoc}
         */
        setParams: function (params) {
            this._params = params || {};
            this._params.$state = this;

            return this;
        },

        /**
         * {@inheritDoc}
         */
        next: function () {
            if (this._cursor < this._nrParts) {
                this._cursor += 1;
            }

            return this;
        },

        /**
         * {@inheritDoc}
         */
        previous: function () {
            if (this._cursor > 1) {
                this._cursor -= 1;
            }

            return this;
        },

        /**
         * {@inheritDoc}
         */
        getCursor: function () {
            return this._cursor;
        },

        /**
         * {@inheritDoc}
         */
        setCursor: function (cursor) {
            if (this._cursor > this._nrParts) {
                this._cursor = this._nrParts;
            } else if (this._cursor < 0) {
                this._cursor = 0;
            } else {
                this._cursor = cursor;
            }

            return this;
        },

        /**
         * {@inheritDoc}
         */
        isEqual: function (state, $stateParams) {
            var x,
                curr;

            // Strict comparation first
            if (this === state) {
                return true;
            }

            // Compare the name
            if (this.getName() !== state.getName()) {
                return false;
            }

            // Compare the state params if any
            if ($stateParams) {
                for (x = $stateParams.length - 1; x >= 0; x -= 1) {
                    curr = $stateParams[x];
                    if (this._params[curr] != state._params[curr]) {
                        return false;
                    }
                }

                return true;
            }

            // Otherwise compare them all
            return this._compareObjects(this._params, state._params);
        },

        /**
         * {@inheritDoc}
         */
        isFullyEqual: function (state) {
            // Strict comparation first
            if (this === state) {
                return true;
            }

            // Compare the name
            if (this._name !== state._name) {
                return false;
            }

            // Compare all the params
            return this._compareObjects(this._params, state._params);
        },

        /**
         * {@inheritDoc}
         */
        clone: function () {
            var ret = new State(this._name, deepClone(this._params));
            ret._cursor = this._cursor;

            return ret;
        },

        /**
         * Compares to objects loosely (not recursively).
         *
         * @return {Boolean} True if they are loosely equal, false otherwise
         */
        _compareObjects: function (obj1, obj2) {
            var keys1 = keys(obj1),
                keys2 = keys(obj2),
                key,
                x;

            remove(keys1, '$state');
            remove(keys2, '$state');

            if (keys1.length !== keys2.length) {
                return false;
            }

            for (x = keys1.length - 1; x >= 0; x -= 1) {
                if (keys2.indexOf(keys1[x]) === -1) {
                    return false;
                }
            }

            for (x = keys1.length - 1; x >= 0; x -= 1) {
                key = keys[x];
                if (obj1[key] !== obj2[key]) {
                    return false;
                }
            }

            return true;
        },

        $statics: {
            _nameRegExp: /^([a-z0-9_\-]+(\.[a-z0-9_\-]+)*)?$/i,

            /**
             * Checks if a given state name is valid.
             *
             * @param {String} state The state
             *
             * @return {Boolean} True if valid, false otherwise
             */
            isValid: function (name) {
                return this._nameRegExp.test(name);
            }
        }
    });

    return State;
});
<commit_msg>Fix another issue with state params comparison.<commit_after>/*jshint eqeqeq:false*/

/**
 * State class.
 */
define([
    'dejavu/Class',
    './StateInterface',
    'mout/object/keys',
    'mout/object/values',
    'mout/object/mixIn',
    'mout/lang/deepClone',
    'mout/array/remove',
    'has'
], function (Class, StateInterface, keys, values, mixIn, deepClone, remove, has) {

    'use strict';

    var State = Class.declare({
        $name: 'State',
        $implements: StateInterface,

        _name: null,
        _params: null,
        _parts: null,
        _nrParts: 0,
        _cursor: 0,

        /**
         * Constructor.
         *
         * @param {String} name      The state name
         * @param {Object} [$params] The state parameters
         */
        initialize: function (name, $params) {
            this.setFullName(name);
            this.setParams($params);
        },

        /**
         * {@inheritDoc}
         */
        getFullName: function () {
            return this._name;
        },

        /**
         * {@inheritDoc}
         */
        setFullName: function (name) {
            if (has('debug') && !this.$static.isValid(name)) {
                throw new Error('State name "' + name + '" has an invalid format.');
            }

            this._name = name;
            this._parts = name.split('.');
            this._nrParts = this._parts.length;
            this.setCursor(this._cursor);

            return this;
        },

        /**
         * {@inheritDoc}
         */
        getName: function () {
            return this._cursor < this._nrParts ? this._parts[this._cursor] : null;
        },

        /**
         * {@inheritDoc}
         */
        getParams: function () {
            return this._params;
        },

        /**
         * {@inheritDoc}
         */
        setParams: function (params) {
            this._params = params || {};
            this._params.$state = this;

            return this;
        },

        /**
         * {@inheritDoc}
         */
        next: function () {
            if (this._cursor < this._nrParts) {
                this._cursor += 1;
            }

            return this;
        },

        /**
         * {@inheritDoc}
         */
        previous: function () {
            if (this._cursor > 1) {
                this._cursor -= 1;
            }

            return this;
        },

        /**
         * {@inheritDoc}
         */
        getCursor: function () {
            return this._cursor;
        },

        /**
         * {@inheritDoc}
         */
        setCursor: function (cursor) {
            if (this._cursor > this._nrParts) {
                this._cursor = this._nrParts;
            } else if (this._cursor < 0) {
                this._cursor = 0;
            } else {
                this._cursor = cursor;
            }

            return this;
        },

        /**
         * {@inheritDoc}
         */
        isEqual: function (state, $stateParams) {
            var x,
                curr;

            // Strict comparation first
            if (this === state) {
                return true;
            }

            // Compare the name
            if (this.getName() !== state.getName()) {
                return false;
            }

            // Compare the state params if any
            if ($stateParams) {
                for (x = $stateParams.length - 1; x >= 0; x -= 1) {
                    curr = $stateParams[x];
                    if (this._params[curr] != state._params[curr]) {
                        return false;
                    }
                }

                return true;
            }

            // Otherwise compare them all
            return this._compareObjects(this._params, state._params);
        },

        /**
         * {@inheritDoc}
         */
        isFullyEqual: function (state) {
            // Strict comparation first
            if (this === state) {
                return true;
            }

            // Compare the name
            if (this._name !== state._name) {
                return false;
            }

            // Compare all the params
            return this._compareObjects(this._params, state._params);
        },

        /**
         * {@inheritDoc}
         */
        clone: function () {
            var ret = new State(this._name, deepClone(this._params));
            ret._cursor = this._cursor;

            return ret;
        },

        /**
         * Compares to objects loosely (not recursively).
         *
         * @return {Boolean} True if they are loosely equal, false otherwise
         */
        _compareObjects: function (obj1, obj2) {
            var keys1 = keys(obj1),
                keys2 = keys(obj2),
                key,
                x;

            remove(keys1, '$state');
            remove(keys2, '$state');

            if (keys1.length !== keys2.length) {
                return false;
            }

            for (x = keys1.length - 1; x >= 0; x -= 1) {
                if (keys2.indexOf(keys1[x]) === -1) {
                    return false;
                }
            }

            for (x = keys1.length - 1; x >= 0; x -= 1) {
                key = keys1[x];
                if (obj1[key] !== obj2[key]) {
                    return false;
                }
            }

            return true;
        },

        $statics: {
            _nameRegExp: /^([a-z0-9_\-]+(\.[a-z0-9_\-]+)*)?$/i,

            /**
             * Checks if a given state name is valid.
             *
             * @param {String} state The state
             *
             * @return {Boolean} True if valid, false otherwise
             */
            isValid: function (name) {
                return this._nameRegExp.test(name);
            }
        }
    });

    return State;
});
<|endoftext|>


<commit_before>// Requires
var Q = require('q');
var _ = require('underscore');

function ProcRPCService(search) {
    this.proc = proc;

    _.bindAll(this);
}

ProcRPCService.prototype.http = function(args) {
    return this.proc.http();
};

// Exports
exports.ProcRPCService = ProcRPCService;
<commit_msg>Fix typo in cb.rpc.proc<commit_after>// Requires
var Q = require('q');
var _ = require('underscore');

function ProcRPCService(proc) {
    this.proc = proc;

    _.bindAll(this);
}

ProcRPCService.prototype.http = function(args) {
    return this.proc.http();
};

// Exports
exports.ProcRPCService = ProcRPCService;
<|endoftext|>


<commit_before>/**
 * Module for global and app configs.
 * @module kbox.core.config
 */

'use strict';

var path = require('path');
var os = require('os');
var fs = require('fs');
var env = require('./env.js');
var deps = require('./deps.js');
var log = require('./log.js');
var _ = require('lodash');

// Constants
var CONFIG_FILENAME = 'kalabox.json';
exports.CONFIG_FILENAME = CONFIG_FILENAME;

var DEFAULT_GLOBAL_CONFIG = {
  domain: 'kbox',
  engine: 'https://github.com/kalabox/kalabox-engine-docker/' +
    'tarball/v0.8.0-beta',
  engineRepo: 'kalabox',
  codeDir: 'code',
  services: 'https://github.com/kalabox/kalabox-services-kalabox/' +
    'tarball/v0.8.0-beta',
  apps: [
    'kalabox-app-drupal@0.7.11',
    'kalabox-app-backdrop@0.7.7'
  ],
  profile: 'standard',
  sharing: true,
  kboxRoot: ':home:/kalabox',
  kalaboxRoot: ':kboxRoot:',
  logLevel: 'debug',
  logLevelConsole: 'info',
  logRoot: ':sysConfRoot:/logs',
  downloadsRoot: ':sysConfRoot:/downloads',
  appsRoot: ':kboxRoot:/apps',
  appRegistry: ':sysConfRoot:/appRegistry.json',
  globalPluginRoot: ':kboxRoot:/plugins',
  globalPlugins: [
    'kalabox-core',
    'kalabox-syncthing',
    'kalabox-app-drupal',
    'kalabox-app-backdrop'
  ],
  configSources: [
    'DEFAULT_GLOBAL_CONFIG'
  ]
};

var logDebug = log.debug;
var logInfo = log.info;

/*
 * Pretty print an object.
 */
var pp = function(obj) {
  return JSON.stringify(obj, null, '  ');
};

/*
 * Looks up a key of the config object and returns it.
 */
var lookupKey = function(config, keyToFind) {

  // Recursive function.
  var rec = function(o, prefix) {

    // Loop through each of the objects properties to find value.
    return _.find(o, function(val, key) {

      // Build namespaced name.
      var name = _.filter([prefix, key]).join('.');

      if (typeof val === 'string') {

        // If name of string value matches, return it.
        return (':' + name + ':') === keyToFind;

      } else if (typeof val === 'object') {

        // Recursively check object.
        return rec(val, name);

      } else {

        // Not a string or an object so just return false.
        return false;

      }

    });

  };

  // Init recursive function and return.
  return rec(config);

};

/*
 * Translate a value.
 */
var normalizeValue = exports.normalizeValue = function(config, v) {

  // Search value for regex matches.
  //var params = v.match(/:[a-zA-Z0-9-_]*:/g);
  var params;
  try {
    params = v.match(/:[a-zA-Z0-9-_]*:/g);
  }
  catch (err) {
    throw new Error(typeof v);
  }

  if (!params) {

    // No params were found, so just return original value.
    return v;

  } else {

    // Reduce list of params to final value.
    return _.reduce(params, function(acc, param) {

      // Get replacement value from config object based on param name.
      var replacementValue = lookupKey(config, param);

      if (!replacementValue) {

        // Replacement value was not found so just return value.
        return acc;

      } else {

        // Replace and return.
        return acc.replace(param, replacementValue);

      }

    }, v);

  }

};

/*
 * Walk the properties of the top level object, replacing strings
 * with other properties values.
 */
var normalize = exports.normalize = function(config) {

  // Recursive funciton.
  var rec = function(o) {

    // Loop through each property of the object.
    _.each(o, function(val, key) {

      if (typeof val === 'string') {

        // For string values normalize.
        o[key] = normalizeValue(config, val);

      } else if (typeof val === 'object') {

        // For object values recursively normalize.
        rec(val);

      }

    });

  };

  // Init recursive function with config.
  rec(config);

  // Return config.
  return config;

};

function sort(config) {
  var keys = Object.keys(config).sort();
  var retVal = {};
  for (var i = 0; i < keys.length; ++i) {
    var key = keys[i];
    retVal[key] = config[key];
  }
  return retVal;
}

// @todo: implement
var KEYS_TO_CONCAT = [
  'configSources'
];

function mixIn(a, b) {
  for (var key in b) {
    var shouldConcat = _.contains(KEYS_TO_CONCAT, key);
    if (shouldConcat) {
      // Concat.
      if (a[key] === undefined) {
        a[key] = b[key];
      } else {
        a[key] = a[key].concat(b[key]);
      }
    } else {
      // Override.
      a[key] = b[key];
    }
  }
  return sort(normalize(a));
}
exports.mixIn = mixIn;

var getPackageJson = function() {
  return require(path.join(env.getSourceRoot(), 'package.json'));
};

/**
 * Gets the kalabox environment config.
 * @returns {object} config - The kalabox enviroment config.
 * @example
 * var envConfig = kbox.core.config.getEnvConfig();
 * // Print home directory to stdout.
 * console.log(envConfig.home);
 */
exports.getEnvConfig = function() {
  var packageJson = getPackageJson();
  var provisioned = false;
  if (fs.existsSync(path.join(env.getSysConfRoot(), 'provisioned'))) {
    provisioned = true;
  }
  return {
    provisioned: provisioned,
    home: env.getHomeDir(),
    os: {
      type: os.type(),
      platform: os.platform(),
      release: os.release(),
      arch: os.arch()
    },
    sysConfRoot: env.getSysConfRoot(),
    sysProviderRoot: env.getSysProviderRoot(),
    srcRoot: env.getSourceRoot(),
    version: packageJson.version,
    configSources: [
      'ENV_CONFIG'
    ]
  };
};

/**
 * Gets the default config. The default config is a combination of the
 *   environment config and a set of default config values.
 * @returns {object} config - The kalabox default config.
 * @example
 * var defaultConfig = kbox.core.config.getDefaultConfig();
 * // Print global plugins
 * defaultConfig.globalPlugins.forEach(function(plugin) {
 *   console.log(plugin)  ;
 * });
 */
exports.getDefaultConfig = function() {
  return mixIn(this.getEnvConfig(), DEFAULT_GLOBAL_CONFIG);
};

var getReleaseConfigFilepath = exports.getReleaseConfigFilepath = function() {
  return path.join(env.getSourceRoot(), CONFIG_FILENAME);
};

var getGlobalConfigFilepath = function() {
  return path.join(env.getSysConfRoot(), CONFIG_FILENAME);
};

var loadConfigFile = function(configFilepath) {
  var loadedConfigFile = require(configFilepath);
  loadedConfigFile.configSources = [configFilepath];
  return loadedConfigFile;
};

/**
 * Gets the global config. The global config is a combination of the
 *   environment config, the default config, and any values overriden
 *   in the $HOME/.kalabox/kalabox.json config file.
 * @returns {object} config - The kalabox global config.
 * @example
 * var globalConfig = kbox.core.config.getGlobalConfig();
 * // Print the entire global config.
 * console.log(JSON.stringify(globalConfig, null, '\t'));
 */
exports.getGlobalConfig = function() {
  var defaultConfig = this.getDefaultConfig();
  var filesToLoad = [
    getReleaseConfigFilepath(),
    getGlobalConfigFilepath()
  ];
  var globalConfig = _.reduce(filesToLoad, function(config, fileToLoad) {
    if (fs.existsSync(fileToLoad)) {
      var loadedConfigFile = loadConfigFile(fileToLoad);
      config = mixIn(config, loadedConfigFile);
    }
    return config;
  }, defaultConfig);
  return globalConfig;
};

exports.getAppConfigFilepath = function(app, config) {
  return path.join(config.appsRoot, app.name, CONFIG_FILENAME);
};

/**
 * Gets the app config for an app. The app config is a combination of the
 *   environment config, the default config, any values overriden in the
 *   $HOME/.kalabox/kalabox.json config file, and the kalabox.json config
 *   file in the app's root directory.
 * @arg {string} app - The name of the app you'd like to get the config for.
 * @arg {string} appRoot [optional] - Directory to load the
 * app's config file from.
 * @returns {object} config - The app's kalabox app config.
 * @example
 * var appConfig = kbox.core.config.getAppConfig('myapp');
 * // Print the entire app config.
 * console.log(JSON.stringify(appConfig, null, '\t'));
 */
exports.getAppConfig = function(app, appRoot) {
  // @todo: this is jank
  if (typeof app === 'string') {
    var appName = app;
    app = {name: appName};
  }

  var globalConfig = this.getGlobalConfig();

  if (!appRoot) {
    appRoot = path.join(globalConfig.appsRoot, app.name);
  }

  var appConfigFilepath = path.join(appRoot, CONFIG_FILENAME);
  var appConfigFile = require(appConfigFilepath);
  appConfigFile.appRoot = appRoot;
  appConfigFile.appCidsRoot = ':appRoot:/.cids';
  var retVal = mixIn(globalConfig, appConfigFile);
  logDebug('CONFIG => App config loaded.', retVal);
  return retVal;
};
<commit_msg>Swap to 0.8.0 beta apps<commit_after>/**
 * Module for global and app configs.
 * @module kbox.core.config
 */

'use strict';

var path = require('path');
var os = require('os');
var fs = require('fs');
var env = require('./env.js');
var deps = require('./deps.js');
var log = require('./log.js');
var _ = require('lodash');

// Constants
var CONFIG_FILENAME = 'kalabox.json';
exports.CONFIG_FILENAME = CONFIG_FILENAME;

var DEFAULT_GLOBAL_CONFIG = {
  domain: 'kbox',
  engine: 'https://github.com/kalabox/kalabox-engine-docker/' +
    'tarball/v0.8.0-beta',
  engineRepo: 'kalabox',
  codeDir: 'code',
  services: 'https://github.com/kalabox/kalabox-services-kalabox/' +
    'tarball/v0.8.0-beta',
  apps: [
    'https://github.com/kalabox/kalabox-app-backdrop/tarball/v0.8.0-beta',
    'https://github.com/kalabox/kalabox-app-drupal/tarball/v0.8.0-beta'
  ],
  profile: 'standard',
  sharing: true,
  kboxRoot: ':home:/kalabox',
  kalaboxRoot: ':kboxRoot:',
  logLevel: 'debug',
  logLevelConsole: 'info',
  logRoot: ':sysConfRoot:/logs',
  downloadsRoot: ':sysConfRoot:/downloads',
  appsRoot: ':kboxRoot:/apps',
  appRegistry: ':sysConfRoot:/appRegistry.json',
  globalPluginRoot: ':kboxRoot:/plugins',
  globalPlugins: [
    'kalabox-core',
    'kalabox-syncthing',
    'kalabox-app-drupal',
    'kalabox-app-backdrop'
  ],
  configSources: [
    'DEFAULT_GLOBAL_CONFIG'
  ]
};

var logDebug = log.debug;
var logInfo = log.info;

/*
 * Pretty print an object.
 */
var pp = function(obj) {
  return JSON.stringify(obj, null, '  ');
};

/*
 * Looks up a key of the config object and returns it.
 */
var lookupKey = function(config, keyToFind) {

  // Recursive function.
  var rec = function(o, prefix) {

    // Loop through each of the objects properties to find value.
    return _.find(o, function(val, key) {

      // Build namespaced name.
      var name = _.filter([prefix, key]).join('.');

      if (typeof val === 'string') {

        // If name of string value matches, return it.
        return (':' + name + ':') === keyToFind;

      } else if (typeof val === 'object') {

        // Recursively check object.
        return rec(val, name);

      } else {

        // Not a string or an object so just return false.
        return false;

      }

    });

  };

  // Init recursive function and return.
  return rec(config);

};

/*
 * Translate a value.
 */
var normalizeValue = exports.normalizeValue = function(config, v) {

  // Search value for regex matches.
  //var params = v.match(/:[a-zA-Z0-9-_]*:/g);
  var params;
  try {
    params = v.match(/:[a-zA-Z0-9-_]*:/g);
  }
  catch (err) {
    throw new Error(typeof v);
  }

  if (!params) {

    // No params were found, so just return original value.
    return v;

  } else {

    // Reduce list of params to final value.
    return _.reduce(params, function(acc, param) {

      // Get replacement value from config object based on param name.
      var replacementValue = lookupKey(config, param);

      if (!replacementValue) {

        // Replacement value was not found so just return value.
        return acc;

      } else {

        // Replace and return.
        return acc.replace(param, replacementValue);

      }

    }, v);

  }

};

/*
 * Walk the properties of the top level object, replacing strings
 * with other properties values.
 */
var normalize = exports.normalize = function(config) {

  // Recursive funciton.
  var rec = function(o) {

    // Loop through each property of the object.
    _.each(o, function(val, key) {

      if (typeof val === 'string') {

        // For string values normalize.
        o[key] = normalizeValue(config, val);

      } else if (typeof val === 'object') {

        // For object values recursively normalize.
        rec(val);

      }

    });

  };

  // Init recursive function with config.
  rec(config);

  // Return config.
  return config;

};

function sort(config) {
  var keys = Object.keys(config).sort();
  var retVal = {};
  for (var i = 0; i < keys.length; ++i) {
    var key = keys[i];
    retVal[key] = config[key];
  }
  return retVal;
}

// @todo: implement
var KEYS_TO_CONCAT = [
  'configSources'
];

function mixIn(a, b) {
  for (var key in b) {
    var shouldConcat = _.contains(KEYS_TO_CONCAT, key);
    if (shouldConcat) {
      // Concat.
      if (a[key] === undefined) {
        a[key] = b[key];
      } else {
        a[key] = a[key].concat(b[key]);
      }
    } else {
      // Override.
      a[key] = b[key];
    }
  }
  return sort(normalize(a));
}
exports.mixIn = mixIn;

var getPackageJson = function() {
  return require(path.join(env.getSourceRoot(), 'package.json'));
};

/**
 * Gets the kalabox environment config.
 * @returns {object} config - The kalabox enviroment config.
 * @example
 * var envConfig = kbox.core.config.getEnvConfig();
 * // Print home directory to stdout.
 * console.log(envConfig.home);
 */
exports.getEnvConfig = function() {
  var packageJson = getPackageJson();
  var provisioned = false;
  if (fs.existsSync(path.join(env.getSysConfRoot(), 'provisioned'))) {
    provisioned = true;
  }
  return {
    provisioned: provisioned,
    home: env.getHomeDir(),
    os: {
      type: os.type(),
      platform: os.platform(),
      release: os.release(),
      arch: os.arch()
    },
    sysConfRoot: env.getSysConfRoot(),
    sysProviderRoot: env.getSysProviderRoot(),
    srcRoot: env.getSourceRoot(),
    version: packageJson.version,
    configSources: [
      'ENV_CONFIG'
    ]
  };
};

/**
 * Gets the default config. The default config is a combination of the
 *   environment config and a set of default config values.
 * @returns {object} config - The kalabox default config.
 * @example
 * var defaultConfig = kbox.core.config.getDefaultConfig();
 * // Print global plugins
 * defaultConfig.globalPlugins.forEach(function(plugin) {
 *   console.log(plugin)  ;
 * });
 */
exports.getDefaultConfig = function() {
  return mixIn(this.getEnvConfig(), DEFAULT_GLOBAL_CONFIG);
};

var getReleaseConfigFilepath = exports.getReleaseConfigFilepath = function() {
  return path.join(env.getSourceRoot(), CONFIG_FILENAME);
};

var getGlobalConfigFilepath = function() {
  return path.join(env.getSysConfRoot(), CONFIG_FILENAME);
};

var loadConfigFile = function(configFilepath) {
  var loadedConfigFile = require(configFilepath);
  loadedConfigFile.configSources = [configFilepath];
  return loadedConfigFile;
};

/**
 * Gets the global config. The global config is a combination of the
 *   environment config, the default config, and any values overriden
 *   in the $HOME/.kalabox/kalabox.json config file.
 * @returns {object} config - The kalabox global config.
 * @example
 * var globalConfig = kbox.core.config.getGlobalConfig();
 * // Print the entire global config.
 * console.log(JSON.stringify(globalConfig, null, '\t'));
 */
exports.getGlobalConfig = function() {
  var defaultConfig = this.getDefaultConfig();
  var filesToLoad = [
    getReleaseConfigFilepath(),
    getGlobalConfigFilepath()
  ];
  var globalConfig = _.reduce(filesToLoad, function(config, fileToLoad) {
    if (fs.existsSync(fileToLoad)) {
      var loadedConfigFile = loadConfigFile(fileToLoad);
      config = mixIn(config, loadedConfigFile);
    }
    return config;
  }, defaultConfig);
  return globalConfig;
};

exports.getAppConfigFilepath = function(app, config) {
  return path.join(config.appsRoot, app.name, CONFIG_FILENAME);
};

/**
 * Gets the app config for an app. The app config is a combination of the
 *   environment config, the default config, any values overriden in the
 *   $HOME/.kalabox/kalabox.json config file, and the kalabox.json config
 *   file in the app's root directory.
 * @arg {string} app - The name of the app you'd like to get the config for.
 * @arg {string} appRoot [optional] - Directory to load the
 * app's config file from.
 * @returns {object} config - The app's kalabox app config.
 * @example
 * var appConfig = kbox.core.config.getAppConfig('myapp');
 * // Print the entire app config.
 * console.log(JSON.stringify(appConfig, null, '\t'));
 */
exports.getAppConfig = function(app, appRoot) {
  // @todo: this is jank
  if (typeof app === 'string') {
    var appName = app;
    app = {name: appName};
  }

  var globalConfig = this.getGlobalConfig();

  if (!appRoot) {
    appRoot = path.join(globalConfig.appsRoot, app.name);
  }

  var appConfigFilepath = path.join(appRoot, CONFIG_FILENAME);
  var appConfigFile = require(appConfigFilepath);
  appConfigFile.appRoot = appRoot;
  appConfigFile.appCidsRoot = ':appRoot:/.cids';
  var retVal = mixIn(globalConfig, appConfigFile);
  logDebug('CONFIG => App config loaded.', retVal);
  return retVal;
};
<|endoftext|>


<commit_before>import { max } from '../../utility/kit';

export class Matrix {
    constructor(isDataRow) {
        this.isDataRow = isDataRow;
    }

    build(table) {
        const isDataRow = this.isDataRow;
        const rows = table.rows;
        const matrix = [];

        const cursor = new Array(rows.length);
        cursor.fill(0);

        let currentRow = 0;
        for (let i = 0, rowsLength = rows.length; i < rowsLength; i++) {
            const tr = rows[i];
            if (!isDataRow(tr)) {
                continue;
            }

            const cells = tr.cells;
            for (let j = 0, cellsLength = cells.length; j < cellsLength; j++) {
                const td = cells[j];

                const colSpan = td.colSpan;
                const rowSpan = td.rowSpan;

                for (let k = 0; k < rowSpan; k++) {
                    const rowIndex = currentRow + k;
                    const colIndex = cursor[rowIndex];
                    let cursorRow = matrix[rowIndex];
                    if (!cursorRow) {
                        cursorRow = [];
                        matrix[rowIndex] = cursorRow;
                    }

                    for (let m = 0; m < colSpan; m++) {
                        cursorRow[colIndex + m] = td;
                    }

                    cursor[rowIndex] = colIndex + colSpan;
                }
            }

            currentRow++;
        }

        return matrix;
    }
}<commit_msg>add flat assert<commit_after>import { max } from '../../utility/kit';
import { AppError } from '../../infrastructure/error';

export class Matrix {
    constructor(isDataRow) {
        this.isDataRow = isDataRow;
    }

    build(table) {
        const isDataRow = this.isDataRow;
        const rows = table.rows;
        const matrix = [];

        const offset = new Array(rows.length);
        offset.fill(0);

        let cursor = 0;
        for (let i = 0, height = rows.length; i < height; i++) {
            const tr = rows[i];
            if (!isDataRow(tr)) {
                continue;
            }

            const cells = tr.cells;
            for (let j = 0, width = cells.length; j < width; j++) {
                const td = cells[j];
                const { colSpan, rowSpan } = td;

                for (let y = 0; y < rowSpan; y++) {
                    const yi = cursor + y;
                    const xi = offset[yi];
                    let row = matrix[yi];
                    if (!row) {
                        row = [];
                        matrix[yi] = row;
                    }

                    for (let x = 0; x < colSpan; x++) {
                        row[xi + x] = td;
                    }

                    offset[yi] = xi + colSpan;
                }
            }

            cursor++;
        }

        this.assertFlatness(matrix);
        return matrix;
    }

    assertFlatness(matrix) {
        if (matrix.length) {
            const height = matrix.length;
            const width = matrix[0].length;
            for (let i = 1; i < height; i++) {
                if (matrix[i].length !== width) {
                    throw new AppError('matrix', `Matrix is not flat, expect width ${width}, actual ${matrix[i].length}`);
                }
            }
        }
    }
}<|endoftext|>


<commit_before>#!/usr/bin/env node

var OPC = new require('./opc')

var fc = new OPC('localhost', 7890);

var sp = require('serialport');
var SerialPort = require('serialport').SerialPort;
var portName = "/dev/ttyArduino";

var runState = "down";

var BRIGHTEN = 100;
var DARKEN = 101;

var BRIGHTEN_S = 200;
var DARKEN_S = 201;

var SWEEP = 300;

var pixelLength = 300;
var particleCount = 400;

var environmentLength = 3000;

var defaultScale = 7;

var pixels = [];
var particles = [];

var lookup = [];

var coordT = [];

var dist_v = [];

var timerIdle = true;

// MAIN COMPUTER PROGRAM!

initialize();
setInterval(evaluate, 30);

function initialize() {
	serialport = new SerialPort(portName , { baudrate : 115200, parser: sp.parsers.readline("|") }, false);
	openPort();

	// Init coord lookup
	var coordRatio = ( ( pixelLength ) / environmentLength );
	for ( var t=0; t<environmentLength+1; t++ ){ coordT[t] = Math.floor( t * coordRatio ); }

	// Init scaling lookup

	lookup[defaultScale] = { 'environmentLength': defaultScale * pixelLength, 'positions': [] };

	for ( var p=0; p < lookup[defaultScale].environmentLength; p++ ){
		var div = p / defaultScale;
		var calc = {
			'left': Math.floor( div ),
			'right': Math.floor( div ) + 1,
			'wleft': 1 - ( div ) % 1,
			'wright': ( div ) % 1
		};

		lookup[defaultScale].positions.push( calc );
	}

	// Init pixel array
	for ( var i=0; i<pixelLength + 3; i++ ) { pixels.push({ 'r':0, 'g':0, 'b':0 }); }
}

function evaluate() {
	if ( runState == "open") {
  	updateParticles();
  	evaluateEnvironment();
  	draw();
	} else {
		if ( timerIdle ) {
			setTimeout( function() {
				openPort();
				timerIdle = true;
			}, 5000);
			timerIdle = false;
		}
	}
}

function updateParticles() {
  for ( var i=0; i<particles.length; i++ ){
		particles[i].update( i );
  }
}

function evaluateEnvironment() {
	// fill particle list
	if ( particles.length < particleCount ) {
		particles.push( getRandParticle() );
	}
}

function draw() {
  if ( runState == "open" ) {

		// Initialize
		initAllPixels( 20, 20, 40 );

	  // Compose
	  for ( var i=0; i<particles.length; i++ ){ particles[i].method(); }

	  // Render
	//	try {
	    for ( var i=0; i<pixels.length; i++ ){
	      fc.setPixel( pixels.length-i, pixels[i].red, pixels[i].green, pixels[i].blue );
	    }
	    fc.writePixels();
	//	} catch( err ) {
	//		console.log('fc write err: ' + error);
	//		runState = "fc write err";
	//	}

  } else {
    // display runstate graphics

  }
}

// update methods

function update_Discrete( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > environmentLength ) {
		particles[i] = getRandParticle();
	}
}

function update_Smooth( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > lookup[this.scale].environmentLength-1 ) {
    particles[i] = getRandParticle();
	}
}

function update_Glower( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > lookup[this.scale].environmentLength-1 ) {
    particles[i] = getRandParticle();
	}
}

// draw methods

function method_Brighten() {
	var dest = coordT[this.position];

	pixels[dest].red += this.color.r;
	pixels[dest].green += this.color.g;
	pixels[dest].blue += this.color.b;
}

function method_Darken() {
	var dest = coordT[this.position];

	pixels[dest].red -= this.color.r;
	pixels[dest].green -= this.color.g;
	pixels[dest].blue -= this.color.b;
}

function method_BrightenSmooth() {
	var pcalc = lookup[this.scale].positions[this.position];
	methodValueSmooth( this, pcalc );
}

function method_DarkenSmooth() {
	var pcalc = lookup[this.scale].positions[this.position];
	if ( this.method == DARKEN_S ) {
		pcalc.wleft *= -1;
		pcalc.wright *= -1;
	}
	methodValueSmooth( this, pcalc );
}

function methodValueSmooth( tgt, pcalc ){
	pixels[pcalc.left].red += tgt.color.r * pcalc.wleft;
	pixels[pcalc.left].green += tgt.color.g * pcalc.wleft;
	pixels[pcalc.left].blue += tgt.color.b * pcalc.wleft;

	pixels[pcalc.right].red += tgt.color.r * pcalc.wright;
	pixels[pcalc.right].green += tgt.color.g * pcalc.wright;
	pixels[pcalc.right].blue += tgt.color.b * pcalc.wright;
}

function method_Sweep() {
	var pcalc = lookup[this.scale].positions[this.position];

	var taillen = 6;
	var fraction = 1/taillen;

	for ( var t=0; t < taillen; t++ ) {
		try {
		var tail = pcalc.right - t;
	} catch ( err ) {
		console.log( i + " | " + this.position );
	}
		if ( tail > 0 ) {
			var factor = ( 6 - t ) * ( fraction );
			pixels[tail].red += this.color.r * factor;
			pixels[tail].green += this.color.g * factor;
			pixels[tail].blue += this.color.b * factor;
		}
	}
	var frontedge = pcalc.right + 1;
	if ( frontedge < pixelLength - 2 ) {
		pixels[frontedge].red = 0;
		pixels[frontedge].green = 0;
		pixels[frontedge].blue = 0;
	}
}

function setPixel( i, r, g, b ) {
	pixels[i].red = r;
	pixels[i].green = g;
	pixels[i].blue = b;
}

function initAllPixels( r, g, b ){
	for ( var i=0; i<pixels.length; i++ ) {
		pixels[i].red = r;
		pixels[i].green = g;
		pixels[i].blue = b;
	}
}

function getRandParticle() {
	var r = Math.random();

	if ( r < .10 ) {
		return getParticle( 4, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 10, 10, 85 );
//	} else if ( r < .15 ) {
//		return getParticle( 3, 0, 1, method_Sweep, update_Smooth, defaultScale, 60, 10, 15 );
//	} else if ( r < .30 ) {
//		return getParticle( 3, 0, 1, method_Sweep, update_Smooth, defaultScale, 30, 30, 95 );
	} else if ( r < .50 ) {
		return getParticle( 4, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 45, 25, 100 )
	} else {
		return getParticle( 2, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 5, 5, 10 );
	}
}

function getParticle( v, p, r, g, b ) {
	return getParticle( v, p, 1, method_Brighten, update_Discrete, defaultScale, r, g, b );
}

function getParticle( v, p, i, m, u, s, r, g, b ) {
  var p = {
    'vel': v,
    'position': p,
    'intensity': i,
		'method': m,
		'update': u,
		'scale': s,
    'color': { 'r': r, 'g': g, 'b': b }
  };
  return p;
}

// Serial Access

function listPorts() {
  serialport.list(function (err, ports) {
    ports.forEach(function(port) {
      console.log(port.comName);
    });
  });
  return ports;
}

function openPort() {
	serialport.on('error', function(err){
		console.log('serialport general error' + err);
	});

  serialport.open(function (error) {
    if ( error ) {
      console.log('open err: ' + error);
//			runState = "conn open err";
	runState = "open";
    } else {
      console.log('open');
			runState = "open";

      serialport.on('data', function(data) {
    		var c = data.trim();
				try{
					//console.log('rcv: ' + c);
	    		dist_v = JSON.parse(c);
					//dist_v = {};
	    		//console.log(' 12: ' + dist_v[12] );
				} catch( err ){
					console.log('parse err ' + err);
				}
	    });

    }
  });

}
<commit_msg>get sonar input<commit_after>#!/usr/bin/env node

var OPC = new require('./opc')

var fc = new OPC('localhost', 7890);

var sp = require('serialport');
var SerialPort = require('serialport').SerialPort;
var portName = "/dev/ttyArduino";

var runState = "down";

var BRIGHTEN = 100;
var DARKEN = 101;

var BRIGHTEN_S = 200;
var DARKEN_S = 201;

var SWEEP = 300;

var pixelLength = 300;
var particleCount = 400;

var environmentLength = 3000;

var defaultScale = 7;

var pixels = [];
var particles = [];

var lookup = [];

var coordT = [];

var dist_v = [];

var timerIdle = true;

// MAIN COMPUTER PROGRAM!

initialize();
setInterval(evaluate, 30);

function initialize() {
	serialport = new SerialPort(portName , { baudrate : 115200, parser: sp.parsers.readline("|") }, false);
	openPort();

	for ( var i=0; i<8; i++ ) { dist_v[i] = 0; }

	// Init coord lookup
	var coordRatio = ( ( pixelLength ) / environmentLength );
	for ( var t=0; t<environmentLength+1; t++ ){ coordT[t] = Math.floor( t * coordRatio ); }

	// Init scaling lookup

	lookup[defaultScale] = { 'environmentLength': defaultScale * pixelLength, 'positions': [] };

	for ( var p=0; p < lookup[defaultScale].environmentLength; p++ ){
		var div = p / defaultScale;
		var calc = {
			'left': Math.floor( div ),
			'right': Math.floor( div ) + 1,
			'wleft': 1 - ( div ) % 1,
			'wright': ( div ) % 1
		};

		lookup[defaultScale].positions.push( calc );
	}

	// Init pixel array
	for ( var i=0; i<pixelLength + 3; i++ ) { pixels.push({ 'r':0, 'g':0, 'b':0 }); }
}

function evaluate() {
	if ( runState == "open") {
  	updateParticles();
  	evaluateEnvironment();
  	draw();
	} else {
		if ( timerIdle ) {
			setTimeout( function() {
				openPort();
				timerIdle = true;
			}, 5000);
			timerIdle = false;
		}
	}
}

function updateParticles() {
  for ( var i=0; i<particles.length; i++ ){
		particles[i].update( i );
  }
}

function evaluateEnvironment() {
	// fill particle list
	if ( particles.length < particleCount ) {
		particles.push( getRandParticle() );
	}

	for ( var s=0; s < 8; s++ ) {

			if ( dist_v[s] > 0 && dist_v[s] < 50 ) {
				particles.push( getProximateParticle( s, dist_v[s] );
			}
	}
}

function draw() {
  if ( runState == "open" ) {

		// Initialize
		initAllPixels( 20, 20, 40 );

	  // Compose
	  for ( var i=0; i<particles.length; i++ ){ particles[i].method(); }

	  // Render
	//	try {
	    for ( var i=0; i<pixels.length; i++ ){
	      fc.setPixel( pixels.length-i, pixels[i].red, pixels[i].green, pixels[i].blue );
	    }
	    fc.writePixels();
	//	} catch( err ) {
	//		console.log('fc write err: ' + error);
	//		runState = "fc write err";
	//	}

  } else {
    // display runstate graphics

  }
}

// update methods

function update_Discrete( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > environmentLength ) {
		particles[i] = getRandParticle();
	}
}

function update_Smooth( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > lookup[this.scale].environmentLength-1 ) {
    particles[i] = getRandParticle();
	}
}

function update_Glower( i ) {
	this.position += this.vel;

	// recycle rules
	if ( this.position > lookup[this.scale].environmentLength-1 ) {
    particles[i] = getRandParticle();
	}
}

// draw methods

function method_Brighten() {
	var dest = coordT[this.position];

	pixels[dest].red += this.color.r;
	pixels[dest].green += this.color.g;
	pixels[dest].blue += this.color.b;
}

function method_Darken() {
	var dest = coordT[this.position];

	pixels[dest].red -= this.color.r;
	pixels[dest].green -= this.color.g;
	pixels[dest].blue -= this.color.b;
}

function method_BrightenSmooth() {
	var pcalc = lookup[this.scale].positions[this.position];
	methodValueSmooth( this, pcalc );
}

function method_DarkenSmooth() {
	var pcalc = lookup[this.scale].positions[this.position];
	if ( this.method == DARKEN_S ) {
		pcalc.wleft *= -1;
		pcalc.wright *= -1;
	}
	methodValueSmooth( this, pcalc );
}

function methodValueSmooth( tgt, pcalc ){
	pixels[pcalc.left].red += tgt.color.r * pcalc.wleft;
	pixels[pcalc.left].green += tgt.color.g * pcalc.wleft;
	pixels[pcalc.left].blue += tgt.color.b * pcalc.wleft;

	pixels[pcalc.right].red += tgt.color.r * pcalc.wright;
	pixels[pcalc.right].green += tgt.color.g * pcalc.wright;
	pixels[pcalc.right].blue += tgt.color.b * pcalc.wright;
}

function method_Sweep() {
	var pcalc = lookup[this.scale].positions[this.position];

	var taillen = 6;
	var fraction = 1/taillen;

	for ( var t=0; t < taillen; t++ ) {
		try {
		var tail = pcalc.right - t;
	} catch ( err ) {
		console.log( i + " | " + this.position );
	}
		if ( tail > 0 ) {
			var factor = ( 6 - t ) * ( fraction );
			pixels[tail].red += this.color.r * factor;
			pixels[tail].green += this.color.g * factor;
			pixels[tail].blue += this.color.b * factor;
		}
	}
	var frontedge = pcalc.right + 1;
	if ( frontedge < pixelLength - 2 ) {
		pixels[frontedge].red = 0;
		pixels[frontedge].green = 0;
		pixels[frontedge].blue = 0;
	}
}

function setPixel( i, r, g, b ) {
	pixels[i].red = r;
	pixels[i].green = g;
	pixels[i].blue = b;
}

function initAllPixels( r, g, b ){
	for ( var i=0; i<pixels.length; i++ ) {
		pixels[i].red = r;
		pixels[i].green = g;
		pixels[i].blue = b;
	}
}

function getProximateParticle( s, dist ) {
	var pos = s * ( pixelLength / 8 );
	return getParticle( 4, pos, 2,  method_BrightenSmooth, update_Smooth, defaultScale, 85, 75, 15 );
}

function getRandParticle() {
	var r = Math.random();

	if ( r < .10 ) {
		return getParticle( 4, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 10, 10, 85 );
//	} else if ( r < .15 ) {
//		return getParticle( 3, 0, 1, method_Sweep, update_Smooth, defaultScale, 60, 10, 15 );
//	} else if ( r < .30 ) {
//		return getParticle( 3, 0, 1, method_Sweep, update_Smooth, defaultScale, 30, 30, 95 );
	} else if ( r < .50 ) {
		return getParticle( 4, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 45, 25, 100 )
	} else {
		return getParticle( 2, 0, 1, method_BrightenSmooth, update_Smooth, defaultScale, 5, 5, 10 );
	}
}

function getParticle( v, p, r, g, b ) {
	return getParticle( v, p, 1, method_Brighten, update_Discrete, defaultScale, r, g, b );
}

function getParticle( v, p, i, m, u, s, r, g, b ) {
  var p = {
    'vel': v,
    'position': p,
    'intensity': i,
		'method': m,
		'update': u,
		'scale': s,
    'color': { 'r': r, 'g': g, 'b': b }
  };
  return p;
}

// Serial Access

function listPorts() {
  serialport.list(function (err, ports) {
    ports.forEach(function(port) {
      console.log(port.comName);
    });
  });
  return ports;
}

function openPort() {
	serialport.on('error', function(err){
		console.log('serialport general error' + err);
	});

  serialport.open(function (error) {
    if ( error ) {
      console.log('open err: ' + error);
//			runState = "conn open err";
	runState = "open";
    } else {
      console.log('open');
			runState = "open";

      serialport.on('data', function(data) {
    		var c = data.trim();
				try{
					//console.log('rcv: ' + c);
	    		dist_v = JSON.parse(c);
					//dist_v = {};
	    		//console.log(' 12: ' + dist_v[12] );
				} catch( err ){
					console.log('parse err ' + err);
				}
	    });

    }
  });

}
<|endoftext|>


<commit_before>'use strict'

const {Parser: XMLParser} = require('xml2js')
const camelCase = require('camelcase')

// -------------------------------------------------------------
// Constants.
// -------------------------------------------------------------

const OPTIONS = {
  explicitArray: false,
  async: false,
  tagNameProcessors: [camelCase]
}

// -------------------------------------------------------------
// Module.
// -------------------------------------------------------------

function parseXML (xml) {
  if (!xml) {
    throw new Error('XML input was null or empty')
  }

  let data

  new XMLParser(OPTIONS).parseString(xml, function (err, result) {
    // FIXME: is there a way to not have an error BUT no result aswell?
    // Check the behavior of xml2js.
    if (err || !result) {
      throw err
    }

    // Values are nested in the "product", "game" or "company" root node.
    // We need to detect and ignore this root element.
    if (result.game) {
      data = result.game
      data.type = 'product'
    } else if (result.product) {
      data = result.product
      data.type = 'product'
    } else if (result.company) {
      data = result.company
      data.type = 'company'
    } else {
      throw new Error('Unrecognized XML file, expected <game> or <company> root tag')
    }
  })

  return data
}

// -------------------------------------------------------------
// Exports.
// -------------------------------------------------------------

module.exports = {
  parseXML
}
<commit_msg>Remove fixme in parser<commit_after>'use strict'

const {Parser: XMLParser} = require('xml2js')
const camelCase = require('camelcase')

// -------------------------------------------------------------
// Constants.
// -------------------------------------------------------------

const OPTIONS = {
  explicitArray: false,
  async: false,
  tagNameProcessors: [camelCase]
}

// -------------------------------------------------------------
// Module.
// -------------------------------------------------------------

function parseXML (xml) {
  if (!xml) {
    throw new Error('XML input was null or empty')
  }

  let data

  new XMLParser(OPTIONS).parseString(xml, function (err, result) {
    if (err || !result) {
      throw new Error('Failed to parse XML file')
    }

    // Values are nested in the "product", "game" or "company" root node.
    // We need to detect and ignore this root element.
    if (result.game) {
      data = result.game
      data.type = 'product'
    } else if (result.product) {
      data = result.product
      data.type = 'product'
    } else if (result.company) {
      data = result.company
      data.type = 'company'
    } else {
      throw new Error('Unrecognized XML file, expected <game> or <company> root tag')
    }
  })

  return data
}

// -------------------------------------------------------------
// Exports.
// -------------------------------------------------------------

module.exports = {
  parseXML
}
<|endoftext|>


<commit_before>'use strict';
const fs = require('fs-extra');
const path = require('path');

function create(options) {
  return new Promise((resolve, reject) => {
    const createdat = Date.now();
    const updatedat = Date.now();
    const configurationDB = this.datas.get('configuration');
    try {
      if (typeof options === 'string') {
        fs.readJSON(path.resolve(options))
          .then(configJSON => {
            resolve(configurationDB.create({
              newdoc: Object.assign({},
                configJSON, {
                  createdat,
                  updatedat,
                }),
            }));
          })
          .catch(reject);
      } else {
        const { filepath, environment, container, config, } = options;
        resolve(configurationDB.create({
          newdoc: {
            filepath,
            environment,
            config,
            container,
            createdat,
            updatedat,
          },
        }));
      }
    } catch (e) {
      reject(e);
    }
  });
}

function update(options) {
  return new Promise((resolve, reject) => {
    const { config, _id, } = options;
    const createdat = Date.now();
    const updatedat = Date.now();
    const configurationDB = this.datas.get('configuration');
    try {
      resolve(configurationDB.update({
        updatedoc: Object.assign({},
          config,
          (_id) ? { _id, } : {}, {
            createdat,
            updatedat,
          }),
      }));
    } catch (e) {
      reject(e);
    }
  });
}

function remove(options) {
  return new Promise((resolve, reject) => {
    let { filepath, _id, id, } = options;
    const configurationDB = this.datas.get('configuration');
    try {
      if (typeof options === 'string') {
        id = options;
      }
      if (id || _id) {
        resolve(configurationDB.delete({
          id: id || _id,
        }));
      } else {
        configurationDB.load({ docid: 'filepath', query: filepath, })
          .then(result => {
            resolve(configurationDB.delete({ id: result._id, }));
          })
          .catch(reject);
      }
    } catch (e) {
      reject(e);
    }
  });
}

function getFilePath(options) {
  const { type, name, environment, filepath } = options;
  switch (type) {
    case 'app':
    case 'application':
    case 'environment':
      return {
        configFilePath: `content/config/environment/${environment}.json`,
        configDefaultSettings: Object.assign({}, this.settings, {
          extensions: {},
          container: {},
        }),
      };
    case 'ext':
    case 'extension':
      return {
        configFilePath: `content/config/extensions/${name}/${environment}.json`,
        configDefaultSettings: require(`${name}/config/settings`),
      };
    case 'ext-local':
    case 'extension-local':
      return {
        configFilePath: `content/config/extensions/${name}/${environment}.json`,
        configDefaultSettings: require(path.resolve(this.app_root, `content/extensions/${name}/config/settings`)),
      };
    case 'con':
    case 'container':
      return {
        configFilePath: `content/config/containers/${name}/${environment}.json`,
        configDefaultSettings: require(`${name}/config/settings`),
      };
    case 'con-local':
    case 'container-local':
      return {
        configFilePath: `content/config/containers/${name}/${environment}.json`,
        configDefaultSettings: require(path.resolve(this.app_root, `content/container/${name}/config/settings`)),
      };
    default:
      throw new Error(`Invalid configuration type (${type}) [app,application,environment|ext,ext-local,extension,extension-local|con,con-local,container,container-local]`);
  }
}

function init(options) {
  return new Promise((resolve, reject) => {
    if (typeof options === 'string') {
      // crud_arg: `${argv.type},${argv.environment},${argv.name},${argv.filepath}`,
      var [type, name, environment, filepath] = options.split(',');
    } else {
      var { type, name, environment, filepath } = options;
    }
    const { configFilePath, configDefaultSettings } = getFilePath.call(this, { type, name, environment, filepath });
    resolve(fs.outputJSON(filepath, {
      filepath: configFilePath,
      environment,
      config: configDefaultSettings,
    }, { spaces: 2, }));
  });
}

module.exports = {
  create,
  remove,
  update,
  init,
};<commit_msg>fixed configjs typo for app root<commit_after>'use strict';
const fs = require('fs-extra');
const path = require('path');

function create(options) {
  return new Promise((resolve, reject) => {
    const createdat = Date.now();
    const updatedat = Date.now();
    const configurationDB = this.datas.get('configuration');
    try {
      if (typeof options === 'string') {
        fs.readJSON(path.resolve(options))
          .then(configJSON => {
            resolve(configurationDB.create({
              newdoc: Object.assign({},
                configJSON, {
                  createdat,
                  updatedat,
                }),
            }));
          })
          .catch(reject);
      } else {
        const { filepath, environment, container, config, } = options;
        resolve(configurationDB.create({
          newdoc: {
            filepath,
            environment,
            config,
            container,
            createdat,
            updatedat,
          },
        }));
      }
    } catch (e) {
      reject(e);
    }
  });
}

function update(options) {
  return new Promise((resolve, reject) => {
    const { config, _id, } = options;
    const createdat = Date.now();
    const updatedat = Date.now();
    const configurationDB = this.datas.get('configuration');
    try {
      resolve(configurationDB.update({
        updatedoc: Object.assign({},
          config,
          (_id) ? { _id, } : {}, {
            createdat,
            updatedat,
          }),
      }));
    } catch (e) {
      reject(e);
    }
  });
}

function remove(options) {
  return new Promise((resolve, reject) => {
    let { filepath, _id, id, } = options;
    const configurationDB = this.datas.get('configuration');
    try {
      if (typeof options === 'string') {
        id = options;
      }
      if (id || _id) {
        resolve(configurationDB.delete({
          id: id || _id,
        }));
      } else {
        configurationDB.load({ docid: 'filepath', query: filepath, })
          .then(result => {
            resolve(configurationDB.delete({ id: result._id, }));
          })
          .catch(reject);
      }
    } catch (e) {
      reject(e);
    }
  });
}

function getFilePath(options) {
  const { type, name, environment, filepath } = options;
  switch (type) {
    case 'app':
    case 'application':
    case 'environment':
      return {
        configFilePath: `content/config/environment/${environment}.json`,
        configDefaultSettings: Object.assign({}, this.settings, {
          extensions: {},
          container: {},
        }),
      };
    case 'ext':
    case 'extension':
      return {
        configFilePath: `content/config/extensions/${name}/${environment}.json`,
        configDefaultSettings: require(`${name}/config/settings`),
      };
    case 'ext-local':
    case 'extension-local':
      return {
        configFilePath: `content/config/extensions/${name}/${environment}.json`,
        configDefaultSettings: require(path.resolve(this.config.app_root, `content/extensions/${name}/config/settings`)),
      };
    case 'con':
    case 'container':
      return {
        configFilePath: `content/config/containers/${name}/${environment}.json`,
        configDefaultSettings: require(`${name}/config/settings`),
      };
    case 'con-local':
    case 'container-local':
      return {
        configFilePath: `content/config/containers/${name}/${environment}.json`,
        configDefaultSettings: require(path.resolve(this.config.app_root, `content/container/${name}/config/settings`)),
      };
    default:
      throw new Error(`Invalid configuration type (${type}) [app,application,environment|ext,ext-local,extension,extension-local|con,con-local,container,container-local]`);
  }
}

function init(options) {
  return new Promise((resolve, reject) => {
    if (typeof options === 'string') {
      // crud_arg: `${argv.type},${argv.environment},${argv.name},${argv.filepath}`,
      var [type, name, environment, filepath] = options.split(',');
    } else {
      var { type, name, environment, filepath } = options;
    }
    const { configFilePath, configDefaultSettings } = getFilePath.call(this, { type, name, environment, filepath });
    resolve(fs.outputJSON(filepath, {
      filepath: configFilePath,
      environment,
      config: configDefaultSettings,
    }, { spaces: 2, }));
  });
}

module.exports = {
  create,
  remove,
  update,
  init,
};<|endoftext|>


<commit_before>var Template = require('./template'),
	api = require('./api'),
	Context = require('./context');
/**
 * use current customTag content
 * @return {Template} current template
 */
Template.prototype.__yield = function() {
	return this.exec({
		dom: function(context, node) {
			var templ = context.data.opts && context.data.opts.__yield;
			if (!templ)
				return;
			return templ.call(node, context);
		},
		string: function(context, descriptor) {
			var templ = context.data.opts && context.data.opts.__yield;
			if (!templ)
				return;
			descriptor.children += templ.toHTMLString(context);
		}
	});
};

var customTags = {
	dom: function(context, args) {
		var ctx = new Context({
			opts: args[0]
		}, context);
		var ctr = args[1].toContainer(ctx).appendTo(this);
		ctr.context = ctx;
	},
	string: function(context, descriptor, args) {
		descriptor.children += args[1].toHTMLString(new Context({
			opts: args[0]
		}, context));
	},
	firstPass: function(context, args) {
		(context.children = context.children || []).push(new Context({
			opts: args[0]
		}, context));
	},
	secondPass: function(context, descriptor, args) {
		descriptor.children += args[1].toHTMLString(context.children.shift());
	}
};

/**
 * addCustomTag in specified api.
 * @param {[type]} apiName        [description]
 * @param {[type]} tagName        [description]
 * @param {[type]} defaultAttrMap [description]
 * @param {[type]} templ          [description]
 */
module.exports = function(apiName, tagName, defaultAttrMap, templ) {
	var space = api[apiName] = api[apiName] || {};
	space[tagName] = function(attrMap, __yield) {
		// copy default to attrMap
		for (var i in defaultAttrMap)
			if (typeof attrMap[i] === 'undefined')
				attrMap[i] = defaultAttrMap[i];
		attrMap.__yield = __yield;
		var args = [attrMap, templ];
		return this.exec(customTags, args);
	}
	return this;
};
<commit_msg>custom tags : follow container propagation<commit_after>var Template = require('./template'),
	api = require('./api'),
	Context = require('./context');
/**
 * use current customTag content
 * @return {Template} current template
 */
Template.prototype.__yield = function() {
	return this.exec({
		dom: function(context, node) {
			var templ = context.data.opts && context.data.opts.__yield;
			if (!templ)
				return;
			return templ.call(node, context);
		},
		string: function(context, descriptor) {
			var templ = context.data.opts && context.data.opts.__yield;
			if (!templ)
				return;
			descriptor.children += templ.toHTMLString(context);
		}
	});
};

var customTags = {
	dom: function(context, node, args, container) {
		var ctx = new Context({
			opts: args[0]
		}, context);
		var ctr = args[1].toContainer(ctx, container).appendTo(this);
		ctr.context = ctx;
	},
	string: function(context, descriptor, args) {
		descriptor.children += args[1].toHTMLString(new Context({
			opts: args[0]
		}, context));
	},
	firstPass: function(context, args) {
		(context.children = context.children || []).push(new Context({
			opts: args[0]
		}, context));
	},
	secondPass: function(context, descriptor, args) {
		descriptor.children += args[1].toHTMLString(context.children.shift());
	}
};

/**
 * addCustomTag in specified api.
 * @param {[type]} apiName        [description]
 * @param {[type]} tagName        [description]
 * @param {[type]} defaultAttrMap [description]
 * @param {[type]} templ          [description]
 */
module.exports = function(apiName, tagName, defaultAttrMap, templ) {
	var space = api[apiName] = api[apiName] || {};
	space[tagName] = function(attrMap, __yield) {
		// copy default to attrMap
		for (var i in defaultAttrMap)
			if (typeof attrMap[i] === 'undefined')
				attrMap[i] = defaultAttrMap[i];
		attrMap.__yield = __yield;
		var args = [attrMap, templ];
		return this.exec(customTags, args);
	}
	return this;
};
<|endoftext|>


<commit_before>var Utils     = require("./utils")
  , DAO       = require("./dao")
  , DataTypes = require("./data-types")
  , Util      = require('util')

module.exports = (function() {
  var DAOFactory = function(name, attributes, options) {
    var self = this

    this.options = Utils._.extend({
      timestamps: true,
      instanceMethods: {},
      classMethods: {},
      validate: {},
      freezeTableName: false,
      underscored: false,
      syncOnAssociation: true,
      paranoid: false,
      whereCollection: null
    }, options || {})

    this.name = name
    if (!this.options.tableName) {
      this.tableName = this.options.freezeTableName ? name : Utils.pluralize(name)
    } else {
      this.tableName = this.options.tableName
    }
    this.rawAttributes = attributes
    this.daoFactoryManager = null // defined in init function
    this.associations = {}

    // extract validation
    this.validate = this.options.validate || {}
  }

  Object.defineProperty(DAOFactory.prototype, 'attributes', {
    get: function() {
      return this.QueryGenerator.attributesToSQL(this.rawAttributes)
    }
  })

  Object.defineProperty(DAOFactory.prototype, 'QueryInterface', {
    get: function() { return this.daoFactoryManager.sequelize.getQueryInterface() }
  })

  Object.defineProperty(DAOFactory.prototype, 'QueryGenerator', {
    get: function() { return this.QueryInterface.QueryGenerator }
  })

  DAOFactory.prototype.init = function(daoFactoryManager) {
    var self = this;

    this.daoFactoryManager = daoFactoryManager

    this.primaryKeys = {};
    Utils._.each(this.attributes, function(dataTypeString, attributeName) {
      // If you don't specify a valid data type lets help you debug it
      if (dataTypeString === undefined) {
        throw new Error("Unrecognized data type for field " + attributeName );
      }

      if ((attributeName !== 'id') && (dataTypeString.indexOf('PRIMARY KEY') !== -1)) {
        self.primaryKeys[attributeName] = dataTypeString
      }
    })

    this.primaryKeyCount = Object.keys(this.primaryKeys).length;
    this.options.hasPrimaryKeys = this.hasPrimaryKeys = this.primaryKeyCount > 0;

    addDefaultAttributes.call(this)
    addOptionalClassMethods.call(this)
    findAutoIncrementField.call(this)

    // DAO prototype
    this.DAO = function() {
      DAO.apply(this, arguments);
    };
    Util.inherits(this.DAO, DAO);

    this.DAO.prototype.rawAttributes = this.rawAttributes;
    if (this.options.instanceMethods) {
      Utils._.each(this.options.instanceMethods, function(fct, name) {
        self.DAO.prototype[name] = fct
      })
    }
    this.DAO.prototype.attributes = Object.keys(this.DAO.prototype.rawAttributes);

    this.DAO.prototype.booleanValues = [];
    this.DAO.prototype.defaultValues = {};
    this.DAO.prototype.validators = {};
    Utils._.each(this.rawAttributes, function (definition, name) {
      if (((definition === DataTypes.BOOLEAN) || (definition.type === DataTypes.BOOLEAN))) {
        self.DAO.prototype.booleanValues.push(name);
      }
      if (definition.hasOwnProperty('defaultValue')) {
        self.DAO.prototype.defaultValues[name] = function() {
          return Utils.toDefaultValue(definition.defaultValue);
        }
      }

      if (definition.hasOwnProperty('validate')) {
        self.DAO.prototype.validators[name] = definition.validate;
      }
    });

    this.DAO.prototype.__factory = this;
    this.DAO.prototype.hasDefaultValues = !Utils._.isEmpty(this.DAO.prototype.defaultValues);

    return this
  }

  DAOFactory.prototype.sync = function(options) {
    options = Utils._.extend({}, this.options, options || {})

    var self = this
    return new Utils.CustomEventEmitter(function(emitter) {
      var doQuery = function() {
        self.QueryInterface
          .createTable(self.tableName, self.attributes, options)
          .success(function() { emitter.emit('success', self) })
          .error(function(err) { emitter.emit('error', err) })
          .on('sql', function(sql) { emitter.emit('sql', sql) })
      }

      if (options.force) {
        self.drop().success(doQuery).error(function(err) { emitter.emit('error', err) })
      } else {
        doQuery()
      }
    }).run()
  }

  DAOFactory.prototype.drop = function() {
    return this.QueryInterface.dropTable(this.tableName)
  }

  // alias for findAll
  DAOFactory.prototype.all = function(options) {
    return this.findAll(options)
  }

  DAOFactory.prototype.findAll = function(options) {
    var hasJoin = false
    var options = Utils._.clone(options)

    if (typeof options === 'object') {
      hasJoin = true

      if (options.hasOwnProperty('include')) {
        hasJoin = true

        options.include = options.include.map(function(include) {
          return validateIncludedElement.call(this, include)
        }.bind(this))
      }

      // whereCollection is used for non-primary key updates
      this.options.whereCollection = options.where || null
    }

    return this.QueryInterface.select(this, this.tableName, options, {
      type:    'SELECT',
      hasJoin: hasJoin
    })
  }

  //right now, the caller (has-many-double-linked) is in charge of the where clause
  DAOFactory.prototype.findAllJoin = function(joinTableName, options) {
    var optcpy = Utils._.clone(options)
    optcpy.attributes = optcpy.attributes || [Utils.addTicks(this.tableName)+".*"]

    // whereCollection is used for non-primary key updates
    this.options.whereCollection = optcpy.where || null;

    return this.QueryInterface.select(this, [this.tableName, joinTableName], optcpy, { type: 'SELECT' })
  }

 /**
  * Search for an instance.
  *
  * @param  {Object} options Options to describe the scope of the search.
  *   @param {Array} include A list of associations which shall get eagerly loaded. Supported is either { include: [ DaoFactory1, DaoFactory2, ...] } or { include: [ { daoFactory: DaoFactory1, as: 'Alias' } ] }.
  * @return {Object}         A promise which fires `success`, `error`, `complete` and `sql`.
  */
  DAOFactory.prototype.find = function(options) {
    var hasJoin = false

    // no options defined?
    // return an emitter which emits null
    if ([null, undefined].indexOf(options) !== -1) {
      return new Utils.CustomEventEmitter(function(emitter) {
        setTimeout(function() { emitter.emit('success', null) }, 10)
      }).run()
    }

    var primaryKeys = this.primaryKeys

    // options is not a hash but an id
    if (typeof options === 'number') {
      options = { where: options }
    } else if (Utils._.size(primaryKeys) && Utils.argsArePrimaryKeys(arguments, primaryKeys)) {
      var where = {}
        , self  = this
        , keys = Object.keys(primaryKeys)

      Utils._.each(arguments, function(arg, i) {
        var key = keys[i]
        where[key] = arg
      })

      options = { where: where }
    } else if (typeof options === 'string' && parseInt(options, 10).toString() === options) {
      var parsedId = parseInt(options, 10)

      if (!Utils._.isFinite(parsedId)) {
        throw new Error('Invalid argument to find(). Must be an id or an options object.')
      }

      options = { where: parsedId }
    } else if (typeof options === 'object') {
      options = Utils._.clone(options)

      if (options.hasOwnProperty('include')) {
        hasJoin = true

        options.include = options.include.map(function(include) {
          return validateIncludedElement.call(this, include)
        }.bind(this))
      }

      // whereCollection is used for non-primary key updates
      this.options.whereCollection = options.where || null
    }

    options.limit = 1

    return this.QueryInterface.select(this, this.tableName, options, {
      plain: true,
      type: 'SELECT',
      hasJoin: hasJoin
    })
  }

  DAOFactory.prototype.count = function(options) {
    options = Utils._.extend({ attributes: [] }, options || {})
    options.attributes.push(['count(*)', 'count'])
    options.parseInt = true

    return this.QueryInterface.rawSelect(this.tableName, options, 'count')
  }

  DAOFactory.prototype.findAndCountAll = function(options) {
    var self  = this
      , copts = Utils._.extend({}, options || {})

    // no limit, offset, order or include for the options given to count()
    copts.offset   = 0;
    copts.limit    = 0;
    copts.order    = null;
    copts.include  = null;

    return new Utils.CustomEventEmitter(function (emitter) {
      var emit = {
          err  : function(e) {        // emit error
            emitter.emit('error', e);
          }
        , okay : function(c, r) {     // emit success
            emitter.emit('success', {
              count: c || 0,
              rows : (r && Array.isArray(r) ? r : [])
            });
          }
        , sql  : function(s) {        // emit SQL
            emitter.emit('sql', s);
          }
      };

      self.count(copts)
          .on('sql', emit.sql)
          .error(emit.err)
          .success(function(cnt) {
            if (cnt === 0)
              return emit.okay(cnt); // no records, no need for another query

            self.findAll(options)
                .on('sql', emit.sql)
                .error(emit.err)
                .success(function(rows) {
                   emit.okay(cnt, rows)
                })
          });

    }).run();
  }

  DAOFactory.prototype.max = function(field, options) {
    options = Utils._.extend({ attributes: [] }, options || {})
    options.attributes.push(['max(' + field + ')', 'max'])
    options.parseInt = true

    return this.QueryInterface.rawSelect(this.tableName, options, 'max')
  }
  DAOFactory.prototype.min = function(field, options) {
    options = Utils._.extend({ attributes: [] }, options || {})
    options.attributes.push(['min(' + field + ')', 'min'])
    options.parseInt = true

    return this.QueryInterface.rawSelect(this.tableName, options, 'min')
  }

  DAOFactory.prototype.build = function(values, options) {
    options = options || { isNewRecord: true }

    var self     = this
      , instance = new this.DAO(values, this.options, options.isNewRecord)

    instance.isNewRecord    = options.isNewRecord
    instance.daoFactoryName = this.name
    instance.daoFactory     = this

    return instance
  }

  DAOFactory.prototype.create = function(values, fields) {
    return this.build(values).save(fields)
  }

  DAOFactory.prototype.findOrCreate = function (params, defaults) {
    var self = this;

    return new Utils.CustomEventEmitter(function (emitter) {
      self.find({
        where: params
      }).success(function (instance) {
        if (instance === null) {
          for (var attrname in defaults) {
            params[attrname] = defaults[attrname]
          }

          self.create(params)
            .success(function (instance) {
              emitter.emit('success', instance)
            })
            .error( function (error) {
              emitter.emit('error', error)
            })
        } else {
          emitter.emit('success', instance)
        }
      }).error(function (error) {
        emitter.emit('error', error)
      });
    }).run()
  }

  // private

  var query = function() {
    var args      = Utils._.map(arguments, function(arg, _) { return arg })
      , sequelize = this.daoFactoryManager.sequelize

    // add this as the second argument
    if (arguments.length === 1) {
      args.push(this)
    }

    // add {} as options
    if (args.length === 2) {
      args.push({})
    }

    return sequelize.query.apply(sequelize, args)
  }

  var addOptionalClassMethods = function() {
    var self = this
    Utils._.each(this.options.classMethods || {}, function(fct, name) { self[name] = fct })
  }

  var addDefaultAttributes = function() {
    var self              = this
      , defaultAttributes = {
        id: {
          type: DataTypes.INTEGER,
          allowNull: false,
          primaryKey: true,
          autoIncrement: true
        }
      }

    if (this.hasPrimaryKeys) {
      defaultAttributes = {}
    }

    if (this.options.timestamps) {
      defaultAttributes[Utils._.underscoredIf('createdAt', this.options.underscored)] = {type: DataTypes.DATE, allowNull: false}
      defaultAttributes[Utils._.underscoredIf('updatedAt', this.options.underscored)] = {type: DataTypes.DATE, allowNull: false}

      if (this.options.paranoid)
        defaultAttributes[Utils._.underscoredIf('deletedAt', this.options.underscored)] = {type: DataTypes.DATE}
    }

    Utils._.each(defaultAttributes, function(value, attr) {
      self.rawAttributes[attr] = value
    })
  }

  var findAutoIncrementField = function() {
    var fields = this.QueryGenerator.findAutoIncrementField(this)

    this.autoIncrementField = null

    fields.forEach(function(field) {
      if (this.autoIncrementField) {
        throw new Error('Invalid DAO definition. Only one autoincrement field allowed.')
      } else {
        this.autoIncrementField = field
      }
    }.bind(this))
  }

  var validateIncludedElement = function(include) {
    if (include instanceof DAOFactory) {
      include = { daoFactory: include, as: include.tableName }
    }

    if (typeof include === 'object') {
      if (include.hasOwnProperty('model')) {
        include.daoFactory = include.model
        delete include.model
      }

      if (include.hasOwnProperty('daoFactory') && (include.hasOwnProperty('as'))) {
        var usesAlias   = (include.as !== include.daoFactory.tableName)
          , association = (usesAlias ? this.getAssociationByAlias(include.as) : this.getAssociation(include.daoFactory))

        // check if the current daoFactory is actually associated with the passed daoFactory
        if (!!association && (!association.options.as || (association.options.as === include.as))) {
          include.association = association

          return include
        } else {
          var msg = include.daoFactory.name

          if (usesAlias) {
            msg += " (" + include.as + ")"
          }

          msg += " is not associated to " + this.name + "!"

          throw new Error(msg)
        }
      } else {
        throw new Error('Include malformed. Expected attributes: daoFactory, as!')
      }
    } else {
      throw new Error('Include unexpected. Element has to be either an instance of DAOFactory or an object.')
    }
  }

  Utils._.extend(DAOFactory.prototype, require("./associations/mixin"))

  return DAOFactory
})()
<commit_msg>improve option handling ("deep" clone of the *where* property) in findAndCountAll() so that generating the "count" query does not break the generated "select" query (due to the query generator overwriting the options *where* property, e.g. from `["name LIKE ?", "foo%"]` to `["foo%"]`)<commit_after>var Utils     = require("./utils")
  , DAO       = require("./dao")
  , DataTypes = require("./data-types")
  , Util      = require('util')

module.exports = (function() {
  var DAOFactory = function(name, attributes, options) {
    var self = this

    this.options = Utils._.extend({
      timestamps: true,
      instanceMethods: {},
      classMethods: {},
      validate: {},
      freezeTableName: false,
      underscored: false,
      syncOnAssociation: true,
      paranoid: false,
      whereCollection: null
    }, options || {})

    this.name = name
    if (!this.options.tableName) {
      this.tableName = this.options.freezeTableName ? name : Utils.pluralize(name)
    } else {
      this.tableName = this.options.tableName
    }
    this.rawAttributes = attributes
    this.daoFactoryManager = null // defined in init function
    this.associations = {}

    // extract validation
    this.validate = this.options.validate || {}
  }

  Object.defineProperty(DAOFactory.prototype, 'attributes', {
    get: function() {
      return this.QueryGenerator.attributesToSQL(this.rawAttributes)
    }
  })

  Object.defineProperty(DAOFactory.prototype, 'QueryInterface', {
    get: function() { return this.daoFactoryManager.sequelize.getQueryInterface() }
  })

  Object.defineProperty(DAOFactory.prototype, 'QueryGenerator', {
    get: function() { return this.QueryInterface.QueryGenerator }
  })

  DAOFactory.prototype.init = function(daoFactoryManager) {
    var self = this;

    this.daoFactoryManager = daoFactoryManager

    this.primaryKeys = {};
    Utils._.each(this.attributes, function(dataTypeString, attributeName) {
      // If you don't specify a valid data type lets help you debug it
      if (dataTypeString === undefined) {
        throw new Error("Unrecognized data type for field " + attributeName );
      }

      if ((attributeName !== 'id') && (dataTypeString.indexOf('PRIMARY KEY') !== -1)) {
        self.primaryKeys[attributeName] = dataTypeString
      }
    })

    this.primaryKeyCount = Object.keys(this.primaryKeys).length;
    this.options.hasPrimaryKeys = this.hasPrimaryKeys = this.primaryKeyCount > 0;

    addDefaultAttributes.call(this)
    addOptionalClassMethods.call(this)
    findAutoIncrementField.call(this)

    // DAO prototype
    this.DAO = function() {
      DAO.apply(this, arguments);
    };
    Util.inherits(this.DAO, DAO);

    this.DAO.prototype.rawAttributes = this.rawAttributes;
    if (this.options.instanceMethods) {
      Utils._.each(this.options.instanceMethods, function(fct, name) {
        self.DAO.prototype[name] = fct
      })
    }
    this.DAO.prototype.attributes = Object.keys(this.DAO.prototype.rawAttributes);

    this.DAO.prototype.booleanValues = [];
    this.DAO.prototype.defaultValues = {};
    this.DAO.prototype.validators = {};
    Utils._.each(this.rawAttributes, function (definition, name) {
      if (((definition === DataTypes.BOOLEAN) || (definition.type === DataTypes.BOOLEAN))) {
        self.DAO.prototype.booleanValues.push(name);
      }
      if (definition.hasOwnProperty('defaultValue')) {
        self.DAO.prototype.defaultValues[name] = function() {
          return Utils.toDefaultValue(definition.defaultValue);
        }
      }

      if (definition.hasOwnProperty('validate')) {
        self.DAO.prototype.validators[name] = definition.validate;
      }
    });

    this.DAO.prototype.__factory = this;
    this.DAO.prototype.hasDefaultValues = !Utils._.isEmpty(this.DAO.prototype.defaultValues);

    return this
  }

  DAOFactory.prototype.sync = function(options) {
    options = Utils._.extend({}, this.options, options || {})

    var self = this
    return new Utils.CustomEventEmitter(function(emitter) {
      var doQuery = function() {
        self.QueryInterface
          .createTable(self.tableName, self.attributes, options)
          .success(function() { emitter.emit('success', self) })
          .error(function(err) { emitter.emit('error', err) })
          .on('sql', function(sql) { emitter.emit('sql', sql) })
      }

      if (options.force) {
        self.drop().success(doQuery).error(function(err) { emitter.emit('error', err) })
      } else {
        doQuery()
      }
    }).run()
  }

  DAOFactory.prototype.drop = function() {
    return this.QueryInterface.dropTable(this.tableName)
  }

  // alias for findAll
  DAOFactory.prototype.all = function(options) {
    return this.findAll(options)
  }

  DAOFactory.prototype.findAll = function(options) {
    var hasJoin = false
    var options = Utils._.clone(options)

    if (typeof options === 'object') {
      hasJoin = true

      if (options.hasOwnProperty('include')) {
        hasJoin = true

        options.include = options.include.map(function(include) {
          return validateIncludedElement.call(this, include)
        }.bind(this))
      }

      // whereCollection is used for non-primary key updates
      this.options.whereCollection = options.where || null
    }

    return this.QueryInterface.select(this, this.tableName, options, {
      type:    'SELECT',
      hasJoin: hasJoin
    })
  }

  //right now, the caller (has-many-double-linked) is in charge of the where clause
  DAOFactory.prototype.findAllJoin = function(joinTableName, options) {
    var optcpy = Utils._.clone(options)
    optcpy.attributes = optcpy.attributes || [Utils.addTicks(this.tableName)+".*"]

    // whereCollection is used for non-primary key updates
    this.options.whereCollection = optcpy.where || null;

    return this.QueryInterface.select(this, [this.tableName, joinTableName], optcpy, { type: 'SELECT' })
  }

 /**
  * Search for an instance.
  *
  * @param  {Object} options Options to describe the scope of the search.
  *   @param {Array} include A list of associations which shall get eagerly loaded. Supported is either { include: [ DaoFactory1, DaoFactory2, ...] } or { include: [ { daoFactory: DaoFactory1, as: 'Alias' } ] }.
  * @return {Object}         A promise which fires `success`, `error`, `complete` and `sql`.
  */
  DAOFactory.prototype.find = function(options) {
    var hasJoin = false

    // no options defined?
    // return an emitter which emits null
    if ([null, undefined].indexOf(options) !== -1) {
      return new Utils.CustomEventEmitter(function(emitter) {
        setTimeout(function() { emitter.emit('success', null) }, 10)
      }).run()
    }

    var primaryKeys = this.primaryKeys

    // options is not a hash but an id
    if (typeof options === 'number') {
      options = { where: options }
    } else if (Utils._.size(primaryKeys) && Utils.argsArePrimaryKeys(arguments, primaryKeys)) {
      var where = {}
        , self  = this
        , keys = Object.keys(primaryKeys)

      Utils._.each(arguments, function(arg, i) {
        var key = keys[i]
        where[key] = arg
      })

      options = { where: where }
    } else if (typeof options === 'string' && parseInt(options, 10).toString() === options) {
      var parsedId = parseInt(options, 10)

      if (!Utils._.isFinite(parsedId)) {
        throw new Error('Invalid argument to find(). Must be an id or an options object.')
      }

      options = { where: parsedId }
    } else if (typeof options === 'object') {
      options = Utils._.clone(options)

      if (options.hasOwnProperty('include')) {
        hasJoin = true

        options.include = options.include.map(function(include) {
          return validateIncludedElement.call(this, include)
        }.bind(this))
      }

      // whereCollection is used for non-primary key updates
      this.options.whereCollection = options.where || null
    }

    options.limit = 1

    return this.QueryInterface.select(this, this.tableName, options, {
      plain: true,
      type: 'SELECT',
      hasJoin: hasJoin
    })
  }

  DAOFactory.prototype.count = function(options) {
    options = Utils._.extend({ attributes: [] }, options || {})
    options.attributes.push(['count(*)', 'count'])
    options.parseInt = true

    return this.QueryInterface.rawSelect(this.tableName, options, 'count')
  }

  DAOFactory.prototype.findAndCountAll = function(options) {
    // this 'options cloner' is a bit hacky, should probably
    // be somewhere more central -- we essentailly need this
    // because in certain cases the "where" property of an options
    // object is clobbered (shallow clone does not help) by a method named
    // "getWhereConditions" (I think)
    var clone = function(v, repls) {
      if (Utils._.isObject(v)) {
        v = Utils._.clone(v);

        if (Utils._.isObject(v.where))
          v.where = Utils._.clone(v.where);
      }

      if (Utils._.isObject(repls))
        v = Utils._.extend({}, v || {}, repls);

      return v;
    };

    var self  = this
      , opts  = clone(options)
      , copts = clone(options, {
          // no limit, offset, order or include for the options given to count()
          offset   : 0,
          limit    : 0,
          order    : null,
          include  : null
      })

    return new Utils.CustomEventEmitter(function (emitter) {
      var emit = {
          err  : function(e) {        // emit error
            emitter.emit('error', e);
          }
        , okay : function(c, r) {     // emit success
            emitter.emit('success', {
              count: c || 0,
              rows : (r && Array.isArray(r) ? r : [])
            });
          }
        , sql  : function(s) {        // emit SQL
            emitter.emit('sql', s);
          }
      };

      self.count(copts)
          .on('sql', emit.sql)
          .error(emit.err)
          .success(function(cnt) {
            if (cnt === 0)
              return emit.okay(cnt); // no records, no need for another query

            self.findAll(options)
                .on('sql', emit.sql)
                .error(emit.err)
                .success(function(rows) {
                   emit.okay(cnt, rows)
                })
          });

    }).run();
  }

  DAOFactory.prototype.max = function(field, options) {
    options = Utils._.extend({ attributes: [] }, options || {})
    options.attributes.push(['max(' + field + ')', 'max'])
    options.parseInt = true

    return this.QueryInterface.rawSelect(this.tableName, options, 'max')
  }
  DAOFactory.prototype.min = function(field, options) {
    options = Utils._.extend({ attributes: [] }, options || {})
    options.attributes.push(['min(' + field + ')', 'min'])
    options.parseInt = true

    return this.QueryInterface.rawSelect(this.tableName, options, 'min')
  }

  DAOFactory.prototype.build = function(values, options) {
    options = options || { isNewRecord: true }

    var self     = this
      , instance = new this.DAO(values, this.options, options.isNewRecord)

    instance.isNewRecord    = options.isNewRecord
    instance.daoFactoryName = this.name
    instance.daoFactory     = this

    return instance
  }

  DAOFactory.prototype.create = function(values, fields) {
    return this.build(values).save(fields)
  }

  DAOFactory.prototype.findOrCreate = function (params, defaults) {
    var self = this;

    return new Utils.CustomEventEmitter(function (emitter) {
      self.find({
        where: params
      }).success(function (instance) {
        if (instance === null) {
          for (var attrname in defaults) {
            params[attrname] = defaults[attrname]
          }

          self.create(params)
            .success(function (instance) {
              emitter.emit('success', instance)
            })
            .error( function (error) {
              emitter.emit('error', error)
            })
        } else {
          emitter.emit('success', instance)
        }
      }).error(function (error) {
        emitter.emit('error', error)
      });
    }).run()
  }

  // private

  var query = function() {
    var args      = Utils._.map(arguments, function(arg, _) { return arg })
      , sequelize = this.daoFactoryManager.sequelize

    // add this as the second argument
    if (arguments.length === 1) {
      args.push(this)
    }

    // add {} as options
    if (args.length === 2) {
      args.push({})
    }

    return sequelize.query.apply(sequelize, args)
  }

  var addOptionalClassMethods = function() {
    var self = this
    Utils._.each(this.options.classMethods || {}, function(fct, name) { self[name] = fct })
  }

  var addDefaultAttributes = function() {
    var self              = this
      , defaultAttributes = {
        id: {
          type: DataTypes.INTEGER,
          allowNull: false,
          primaryKey: true,
          autoIncrement: true
        }
      }

    if (this.hasPrimaryKeys) {
      defaultAttributes = {}
    }

    if (this.options.timestamps) {
      defaultAttributes[Utils._.underscoredIf('createdAt', this.options.underscored)] = {type: DataTypes.DATE, allowNull: false}
      defaultAttributes[Utils._.underscoredIf('updatedAt', this.options.underscored)] = {type: DataTypes.DATE, allowNull: false}

      if (this.options.paranoid)
        defaultAttributes[Utils._.underscoredIf('deletedAt', this.options.underscored)] = {type: DataTypes.DATE}
    }

    Utils._.each(defaultAttributes, function(value, attr) {
      self.rawAttributes[attr] = value
    })
  }

  var findAutoIncrementField = function() {
    var fields = this.QueryGenerator.findAutoIncrementField(this)

    this.autoIncrementField = null

    fields.forEach(function(field) {
      if (this.autoIncrementField) {
        throw new Error('Invalid DAO definition. Only one autoincrement field allowed.')
      } else {
        this.autoIncrementField = field
      }
    }.bind(this))
  }

  var validateIncludedElement = function(include) {
    if (include instanceof DAOFactory) {
      include = { daoFactory: include, as: include.tableName }
    }

    if (typeof include === 'object') {
      if (include.hasOwnProperty('model')) {
        include.daoFactory = include.model
        delete include.model
      }

      if (include.hasOwnProperty('daoFactory') && (include.hasOwnProperty('as'))) {
        var usesAlias   = (include.as !== include.daoFactory.tableName)
          , association = (usesAlias ? this.getAssociationByAlias(include.as) : this.getAssociation(include.daoFactory))

        // check if the current daoFactory is actually associated with the passed daoFactory
        if (!!association && (!association.options.as || (association.options.as === include.as))) {
          include.association = association

          return include
        } else {
          var msg = include.daoFactory.name

          if (usesAlias) {
            msg += " (" + include.as + ")"
          }

          msg += " is not associated to " + this.name + "!"

          throw new Error(msg)
        }
      } else {
        throw new Error('Include malformed. Expected attributes: daoFactory, as!')
      }
    } else {
      throw new Error('Include unexpected. Element has to be either an instance of DAOFactory or an object.')
    }
  }

  Utils._.extend(DAOFactory.prototype, require("./associations/mixin"))

  return DAOFactory
})()
<|endoftext|>


<commit_before>var levelup = require('levelup')
,   streams = require('./streams')
,   db

function DataStreams(fileName) {
    // this need calback
    if (!(this instanceof DataStreams))
        return new DataStreams(fileName)
    db = levelup(fileName, { valueEncoding: 'json' });
    this.db = db // this is just for testing
}

DataStreams.prototype.addObject = function(type, unique, options) {
    // this will be depricated I'd imagine
    var node = type + '!' + unique
    console.log('node', node)
    db.put(node, options, function (err) {
        if (err) return console.log('Ooops!', err)
    })
}

DataStreams.prototype.stream = function(opt) {
    return db.createReadStream(opt)
}

DataStreams.prototype.createStream = function(arrayOfObjects, callback) {
    var endpoint = arrayOfObjects[arrayOfObjects.length - 1]
    ,   stream = buildStream(arrayOfObjects)
    if (callback) callback(new DataStream(stream))
    return new DataStream(stream, endpoint)
}

// Data stream functin object and methods
function DataStream(stream, endpoint) {
    if (!(this instanceof DataStream))
        return new DataStream(stream, endpoint)

    this.stream = stream
    this.endpoint = endpoint
}

DataStream.prototype.addData = function(components, endData) {
    // return and callback ? yess
    var uniques = buildStream(components)
    ,   stream = this.stream + uniques
    db.put(stream, endData, function (err) {
        if (err) return console.log('Ooops!', err)
    })
}

DataStream.prototype.addStreamingData = function() {
    console.log('adding streaming data')
}

DataStream.prototype.simpleStream = function(start, end) {
    // callback Maybe build this optionals different
    var newStreamArray = []
    ,   streamStart = this.stream
    ,   streamEnd = streamEnd = this.stream + '\xff'
    if (start) streamStart = this.stream + start
    if (end) streamEnd = this.stream + '\xff'
    return db.createReadStream({start: streamStart, end: streamEnd})
}

DataStream.prototype.linkedStreamToObject = function(start, end, callback) {
    // this will need a return and callback - set up options here with default (everywher)
    var newStreamArray = []
    ,   streamStart = this.stream
    ,   streamEnd = streamEnd = this.stream + '\xff'
    ,   endpoint = this.endpoint
    if (start) streamStart = this.stream + start
    if (end) streamEnd = this.stream + '\xff'
    var source = db.createReadStream({start: streamStart, end: streamEnd})

    return new streams.LinkedStreamToObject(db, source, endpoint)
}

DataStream.prototype.linkedStreamToStream = function(dataStream, start, end) {
    var streamStart = this.stream
    ,   streamEnd = streamEnd = this.stream + '\xff'
    ,   stream = dataStream.stream
    if (start) streamStart = this.stream + start
    if (end) streamEnd = this.stream + end + '\xff'
    var source = db.createReadStream({start: streamStart, end: streamEnd})
    return new streams.LinkedStreamToStream(db, source, stream)

}

function _readStream(start, callback) {
    var end = start + '\xff'
    ,   results = []
    db.createReadStream({start: start, end: end})
        .on('data', function (data) {results.push(data)})
        .on('close', function () {return callback(null, results[0])})
}

function buildStream(arrayOfObjects) {
    if(typeof arrayOfObjects == 'string') return arrayOfObjects + '!'
    var stream = ''
    for (var i in arrayOfObjects) {
        var key = arrayOfObjects[i]
        stream += key + '!'
    }
    return stream

}

exports.DataStreams = DataStreams<commit_msg>cleaning up unneeded code<commit_after>var levelup = require('levelup')
,   streams = require('./streams')
,   db

function DataStreams(fileName) {
    // this need calback
    if (!(this instanceof DataStreams))
        return new DataStreams(fileName)
    db = levelup(fileName, { valueEncoding: 'json' });
    this.db = db // this is just for testing
}

DataStreams.prototype.addObject = function(type, unique, options) {
    // this will be depricated I'd imagine
    var node = type + '!' + unique
    console.log('node', node)
    db.put(node, options, function (err) {
        if (err) return console.log('Ooops!', err)
    })
}

DataStreams.prototype.stream = function(opt) {
    return db.createReadStream(opt)
}

DataStreams.prototype.createStream = function(arrayOfObjects, callback) {
    var endpoint = arrayOfObjects[arrayOfObjects.length - 1]
    ,   stream = buildStream(arrayOfObjects)
    if (callback) callback(new DataStream(stream))
    return new DataStream(stream, endpoint)
}

// Data stream functin object and methods
function DataStream(stream, endpoint) {
    if (!(this instanceof DataStream))
        return new DataStream(stream, endpoint)

    this.stream = stream
    this.endpoint = endpoint
}

DataStream.prototype.addData = function(components, endData) {
    // return and callback ? yess
    var uniques = buildStream(components)
    ,   stream = this.stream + uniques
    db.put(stream, endData, function (err) {
        if (err) return console.log('Ooops!', err)
    })
}

DataStream.prototype.addStreamingData = function() {
    console.log('adding streaming data')
}

DataStream.prototype.simpleStream = function(start, end) {
    // callback Maybe build this optionals different
    var newStreamArray = []
    ,   streamStart = this.stream
    ,   streamEnd = streamEnd = this.stream + '\xff'
    if (start) streamStart = this.stream + start
    if (end) streamEnd = this.stream + '\xff'
    return db.createReadStream({start: streamStart, end: streamEnd})
}

DataStream.prototype.linkedStreamToObject = function(start, end, callback) {
    // this will need a return and callback - set up options here with default (everywher)
    var newStreamArray = []
    ,   streamStart = this.stream
    ,   streamEnd = streamEnd = this.stream + '\xff'
    ,   endpoint = this.endpoint
    if (start) streamStart = this.stream + start
    if (end) streamEnd = this.stream + '\xff'
    var source = db.createReadStream({start: streamStart, end: streamEnd})

    return new streams.LinkedStreamToObject(db, source, endpoint)
}

DataStream.prototype.linkedStreamToStream = function(dataStream, start, end) {
    var streamStart = this.stream
    ,   streamEnd = streamEnd = this.stream + '\xff'
    ,   stream = dataStream.stream
    if (start) streamStart = this.stream + start
    if (end) streamEnd = this.stream + end + '\xff'
    var source = db.createReadStream({start: streamStart, end: streamEnd})
    return new streams.LinkedStreamToStream(db, source, stream)

}

function buildStream(arrayOfObjects) {
    if(typeof arrayOfObjects == 'string') return arrayOfObjects + '!'
    var stream = ''
    for (var i in arrayOfObjects) {
        var key = arrayOfObjects[i]
        stream += key + '!'
    }
    return stream

}

exports.DataStreams = DataStreams<|endoftext|>