<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: 'kalabox-engine-docker@0.10.5',
  engineRepo: 'kalabox',
  codeDir: 'code',
  services: 'kalabox-services-kalabox@0.10.4',
  apps: [
    'kalabox-app-pantheon@0.10.6'
  ],
  profile: 'standard',
  sharing: true,
  stats: {
    report: true,
    url: 'http://stats.kalabox.biz'
  },
  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-dev',
    'kalabox-syncthing',
    'kalabox-app-pantheon'
  ],
  configSources: [
    'DEFAULT_GLOBAL_CONFIG'
  ],
  shareIgnores: [
    '*.7z',
    '*.bz2',
    '*.dmg',
    '*.gz',
    '*.iso',
    '*.jar',
    '*.rar',
    '*.tar',
    '*.tgz',
    '*.un~',
    '*.zip',
    '.*.swp',
    '.*DS_Store',
    '.DS_Store*',
    '._*',
    '.sass-cache',
    'Icon',
    'Thumbs.db',
    'ehthumbs.db'
  ]
};

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',
  'shareIgnores'
];

function mixIn(a, b) {
  for (var key in b) {
    var shouldConcat = _.contains(KEYS_TO_CONCAT, key);
    if (shouldConcat) {
      // Concat.
      if (_.isArray(a[key]) && _.isArray(b[key])) {
        a[key] = _.uniq(a[key].concat(b[key]));
        a[key].sort();
      } else {
        a[key] = 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() {

  // Grab the kbox version
  var packageJson = getPackageJson();
  var kboxVersion = packageJson.version;

  // Grab the provision file path
  var provisionedFile = path.join(env.getSysConfRoot(), 'provisioned');

  // Grab the installed file
  var iF = path.join(env.getSysConfRoot(), 'installed.json');
  var cI = (fs.existsSync(iF)) ? require(iF) : {KALABOX_VERSION:kboxVersion};

  // Check whether we are in a binary or not
  var isBinary = (process.isPackaged || process.IsEmbedded) ? true : false;

  return {
    isBinary: isBinary,
    needsUpdates: (cI.KALABOX_VERSION !== kboxVersion),
    devMode: env.getDevMode(),
    provisioned: fs.existsSync(provisionedFile),
    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: kboxVersion,
    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);
  var appConfigOverride = function(key, val) {
    if (!appConfigFile[key]) {
      appConfigFile[key] = val;
    }
  };

  appConfigOverride('appRoot', appRoot);
  appConfigOverride('appCidsRoot', ':sysConfRoot:' + path.sep + 'appcids');
  appConfigOverride('codeRoot', ':appRoot:' + path.sep + ':codeDir:');
  var retVal = mixIn(globalConfig, appConfigFile);
  logDebug('CONFIG => App config loaded.', retVal);
  return retVal;
};
<commit_msg>Upgrade backends and apps for imminent 0.10.5 release<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: 'kalabox-engine-docker@0.10.6',
  engineRepo: 'kalabox',
  codeDir: 'code',
  services: 'kalabox-services-kalabox@0.10.5',
  apps: [
    'kalabox-app-pantheon@0.10.7'
  ],
  profile: 'standard',
  sharing: true,
  stats: {
    report: true,
    url: 'http://stats.kalabox.biz'
  },
  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-dev',
    'kalabox-syncthing',
    'kalabox-app-pantheon'
  ],
  configSources: [
    'DEFAULT_GLOBAL_CONFIG'
  ],
  shareIgnores: [
    '*.7z',
    '*.bz2',
    '*.dmg',
    '*.gz',
    '*.iso',
    '*.jar',
    '*.rar',
    '*.tar',
    '*.tgz',
    '*.un~',
    '*.zip',
    '.*.swp',
    '.*DS_Store',
    '.DS_Store*',
    '._*',
    '.sass-cache',
    'Icon',
    'Thumbs.db',
    'ehthumbs.db'
  ]
};

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',
  'shareIgnores'
];

function mixIn(a, b) {
  for (var key in b) {
    var shouldConcat = _.contains(KEYS_TO_CONCAT, key);
    if (shouldConcat) {
      // Concat.
      if (_.isArray(a[key]) && _.isArray(b[key])) {
        a[key] = _.uniq(a[key].concat(b[key]));
        a[key].sort();
      } else {
        a[key] = 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() {

  // Grab the kbox version
  var packageJson = getPackageJson();
  var kboxVersion = packageJson.version;

  // Grab the provision file path
  var provisionedFile = path.join(env.getSysConfRoot(), 'provisioned');

  // Grab the installed file
  var iF = path.join(env.getSysConfRoot(), 'installed.json');
  var cI = (fs.existsSync(iF)) ? require(iF) : {KALABOX_VERSION:kboxVersion};

  // Check whether we are in a binary or not
  var isBinary = (process.isPackaged || process.IsEmbedded) ? true : false;

  return {
    isBinary: isBinary,
    needsUpdates: (cI.KALABOX_VERSION !== kboxVersion),
    devMode: env.getDevMode(),
    provisioned: fs.existsSync(provisionedFile),
    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: kboxVersion,
    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);
  var appConfigOverride = function(key, val) {
    if (!appConfigFile[key]) {
      appConfigFile[key] = val;
    }
  };

  appConfigOverride('appRoot', appRoot);
  appConfigOverride('appCidsRoot', ':sysConfRoot:' + path.sep + 'appcids');
  appConfigOverride('codeRoot', ':appRoot:' + path.sep + ':codeDir:');
  var retVal = mixIn(globalConfig, appConfigFile);
  logDebug('CONFIG => App config loaded.', retVal);
  return retVal;
};
<|endoftext|>


<commit_before>import d3 from 'd3'
import {dimensionLabelTitle} from './labels'
import {capitalize} from 'lodash'

// Generate CSV for downloading and drawing in TableChart.jsx
export function generateCSV(incomingData) {
  if (!incomingData || !incomingData.rows) {
    return {}
  }

  const data = Object.assign({}, incomingData, {
    dimensions: incomingData.dimensions.map(item => item.name),
    rows: incomingData.rows.slice()
  })

  let csv = ''
  const separator = ';'

  // We need at least two dimensions to make our table
  if (data.dimensions.length < 2) {
    csv = `Error\nNeed at least two dimensions\nGot: ['${data.dimensions.join(',')}']`
    return {csv: csv, separator: separator}
  }

  // This key will be used to create the first columns (usually 'region')
  const leftcolumnKey = data.dimensions[0]

  // See 04-befolkning_alder-fylke-2014.csv for the format we are constructing
  const nester = d3.nest()
    .key(item => item[leftcolumnKey])
    .sortKeys(d3.ascending)
    .key(item => data.dimensions.join(','))

  const rows = nester.entries(data.rows)

  // Headers
  // Begin the CSV with the left column and its name
  // example:
  // "region;Navn;"
  csv += `${capitalize(leftcolumnKey)}${separator}Navn${separator}`

  // Done with the left colum
  data.dimensions.shift()
  // Collect any other dimensions

  data.dimensions.forEach((dimension, rowIndex) => {
    const dimensions = []
    if (rowIndex > 0) {
      // The first line in csv has "leftcolumnKey;Navn;"" already
      // so the other rows need to make space for them by inserting blank
      // cells in those two positions
      dimensions.push('')
      dimensions.push('')
    }
    // Now we add the labelized dimension name
    rows[0].values[0].values.forEach(row => {
      dimensions.push(`${dimensionLabelTitle(dimension)}: ${dimensionLabelTitle(dimension, row[dimension])}`)
    })
    csv += `${dimensions.join(separator)}\n`
    // here csv would be
    // region;Navn;dimension1;dimension2;etc\n
    // after the first pass, then
    // ;;variableName1;variableName2;etc\n
    // ;;variableName1;variableName2;etc\n
    // for the rest of the dimensions/their variables
  })

  // CSV is now probably like this:
  // region;Navn;dimension1;dimension2;etc\n
  // ;;variableName1;variableName2;etc\n

  // Now, for every data row, nested by the dimensions...
  rows.forEach(dimension => {
    // Add the first two columns, which in our example are
    // K0301;Oslo
    const firstTwoColumns = [dimension.key, dimensionLabelTitle(leftcolumnKey, dimension.key)]
    csv += firstTwoColumns.join(separator)
    // append the rest of the columns, which are the actual values, example
    // ;12,39,etc\n
    const values = dimension.values[0].values.map(row => row.tabellvariabel)
    csv += `;${values.join(separator)}\n`
  })

  // CSV is now like this:
  // region;Navn;dimension1;dimension2;etc\n
  // ;;variableName1;variableName2;etc\n
  // K0301;Oslo;12;39;etc\n
  // K1505;Kristiansund;9;7;etc\n
  return {csv: csv, separator: separator}
}
<commit_msg>Sort rows along the year axis as well<commit_after>import d3 from 'd3'
import {dimensionLabelTitle} from './labels'
import {capitalize} from 'lodash'

// Generate CSV for downloading and drawing in TableChart.jsx
export function generateCSV(incomingData) {
  if (!incomingData || !incomingData.rows) {
    return {}
  }

  const data = Object.assign({}, incomingData, {
    dimensions: incomingData.dimensions.map(item => item.name),
    rows: incomingData.rows.slice()
  })

  let csv = ''
  const separator = ';'

  // We need at least two dimensions to make our table
  if (data.dimensions.length < 2) {
    csv = `Error\nNeed at least two dimensions\nGot: ['${data.dimensions.join(',')}']`
    return {csv: csv, separator: separator}
  }

  // This key will be used to create the first columns (usually 'region')
  const leftcolumnKey = data.dimensions[0]

  function compareItems(itemA, itemB) {
    const yearA = Number(itemA.aar)
    const yearB = Number(itemB.aar)
    if (yearA == yearB) {
      return itemB[leftcolumnKey] < itemA[leftcolumnKey] ? 1 : -1
    }
    return yearA < yearB ? -1 : 1
  }

  // See 04-befolkning_alder-fylke-2014.csv for the format we are constructing
  const nester = d3.nest()
    .key(item => item[leftcolumnKey])
    .sortKeys(d3.ascending)
    .sortValues(compareItems)
    .key(item => data.dimensions.join(','))

  const rows = nester.entries(data.rows)

  // Headers
  // Begin the CSV with the left column and its name
  // example:
  // "region;Navn;"
  csv += `${capitalize(leftcolumnKey)}${separator}Navn${separator}`

  // Done with the left colum
  data.dimensions.shift()

  // Collect any other dimensions
  data.dimensions.forEach((dimension, rowIndex) => {
    const dimensions = []
    if (rowIndex > 0) {
      // The first line in csv has "leftcolumnKey;Navn;"" already
      // so the other rows need to make space for them by inserting blank
      // cells in those two positions
      dimensions.push('')
      dimensions.push('')
    }
    // Now we add the labelized dimension name
    rows[0].values[0].values.forEach(row => {
      dimensions.push(`${dimensionLabelTitle(dimension)}: ${dimensionLabelTitle(dimension, row[dimension])}`)
    })

    csv += `${dimensions.join(separator)}\n`
    // here csv would be
    // region;Navn;dimension1;dimension2;etc\n
    // after the first pass, then
    // ;;variableName1;variableName2;etc\n
    // ;;variableName1;variableName2;etc\n
    // for the rest of the dimensions/their variables
  })

  // CSV is now probably like this:
  // region;Navn;dimension1;dimension2;etc\n
  // ;;variableName1;variableName2;etc\n

  // Now, for every data row, nested by the dimensions...
  rows.forEach(dimension => {
    // Add the first two columns, which in our example are
    // K0301;Oslo
    const firstTwoColumns = [dimension.key, dimensionLabelTitle(leftcolumnKey, dimension.key)]
    csv += firstTwoColumns.join(separator)
    // append the rest of the columns, which are the actual values, example
    // ;12,39,etc\n
    const values = dimension.values[0].values.map(row => row.tabellvariabel)
    // How can this work if years are not the same length??????
    csv += `;${values.join(separator)}\n`
  })

  // CSV is now like this:
  // region;Navn;dimension1;dimension2;etc\n
  // ;;variableName1;variableName2;etc\n
  // K0301;Oslo;12;39;etc\n
  // K1505;Kristiansund;9;7;etc\n
  return {csv: csv, separator: separator}
}
<|endoftext|>


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

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,
      paranoid: false
    }, options || {})

    this.name = name
    this.tableName = this.options.freezeTableName ? name : Utils.pluralize(name)
    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 }
  })

  Object.defineProperty(DAOFactory.prototype, 'primaryKeyCount', {
    get: function() { return Utils._.keys(this.primaryKeys).length }
  })

  Object.defineProperty(DAOFactory.prototype, 'hasPrimaryKeys', {
    get: function() { return this.primaryKeyCount > 0 }
  })

  DAOFactory.prototype.init = function(daoFactoryManager) {
    this.daoFactoryManager = daoFactoryManager

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

    return this
  }

  DAOFactory.prototype.sync = function(options) {
    options = Utils.merge(options || {}, this.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('failure', err) })
          .on('sql', function(sql) { emitter.emit('sql', sql) })
      }

      if(options.force)
        self.drop().success(doQuery).error(function(err) { emitter.emit('failure', 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) {
    return this.QueryInterface.select(this, this.tableName, options)
  }

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

    return this.QueryInterface.select(this, [this.tableName, joinTableName], optcpy)
  }

  DAOFactory.prototype.find = function(options) {
    if([null, undefined].indexOf(options) > -1) {
      var NullEmitter = require("./emitters/null-emitter")
      return new NullEmitter()
    }

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

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

        options = { where: where }
    }

    options.limit = 1

    return this.QueryInterface.select(this, this.tableName, options, {plain: true})
  }

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

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

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

    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'])

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

  DAOFactory.prototype.build = function(values, options) {
    var instance = new DAO(values, Utils._.extend(this.options, this.attributes, { hasPrimaryKeys: this.hasPrimaryKeys }))
      , self     = this

    options = options || {}
    instance.__factory = this

    Utils._.each(this.attributes, function(definition, name) {
      //transform integer 0,1 into boolean
      if(definition.indexOf(DataTypes.BOOLEAN) !== -1 && typeof instance[name] === "number") {
        instance[name] = (instance[name] === 0) ? false : true;
      }

      //add default attributes
      if(typeof instance[name] == 'undefined') {
        var value = null

        if(self.rawAttributes.hasOwnProperty(name) && self.rawAttributes[name].hasOwnProperty('defaultValue')) {
            value = self.rawAttributes[name].defaultValue
        }

        instance[name] = value
        instance.addAttribute(name, value)
      }
      // add validation
      if (self.rawAttributes.hasOwnProperty(name) && self.rawAttributes[name].hasOwnProperty('validate')) {
        instance.setValidators(name, self.rawAttributes[name].validate)
      }
    })
    Utils._.each(this.options.instanceMethods || {}, function(fct, name) { instance[name] = fct })
    Utils._.each(this.associations, function(association, associationName) {
      association.injectGetter(instance)
      association.injectSetter(instance)
    })

    instance.isNewRecord = options.hasOwnProperty('isNewRecord') ? options.isNewRecord : true

    return instance
  }

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

  DAOFactory.prototype.__defineGetter__('primaryKeys', function() {
    var result = {}
    Utils._.each(this.attributes, function(dataTypeString, attributeName) {
      if((attributeName != 'id') && (dataTypeString.indexOf('PRIMARY KEY') > -1))
        result[attributeName] = dataTypeString
    })

    return result
  })

  // private

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

    // add this as the second argument
    if(arguments.length == 1) args.push(this)
    return s.query.apply(s, 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 self   = this
      , fields = this.QueryGenerator.findAutoIncrementField(this)

    this.autoIncrementField = null

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

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

  return DAOFactory
})()
<commit_msg>improved logic<commit_after>var Utils     = require("./utils")
  , DAO       = require("./dao")
  , DataTypes = require("./data-types")

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,
      paranoid: false
    }, options || {})

    this.name = name
    this.tableName = this.options.freezeTableName ? name : Utils.pluralize(name)
    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 }
  })

  Object.defineProperty(DAOFactory.prototype, 'primaryKeyCount', {
    get: function() { return Utils._.keys(this.primaryKeys).length }
  })

  Object.defineProperty(DAOFactory.prototype, 'hasPrimaryKeys', {
    get: function() { return this.primaryKeyCount > 0 }
  })

  DAOFactory.prototype.init = function(daoFactoryManager) {
    this.daoFactoryManager = daoFactoryManager

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

    return this
  }

  DAOFactory.prototype.sync = function(options) {
    options = Utils.merge(options || {}, this.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('failure', err) })
          .on('sql', function(sql) { emitter.emit('sql', sql) })
      }

      if(options.force)
        self.drop().success(doQuery).error(function(err) { emitter.emit('failure', 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) {
    return this.QueryInterface.select(this, this.tableName, options)
  }

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

    return this.QueryInterface.select(this, [this.tableName, joinTableName], optcpy)
  }

  DAOFactory.prototype.find = function(options) {
    if([null, undefined].indexOf(options) > -1) {
      var NullEmitter = require("./emitters/null-emitter")
      return new NullEmitter()
    }

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

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

        options = { where: where }
    }

    options.limit = 1

    return this.QueryInterface.select(this, this.tableName, options, {plain: true})
  }

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

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

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

    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'])

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

  DAOFactory.prototype.build = function(values, options) {
    var instance = new DAO(values, Utils._.extend(this.options, this.attributes, { hasPrimaryKeys: this.hasPrimaryKeys }))
      , self     = this

    options = options || {}
    instance.__factory = this

    Utils._.each(this.attributes, function(definition, name) {
      //transform integer 0,1 into boolean
      if((definition.indexOf(DataTypes.BOOLEAN) !== -1) && (typeof instance[name] === "number")) {
        instance[name] = (instance[name] !== 0)
      }

      //add default attributes
      if(typeof instance[name] == 'undefined') {
        var value = null

        if(self.rawAttributes.hasOwnProperty(name) && self.rawAttributes[name].hasOwnProperty('defaultValue')) {
            value = self.rawAttributes[name].defaultValue
        }

        instance[name] = value
        instance.addAttribute(name, value)
      }
      // add validation
      if (self.rawAttributes.hasOwnProperty(name) && self.rawAttributes[name].hasOwnProperty('validate')) {
        instance.setValidators(name, self.rawAttributes[name].validate)
      }
    })
    Utils._.each(this.options.instanceMethods || {}, function(fct, name) { instance[name] = fct })
    Utils._.each(this.associations, function(association, associationName) {
      association.injectGetter(instance)
      association.injectSetter(instance)
    })

    instance.isNewRecord = options.hasOwnProperty('isNewRecord') ? options.isNewRecord : true

    return instance
  }

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

  DAOFactory.prototype.__defineGetter__('primaryKeys', function() {
    var result = {}
    Utils._.each(this.attributes, function(dataTypeString, attributeName) {
      if((attributeName != 'id') && (dataTypeString.indexOf('PRIMARY KEY') > -1))
        result[attributeName] = dataTypeString
    })

    return result
  })

  // private

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

    // add this as the second argument
    if(arguments.length == 1) args.push(this)
    return s.query.apply(s, 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 self   = this
      , fields = this.QueryGenerator.findAutoIncrementField(this)

    this.autoIncrementField = null

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

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

  return DAOFactory
})()
<|endoftext|>


<commit_before>'use strict';

var BluebirdPromise = require('bluebird');
var Class = require('../util/class');
var Query = require('./query');

/**
 * @since 1.0
 * @public
 * @constructor
 */
var Database = Class.extend(/** @lends Database# */{

  /**
   * Create a new database.
   *
   * @alias Database
   * @param {Object} connection The connection information.
   * @param {String} connection.adapter The adapter to use. Possible choices
   * are:
   *   - pg
   *   - mysql
   *   - sqlite
   * @param {String} connection.database The database to connect to.
   * @param {String} connection.username The username to connect with.
   * @param {String} connection.password The password to connect with.
   */
  init: function(connection) {
    if (!connection) { throw new Error('Missing connection information.'); }

    var Adapter;
    if (connection.adapter && typeof connection.adapter.__class__ === 'function') {
      Adapter = connection.adapter;
    }
    if (!Adapter) {
      try { Adapter = require('./adapters/' + connection.adapter); }
      catch (e) {
        if (e.code === 'MODULE_NOT_FOUND') {
          throw new Error('No adapter found for ' + connection.adapter);
        }
        else { throw e; }
      }
    }
    this._adapter = Adapter.create();
    this._query = Query.create(this._adapter);

    this._ready = BluebirdPromise.bind(this)
    .then(function() {
      return this._adapter.connect(connection);
    })
    .then(function() { return this; });
  },

  /**
   * Ensure the database is ready.
   *
   * @return {Promise} A promise that resolves with the database instance
   * when the database is fully connected.
   */
  ready: function() {
    return this._ready;
  },

  /**
   * Disconnect from the database.
   *
   * @return {Promise} A promise indicating that the database has been
   * disconnected.
   */
  disconnect: function() {
    return this._adapter.disconnect();
  }
});

/**
 * Documentation forthcoming.
 *
 * @private
 * @function Database~query
 */
var query = function(name) {
  return function() {
    return this._query[name].apply(this._query, arguments);
  };
};

Database.reopen(/** @lends Database# */{
  /**
   * Documentation forthcoming.
   *
   * @since 1.0
   * @public
   * @method
   */
  select: query('select')
});

module.exports = Database.reopenClass({ __name__: 'Database' });
<commit_msg>Added query accessor & documentation.<commit_after>'use strict';

var BluebirdPromise = require('bluebird');
var Class = require('../util/class');
var Query = require('./query');

/**
 * @since 1.0
 * @public
 * @constructor
 */
var Database = Class.extend(/** @lends Database# */{

  /**
   * Create a new database.
   *
   * @alias Database
   * @param {Object} connection The connection information.
   * @param {String} connection.adapter The adapter to use. Possible choices
   * are:
   *   - pg
   *   - mysql
   *   - sqlite
   * @param {String} connection.database The database to connect to.
   * @param {String} connection.username The username to connect with.
   * @param {String} connection.password The password to connect with.
   */
  init: function(connection) {
    if (!connection) { throw new Error('Missing connection information.'); }

    var Adapter;
    if (connection.adapter && typeof connection.adapter.__class__ === 'function') {
      Adapter = connection.adapter;
    }
    if (!Adapter) {
      try { Adapter = require('./adapters/' + connection.adapter); }
      catch (e) {
        if (e.code === 'MODULE_NOT_FOUND') {
          throw new Error('No adapter found for ' + connection.adapter);
        }
        else { throw e; }
      }
    }
    this._adapter = Adapter.create();
    this._query = Query.create(this._adapter);

    this._ready = BluebirdPromise.bind(this)
    .then(function() {
      return this._adapter.connect(connection);
    })
    .then(function() { return this; });
  },

  /**
   * Ensure the database is ready.
   *
   * @return {Promise} A promise that resolves with the database instance
   * when the database is fully connected.
   */
  ready: function() {
    return this._ready;
  },

  /**
   * Disconnect from the database.
   *
   * @return {Promise} A promise indicating that the database has been
   * disconnected.
   */
  disconnect: function() {
    return this._adapter.disconnect();
  }
});

/**
 * Documentation forthcoming.
 *
 * @private
 * @function Database~query
 */
var query = function(name) {
  return function() {
    return this._query[name].apply(this._query, arguments);
  };
};

/**
 * Access to a query object that is tied to this database.
 *
 * @name Database#query
 * @since 1.0
 * @public
 * @type {Query}
 * @readonly
 */
Database.defineAccessor('query');

Database.reopen(/** @lends Database# */ {

  /**
   * Shortcut for `db.query.select()`.
   *
   * @since 1.0
   * @public
   * @method
   * @see {@link Database#query}
   * @see {@link Query#select}
   */
  select: query('select')

});

module.exports = Database.reopenClass({ __name__: 'Database' });
<|endoftext|>


<commit_before>'use strict';

const Sugar = require('sugar');

const validators = require('./validators');

class Declaration {
	static parse(declaration) {
		const
			resName = `res${Date.now().toString(36)}${Sugar.Number.random(1000000000, 10000000000).toString(36)}`,
			code = `
const global = null;
let ${resName} = null;

function package(name) {
	${resName} = {name};

	const
		dependencies = (...names) => {${resName}.dependencies = names;},
		ext = (name) => {${resName}.parent = name; return {dependencies};};

	return {extends: ext, dependencies};
}

${declaration};

return ${resName};
`;

		return new this(Function(code)());
	}

	constructor(declaration) {
		if (typeof declaration === 'string') {
			return this.constructor.parse(declaration);
		}

		const {name, parent, dependencies} = validators.declaration(declaration);

		this.name = name;
		this.parent = parent;
		this.dependencies = dependencies;
	}

	toJSON() {
		return Sugar.Object.select(this, ['name', 'parent', 'dependencies']);
	}

	toString() {
		let res = `package('${this.name}')`;

		if (this.parent) {
			res += `\n	.extends('${this.parent}')`;
		}

		if (this.dependencies.length) {
			res += `\n	.dependencies('${this.dependencies.join(`', '`)}')`;
		}

		return `${res};`;
	}
}

module.exports = Declaration;
<commit_msg>optional test before parse<commit_after>'use strict';

const Sugar = require('sugar');

const validators = require('./validators');

class Declaration {
	static parse(declaration, test = false) {
		if (test && !/package\(/.test(declaration)) {
			return null;
		}

		const
			resName = `res${Date.now().toString(36)}${Sugar.Number.random(1000000000, 10000000000).toString(36)}`,
			code = `
const global = null;
let ${resName} = null;

function package(name) {
	${resName} = {name};

	const
		dependencies = (...names) => {${resName}.dependencies = names;},
		ext = (name) => {${resName}.parent = name; return {dependencies};};

	return {extends: ext, dependencies};
}

${declaration};

return ${resName};
`;

		return new this(Function(code)());
	}

	constructor(declaration) {
		if (typeof declaration === 'string') {
			return this.constructor.parse(declaration);
		}

		const {name, parent, dependencies} = validators.declaration(declaration);

		this.name = name;
		this.parent = parent;
		this.dependencies = dependencies;
	}

	toJSON() {
		return Sugar.Object.select(this, ['name', 'parent', 'dependencies']);
	}

	toString() {
		let res = `package('${this.name}')`;

		if (this.parent) {
			res += `\n	.extends('${this.parent}')`;
		}

		if (this.dependencies.length) {
			res += `\n	.dependencies('${this.dependencies.join(`', '`)}')`;
		}

		return `${res};`;
	}
}

module.exports = Declaration;
<|endoftext|>


<commit_before>/**
 * @Class : main
 * realiza desnho de um cubo 3d
 */
var main = function () {
    /**
     * @define canvas poroperts
     */
    var CANVAS = document.getElementById("canvas_cube");
        CANVAS.width  = window.innerWidth;
        CANVAS.height = window.innerHeight;

   /** Capturar eventos do mouse **/

    var AMORTIZATION = 0.95;
    var drag = false;

    var old_x, old_y;
    var dX = 0, dY = 0;

    var mouseDown = function (e) {
        drag = true;

        old_x = e.pageX;
        old_y = e.pageY;

        e.preventDefault();
        return false;
    };

    var mouseUp = function (e) {
        drag = false;
    };

    var mouseMove = function (e) {
        if (!drag) return false;

        dX = (e.pageX - old_x) * 2 * Math.PI / CANVAS.width;
        dY = (e.pageY - old_y) * 2 * Math.PI / CANVAS.height;

        THETA += dX;
        PHI += dY;

        old_x = e.pageX;
        old_y = e.pageY;

        e.preventDefault();
    };

    CANVAS.addEventListener("mousedown", mouseDown, false);
    CANVAS.addEventListener("mousemove", mouseMove, false);
    CANVAS.addEventListener("mouseout", mouseUp, false);
    CANVAS.addEventListener("mouseup", mouseUp, false);

    CANVAS.addEventListener("touchstart", mouseDown, false);
    CANVAS.addEventListener("touchmove", mouseMove, false);
    //CANVAS.addEventListener("touchcancel", mouseUp, false);
    CANVAS.addEventListener("touchleave", mouseUp, false);
    CANVAS.addEventListener("touchend", mouseUp, false);

    /** Obtem contexto WebGL **/
    // esta variavel é o ponto de acesso com a lib
    var GL;
    //atribuimos a variavel GL todas as funconalidades da biblioteca webgl
    try {
        /**
         * @method getContext
         * Obtem o contexto de WebGL
         * @param {string} contextType
         *  "2d" => para contexto 2D que representa um contexto de renderização bidimensional
         *  "WebGL" ou "experimental-WebGL" => para objeto que representa um contexto de renderização tridimensional
         *  "Webgl2" ou "experimental-webgl2" =>  para objeto que representa um contexto de renderização tridimensional
         * @param {object} contextAttributes
         *  "antialias" => habilita a suavilização na criacao do contexto WebGL
         */
        GL = CANVAS.getContext("experimental-webgl", {antialias: true});
    } catch (e) {
        alert("Seu navegador nao tem suporte para WebGL.");
        return false;
    }

     /** Shaders **/

    /**
     * @declare : shaders
     * shaders sao pedaços de códigos compilados por WebGL e executados sem dipositivo grafo
     **/

    /**
     * @attribute : shader_vertex_source
     * é executado a cada vertice do cubo, como um sombreador.
     * calcula a posicao do ponto sobre a tela de visualização
     * gl_Position é dado em coordenadas
     */

    var shader_vertex_source = "\n\
        attribute vec3 position;\n\
        uniform mat4 Pmatrix;\n\
        uniform mat4 Vmatrix; //Vmatrix é a matrix de movimento dos objetos para exibição\n\
        uniform mat4 Mmatrix; //Mmatrix é a matrix de movimento do cubo\n\
        attribute vec3 color; //a cor do ponto dado como um vetor RGB\n\
        varying vec3 vColor;  //usado para dar cor ao fragmento shader\n\
        void main(void) { //funcao pre-construtora\n\
        gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.);\n\
        vColor=color; //vColor é interpolado entre os pontos do cubo/triangulo\n\
    }";

    /**
     * @attribute : shader_fragment_source (ou pixel)
     * é executado a cada pixel redenrizado.
     * retona a cor RGBA do pixel com o gl_FragColor
     */
    var shader_fragment_source = "\n\
        precision mediump float;\n\
        varying vec3 vColor; //obtemos a cor do vertice shader com essa variavel\n\
        void main(void) {\n\
        gl_FragColor = vec4(vColor, 1.); //atribui a cor do pixel para vColor com um compomente de alpha=1 (totalmete opaco)\n\
    }";

    /**
     * @method : getShader
     * usado para compilar um sombreador
     * @param {string} source Códido a ser compilado
     * @param {object} type tipo do objeto referenciado pala biblioteca WebGL
     * @param {string} typeString string descrevendo o tipo do codigo
     */
    var get_shader = function (source, type, typeString) {

        var shader = GL.createShader(type);

        GL.shaderSource(shader, source);
        GL.compileShader(shader);

        if (!GL.getShaderParameter(shader, GL.COMPILE_STATUS)) {
            alert("ERRO EM " + typeString + " SHADER : " + GL.getShaderInfoLog(shader));
            return false;
        }

        return shader;
    };
    // compilacao do vertice
    var shader_vertex = get_shader(shader_vertex_source, GL.VERTEX_SHADER, "VERTEX");
    // compilacao do fragmento/aresta/pixel
    var shader_fragment = get_shader(shader_fragment_source, GL.FRAGMENT_SHADER, "FRAGMENT");

    // criacao do programa shader
    var SHADER_PROGRAM = GL.createProgram();
    GL.attachShader(SHADER_PROGRAM, shader_vertex);
    GL.attachShader(SHADER_PROGRAM, shader_fragment);
    // vinculacao do programa shader ao WebGL
    GL.linkProgram(SHADER_PROGRAM);

    //obtem os atributos GLSL e os atribui as variaveis
    var _Pmatrix = GL.getUniformLocation(SHADER_PROGRAM, "Pmatrix");
    var _Vmatrix = GL.getUniformLocation(SHADER_PROGRAM, "Vmatrix");
    var _Mmatrix = GL.getUniformLocation(SHADER_PROGRAM, "Mmatrix");
    var _color   = GL.getAttribLocation(SHADER_PROGRAM, "color");
    var _position= GL.getAttribLocation(SHADER_PROGRAM, "position");

    //ativa atributos GLSL
    GL.enableVertexAttribArray(_color);
    GL.enableVertexAttribArray(_position);

    // diz ao contexto WebGL para usar o programa SHADER_PROGRAM para fazer as renderizações na tela
    GL.useProgram(SHADER_PROGRAM);

    /** O Cubo **/

    /**
     * @attribute : cube_vertex
     * define os vertices do cubo
     */
    var cube_vertex = [
       // face : posterior // cor : amarelo
       -1,-1,-1,    1,1,0,
        1,-1,-1,    1,1,0,
        1, 1,-1,    1,1,0,
       -1, 1,-1,    1,1,0,

       // face : frontal // cor : azul
       -1,-1, 1,    0,0,1,
        1,-1, 1,    0,0,1,
        1, 1, 1,    0,0,1,
       -1, 1, 1,    0,0,1,

       // face : esquerda // cor : ciano
       -1,-1,-1,    0,1,1,
       -1, 1,-1,    0,1,1,
       -1, 1, 1,    0,1,1,
       -1,-1, 1,    0,1,1,

       // face : direita // cor : vermelho
        1,-1,-1,    1,0,0,
        1, 1,-1,    1,0,0,
        1, 1, 1,    1,0,0,
        1,-1, 1,    1,0,0,

       // face : inferior // cor : roxo
       -1,-1,-1,    1,0,1,
       -1,-1, 1,    1,0,1,
        1,-1, 1,    1,0,1,
        1,-1,-1,    1,0,1,

       // face : superior // cor : verde
       -1, 1,-1,    0,1,0,
       -1, 1, 1,    0,1,0,
        1, 1, 1,    0,1,0,
        1, 1,-1,    0,1,0
    ];

    /**
     * @attribute : @global CUBE_VERTEX
     * define um VBO com as coordenadas do cubo
     * Vertex Buffer of Object => array de vertices WebGL
     */
    var CUBE_VERTEX = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, CUBE_VERTEX);
    GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(cube_vertex), GL.STATIC_DRAW);

    /**
     * @attribute : cube_faces
     * usa os pontos de triangulos como indices par construir um cuboGL
     * 2 triangulos para cada face
     */
    var cube_faces = [
        0, 1, 2,  // face de posterior
        0, 2, 3,

        4, 5, 6,  // face frontal
        4, 6, 7,

        8, 9, 10, // face esquerda
        8,10, 11,

        12,13,14, // face direita
        12,14,15,

        16,17,18, // face superior
        16,18,19,

        20,21,22, // face inferior
        20,22,23
    ];

    /**
     * @attribute : @global CUBE_FACES
     * define um VBO com as coordenadas das faces do cubo
     * Vertex Buffer of Object => array de vertices WebGL
     */
    var CUBE_FACES = GL.createBuffer();
    GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, CUBE_FACES);
    GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, new Uint16Array(cube_faces), GL.STATIC_DRAW);

    /**
     * @attribute : @global PROJMATRIX
     * Obtem a matri projeção em Z
     * 40 é o angulo da camera em graus
     * a camera só mostra pixes entre zMax e zMin
     */
    var PROJMATRIX = LIBS.get_projection(40, CANVAS.width / CANVAS.height, 1, 100);
    /**
     * @attribute : @global MOVEMATRIX
     * Matrix de movmentos do cubo
     * Iniciada como matrix identidade
     */
    var MOVEMATRIX = LIBS.get_I4();
    /**
     * @attribute : @global MOVEMATRIX
     * Matrix de movmentos de visualizacao do objeto
     * Iniciada como matrix identidade
     */
    var VIEWMATRIX = LIBS.get_I4();

    // translada em -6
    LIBS.translateZ(VIEWMATRIX, -6);
    var THETA = 0, PHI = 0;

    /** Desenho **/
    GL.enable(GL.DEPTH_TEST);
    GL.depthFunc(GL.LEQUAL);
    //define cor clara e transparente
    GL.clearColor(0.0, 0.0, 0.0, 0.0);
    GL.clearDepth(1.0);

    var time_old = 0;
    /**
     * @method animate
     * responsavel por desenhar a cena
     */
    var animate = function (time) {

        var dt = time - time_old;

        if (!drag) {
            dX *= AMORTIZATION;
            dY *= AMORTIZATION;
            THETA += dX, PHI += dY;
        }

        LIBS.set_I4(MOVEMATRIX);
        LIBS.rotateY(MOVEMATRIX, THETA);
        LIBS.rotateX(MOVEMATRIX, PHI);

        time_old = time;

        // define a area de desenho np canvas e limpa-a
        GL.viewport(0.0, 0.0, CANVAS.width, CANVAS.height);
        GL.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);

        GL.uniformMatrix4fv(_Pmatrix, false, PROJMATRIX);
        GL.uniformMatrix4fv(_Vmatrix, false, VIEWMATRIX);
        GL.uniformMatrix4fv(_Mmatrix, false, MOVEMATRIX);

        // usa esses pontos par ao proximo desenho
        GL.bindBuffer(GL.ARRAY_BUFFER, CUBE_VERTEX);
        //GL.vertexAttribPointer(variavel,dimensao,tipo,normalizador,tamnho total do vertice em bytes,deslocamento)
        GL.vertexAttribPointer(_position, 3, GL.FLOAT, false, 4 * (3 + 3), 0);
        //GL.vertexAttribPointer(variavel,dimensao,tipo,normalizador,tamnho total do vertice em bytes,deslocamento)
        GL.vertexAttribPointer(_color, 3, GL.FLOAT, false, 4 * (3 + 3), 3 * 4);

        GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, CUBE_FACES);
        // desenha o cubo
        // chama os 12 triangulos do cubo
        // 6 faces * 2 triangulo por face * 3 pontos por triangulo
        GL.drawElements(GL.TRIANGLES, 6 * 2 * 3, GL.UNSIGNED_SHORT, 0);

        // [ . . . ] // poderia criar mais objetos aqui

        // desnho esta terminado, pronto para renderizar
        GL.flush();

        // redesenha a cena assim que pronta
        window.requestAnimationFrame(animate);
    };
    // pela primeira vez que executado nao tem animação, por isso zero
    animate(0);
};
<commit_msg>Update script.js<commit_after>/**
 * @Class : main
 * realiza desnho de um cubo 3d
 */
var main = function () {
    /**
     * @define canvas poroperts
     */
    var CANVAS = document.getElementById("canvas_cube");
        CANVAS.width  = window.innerWidth;
        CANVAS.height = window.innerHeight;

   /** Capturar eventos do mouse **/

    var AMORTIZATION = 0.95;
    var drag = false;

    var old_x, old_y;
    var dX = 0, dY = 0;

    var mouseDown = function (e) {
        drag = true;

        old_x = e.pageX;
        old_y = e.pageY;

        e.preventDefault();
        return false;
    };

    var mouseUp = function (e) {
        drag = false;
    };

    var mouseMove = function (e) {
        if (!drag) return false;

        dX = (e.pageX - old_x) * 2 * Math.PI / CANVAS.width;
        dY = (e.pageY - old_y) * 2 * Math.PI / CANVAS.height;

        THETA += dX;
        PHI += dY;

        old_x = e.pageX;
        old_y = e.pageY;

        e.preventDefault();
    };

    CANVAS.addEventListener("mousedown", mouseDown, false);
    CANVAS.addEventListener("mousemove", mouseMove, false);
    CANVAS.addEventListener("mouseout", mouseUp, false);
    CANVAS.addEventListener("mouseup", mouseUp, false);

    CANVAS.addEventListener("touchstart", mouseDown, false);
    CANVAS.addEventListener("touchmove", mouseMove, false);
    CANVAS.addEventListener("touchcancel", mouseUp, false);
    CANVAS.addEventListener("touchleave", mouseUp, false);
    CANVAS.addEventListener("touchend", mouseUp, false);

    /** Obtem contexto WebGL **/
    // esta variavel é o ponto de acesso com a lib
    var GL;
    //atribuimos a variavel GL todas as funconalidades da biblioteca webgl
    try {
        /**
         * @method getContext
         * Obtem o contexto de WebGL
         * @param {string} contextType
         *  "2d" => para contexto 2D que representa um contexto de renderização bidimensional
         *  "WebGL" ou "experimental-WebGL" => para objeto que representa um contexto de renderização tridimensional
         *  "Webgl2" ou "experimental-webgl2" =>  para objeto que representa um contexto de renderização tridimensional
         * @param {object} contextAttributes
         *  "antialias" => habilita a suavilização na criacao do contexto WebGL
         */
        GL = CANVAS.getContext("experimental-webgl", {antialias: true});
    } catch (e) {
        alert("Seu navegador nao tem suporte para WebGL.");
        return false;
    }

     /** Shaders **/

    /**
     * @declare : shaders
     * shaders sao pedaços de códigos compilados por WebGL e executados sem dipositivo grafo
     **/

    /**
     * @attribute : shader_vertex_source
     * é executado a cada vertice do cubo, como um sombreador.
     * calcula a posicao do ponto sobre a tela de visualização
     * gl_Position é dado em coordenadas
     */

    var shader_vertex_source = "\n\
        attribute vec3 position;\n\
        uniform mat4 Pmatrix;\n\
        uniform mat4 Vmatrix; //Vmatrix é a matrix de movimento dos objetos para exibição\n\
        uniform mat4 Mmatrix; //Mmatrix é a matrix de movimento do cubo\n\
        attribute vec3 color; //a cor do ponto dado como um vetor RGB\n\
        varying vec3 vColor;  //usado para dar cor ao fragmento shader\n\
        void main(void) { //funcao pre-construtora\n\
        gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(position, 1.);\n\
        vColor=color; //vColor é interpolado entre os pontos do cubo/triangulo\n\
    }";

    /**
     * @attribute : shader_fragment_source (ou pixel)
     * é executado a cada pixel redenrizado.
     * retona a cor RGBA do pixel com o gl_FragColor
     */
    var shader_fragment_source = "\n\
        precision mediump float;\n\
        varying vec3 vColor; //obtemos a cor do vertice shader com essa variavel\n\
        void main(void) {\n\
        gl_FragColor = vec4(vColor, 1.); //atribui a cor do pixel para vColor com um compomente de alpha=1 (totalmete opaco)\n\
    }";

    /**
     * @method : getShader
     * usado para compilar um sombreador
     * @param {string} source Códido a ser compilado
     * @param {object} type tipo do objeto referenciado pala biblioteca WebGL
     * @param {string} typeString string descrevendo o tipo do codigo
     */
    var get_shader = function (source, type, typeString) {

        var shader = GL.createShader(type);

        GL.shaderSource(shader, source);
        GL.compileShader(shader);

        if (!GL.getShaderParameter(shader, GL.COMPILE_STATUS)) {
            alert("ERRO EM " + typeString + " SHADER : " + GL.getShaderInfoLog(shader));
            return false;
        }

        return shader;
    };
    // compilacao do vertice
    var shader_vertex = get_shader(shader_vertex_source, GL.VERTEX_SHADER, "VERTEX");
    // compilacao do fragmento/aresta/pixel
    var shader_fragment = get_shader(shader_fragment_source, GL.FRAGMENT_SHADER, "FRAGMENT");

    // criacao do programa shader
    var SHADER_PROGRAM = GL.createProgram();
    GL.attachShader(SHADER_PROGRAM, shader_vertex);
    GL.attachShader(SHADER_PROGRAM, shader_fragment);
    // vinculacao do programa shader ao WebGL
    GL.linkProgram(SHADER_PROGRAM);

    //obtem os atributos GLSL e os atribui as variaveis
    var _Pmatrix = GL.getUniformLocation(SHADER_PROGRAM, "Pmatrix");
    var _Vmatrix = GL.getUniformLocation(SHADER_PROGRAM, "Vmatrix");
    var _Mmatrix = GL.getUniformLocation(SHADER_PROGRAM, "Mmatrix");
    var _color   = GL.getAttribLocation(SHADER_PROGRAM, "color");
    var _position= GL.getAttribLocation(SHADER_PROGRAM, "position");

    //ativa atributos GLSL
    GL.enableVertexAttribArray(_color);
    GL.enableVertexAttribArray(_position);

    // diz ao contexto WebGL para usar o programa SHADER_PROGRAM para fazer as renderizações na tela
    GL.useProgram(SHADER_PROGRAM);

    /** O Cubo **/

    /**
     * @attribute : cube_vertex
     * define os vertices do cubo
     */
    var cube_vertex = [
       // face : posterior // cor : amarelo
       -1,-1,-1,    1,1,0,
        1,-1,-1,    1,1,0,
        1, 1,-1,    1,1,0,
       -1, 1,-1,    1,1,0,

       // face : frontal // cor : azul
       -1,-1, 1,    0,0,1,
        1,-1, 1,    0,0,1,
        1, 1, 1,    0,0,1,
       -1, 1, 1,    0,0,1,

       // face : esquerda // cor : ciano
       -1,-1,-1,    0,1,1,
       -1, 1,-1,    0,1,1,
       -1, 1, 1,    0,1,1,
       -1,-1, 1,    0,1,1,

       // face : direita // cor : vermelho
        1,-1,-1,    1,0,0,
        1, 1,-1,    1,0,0,
        1, 1, 1,    1,0,0,
        1,-1, 1,    1,0,0,

       // face : inferior // cor : roxo
       -1,-1,-1,    1,0,1,
       -1,-1, 1,    1,0,1,
        1,-1, 1,    1,0,1,
        1,-1,-1,    1,0,1,

       // face : superior // cor : verde
       -1, 1,-1,    0,1,0,
       -1, 1, 1,    0,1,0,
        1, 1, 1,    0,1,0,
        1, 1,-1,    0,1,0
    ];

    /**
     * @attribute : @global CUBE_VERTEX
     * define um VBO com as coordenadas do cubo
     * Vertex Buffer of Object => array de vertices WebGL
     */
    var CUBE_VERTEX = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, CUBE_VERTEX);
    GL.bufferData(GL.ARRAY_BUFFER, new Float32Array(cube_vertex), GL.STATIC_DRAW);

    /**
     * @attribute : cube_faces
     * usa os pontos de triangulos como indices par construir um cuboGL
     * 2 triangulos para cada face
     */
    var cube_faces = [
        0, 1, 2,  // face de posterior
        0, 2, 3,

        4, 5, 6,  // face frontal
        4, 6, 7,

        8, 9, 10, // face esquerda
        8,10, 11,

        12,13,14, // face direita
        12,14,15,

        16,17,18, // face superior
        16,18,19,

        20,21,22, // face inferior
        20,22,23
    ];

    /**
     * @attribute : @global CUBE_FACES
     * define um VBO com as coordenadas das faces do cubo
     * Vertex Buffer of Object => array de vertices WebGL
     */
    var CUBE_FACES = GL.createBuffer();
    GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, CUBE_FACES);
    GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, new Uint16Array(cube_faces), GL.STATIC_DRAW);

    /**
     * @attribute : @global PROJMATRIX
     * Obtem a matri projeção em Z
     * 40 é o angulo da camera em graus
     * a camera só mostra pixes entre zMax e zMin
     */
    var PROJMATRIX = LIBS.get_projection(40, CANVAS.width / CANVAS.height, 1, 100);
    /**
     * @attribute : @global MOVEMATRIX
     * Matrix de movmentos do cubo
     * Iniciada como matrix identidade
     */
    var MOVEMATRIX = LIBS.get_I4();
    /**
     * @attribute : @global MOVEMATRIX
     * Matrix de movmentos de visualizacao do objeto
     * Iniciada como matrix identidade
     */
    var VIEWMATRIX = LIBS.get_I4();

    // translada em -6
    LIBS.translateZ(VIEWMATRIX, -6);
    var THETA = 0, PHI = 0;

    /** Desenho **/
    GL.enable(GL.DEPTH_TEST);
    GL.depthFunc(GL.LEQUAL);
    //define cor clara e transparente
    GL.clearColor(0.0, 0.0, 0.0, 0.0);
    GL.clearDepth(1.0);

    var time_old = 0;
    /**
     * @method animate
     * responsavel por desenhar a cena
     */
    var animate = function (time) {

        var dt = time - time_old;

        if (!drag) {
            dX *= AMORTIZATION;
            dY *= AMORTIZATION;
            THETA += dX, PHI += dY;
        }

        LIBS.set_I4(MOVEMATRIX);
        LIBS.rotateY(MOVEMATRIX, THETA);
        LIBS.rotateX(MOVEMATRIX, PHI);

        time_old = time;

        // define a area de desenho np canvas e limpa-a
        GL.viewport(0.0, 0.0, CANVAS.width, CANVAS.height);
        GL.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);

        GL.uniformMatrix4fv(_Pmatrix, false, PROJMATRIX);
        GL.uniformMatrix4fv(_Vmatrix, false, VIEWMATRIX);
        GL.uniformMatrix4fv(_Mmatrix, false, MOVEMATRIX);

        // usa esses pontos par ao proximo desenho
        GL.bindBuffer(GL.ARRAY_BUFFER, CUBE_VERTEX);
        //GL.vertexAttribPointer(variavel,dimensao,tipo,normalizador,tamnho total do vertice em bytes,deslocamento)
        GL.vertexAttribPointer(_position, 3, GL.FLOAT, false, 4 * (3 + 3), 0);
        //GL.vertexAttribPointer(variavel,dimensao,tipo,normalizador,tamnho total do vertice em bytes,deslocamento)
        GL.vertexAttribPointer(_color, 3, GL.FLOAT, false, 4 * (3 + 3), 3 * 4);

        GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, CUBE_FACES);
        // desenha o cubo
        // chama os 12 triangulos do cubo
        // 6 faces * 2 triangulo por face * 3 pontos por triangulo
        GL.drawElements(GL.TRIANGLES, 6 * 2 * 3, GL.UNSIGNED_SHORT, 0);

        // [ . . . ] // poderia criar mais objetos aqui

        // desnho esta terminado, pronto para renderizar
        GL.flush();

        // redesenha a cena assim que pronta
        window.requestAnimationFrame(animate);
    };
    // pela primeira vez que executado nao tem animação, por isso zero
    animate(0);
};
<|endoftext|>


<commit_before>var util = require('util');
var events = require('events');
var type = require('../data_type');
var log = require('../log');
var Class = require('../class');
var Promise = require('bluebird');

module.exports = Base = Class.extend({
  init: function() {
    this.eventEmmiter = new events.EventEmitter();
    for(var n in events.EventEmitter.prototype) {
      this[n] = events.EventEmitter.prototype[n];
    }
  },

  close: function() {
    throw new Error('not yet implemented');
  },

  mapDataType: function(str) {
    switch(str) {
      case type.STRING:
        return 'VARCHAR';
      case type.TEXT:
        return 'TEXT';
      case type.INTEGER:
        return 'INTEGER';
      case type.BIG_INTEGER:
        return 'BIGINT';
      case type.DATE_TIME:
        return 'INTEGER';
      case type.REAL:
        return 'REAL';
      case type.BLOB:
        return 'BLOB';
      case type.TIMESTAMP:
        return 'TIMESTAMP';
      case type.BINARY:
        return 'BINARY';
      case type.BOOLEAN:
        return 'BOOLEAN';
      case type.DECIMAL:
        return 'DECIMAL';
      case type.CHAR:
        return 'CHAR';
      case type.DATE:
        return 'DATE';
      case type.SMALLINT:
        return 'SMALLINT';
      default:
        var unknownType = str.toUpperCase();
        log.warn('Using unknown data type', unknownType);
        return unknownType;
    }
  },

  createDatabase: function() {

    throw new Error('not implemented');
  },

  switchDatabase: function() {
    throw new Error('not implemented');
  },

  dropDatabase: function() {
    throw new Error('not implemented');
  },

  recurseCallbackArray: function(foreignKeys, callback)
  {
    var self = this;

    if (foreignKeys.length > 0)
      (foreignKeys.pop())(function() { self.recurseCallbackArray(foreignKeys, callback); } );
    else
      callback();
  },

  bindForeignKey: function(tableName, columnName, fkOptions) {
    var self = this,
        mapping = {};

    if(typeof(fkOptions.mapping) === 'string')
      mapping[columnName] = fkOptions.mapping;
    else
      mapping = fkOptions.mapping;

    return function (callback) { self.addForeignKey(tableName, fkOptions.table,
        fkOptions.name, mapping, fkOptions.rules, callback); };
  },

  createColumnDef: function(name, spec, options) {
    name = '"' + name + '"';
    var type       = this.mapDataType(spec.type);
    var len        = spec.length ? util.format('(%s)', spec.length) : '';
    var constraint = this.createColumnConstraint(spec, options);

    return { foreignKey: null,
                 constraints: [name, type, len, constraint].join(' ') };
  },

  createMigrationsTable: function(callback) {
    var options = {
      columns: {
        'id': { type: type.INTEGER, notNull: true, primaryKey: true, autoIncrement: true },
        'name': { type: type.STRING, length: 255, notNull: true},
        'run_on': { type: type.DATE_TIME, notNull: true}
      },
      ifNotExists: true
    };
    this.createTable(global.migrationTable, options, callback);
  },

  createTable: function(tableName, options, callback) {
    log.verbose('creating table:', tableName);
    var columnSpecs = options;
    var tableOptions = {};

    if (options.columns !== undefined) {
      columnSpecs = options.columns;
      delete options.columns;
      tableOptions = options;
    }

    var ifNotExistsSql = "";
    if(tableOptions.ifNotExists) {
      ifNotExistsSql = "IF NOT EXISTS";
    }

    var primaryKeyColumns = [];
    var columnDefOptions = {
      emitPrimaryKey: false
    };

    for (var columnName in columnSpecs) {
      var columnSpec = this.normalizeColumnSpec(columnSpecs[columnName]);
      columnSpecs[columnName] = columnSpec;
      if (columnSpec.primaryKey) {
        primaryKeyColumns.push(columnName);
      }
    }

    var pkSql = '';
    if (primaryKeyColumns.length > 1) {
      pkSql = util.format(', PRIMARY KEY (%s)', this.quoteArr(primaryKeyColumns).join(', '));
    } else {
      columnDefOptions.emitPrimaryKey = true;
    }

    var columnDefs = [];
    var foreignKeys = [];

    for (var columnName in columnSpecs) {
      var columnSpec = columnSpecs[columnName];
      var constraint = this.createColumnDef(columnName, columnSpec, columnDefOptions, tableName);

      columnDefs.push(constraint.constraints);
      if (constraint.foreignKey)
        foreignKeys.push(constraint.foreignKey);
    }

    var sql = util.format('CREATE TABLE %s "%s" (%s%s)', ifNotExistsSql, tableName, columnDefs.join(', '), pkSql);

    this.runSql(sql, function()
    {

        this.recurseCallbackArray(foreignKeys, callback);
    }.bind(this));
  },

  dropTable: function(tableName, options, callback) {

    if (arguments.length < 3) {
      callback = options;
      options = {};
    }

    var ifExistsSql = '';
    if (options.ifExists) {
      ifExistsSql = 'IF EXISTS';
    }
    var sql = util.format('DROP TABLE %s "%s"', ifExistsSql, tableName);
    this.runSql(sql, callback);
  },

  renameTable: function(tableName, newTableName, callback) {
    throw new Error('not yet implemented');
  },

  addColumn: function(tableName, columnName, columnSpec, callback) {

    var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec, tableName));
    var sql = util.format('ALTER TABLE "%s" ADD COLUMN %s', tableName, def.constraints);

    this.runSql(sql, function()
    {
      if(def.foreignKey)
        def.foreignKey(callback);
      else
        callback();
    });
  },

  removeColumn: function(tableName, columnName, callback) {
    throw new Error('not yet implemented');
  },

  renameColumn: function(tableName, oldColumnName, newColumnName, callback) {
    throw new Error('not yet implemented');
  },

  changeColumn: function(tableName, columnName, columnSpec, callback) {
    throw new Error('not yet implemented');
  },

  quoteArr: function(arr) {

      for(var i = 0; i < arr.length; ++i)
        arr[i] = '"' + arr[i] + '"';

      return arr;
  },

  addIndex: function(tableName, indexName, columns, unique, callback) {
    if (typeof(unique) === 'function') {
      callback = unique;
      unique = false;
    }

    if (!Array.isArray(columns)) {
      columns = [columns];
    }
    var sql = util.format('CREATE %s INDEX "%s" ON "%s" (%s)', (unique ? 'UNIQUE' : ''),
      indexName, tableName, this.quoteArr(columns).join(', '));

    this.runSql(sql, callback);
  },

  insert: function(tableName, columnNameArray, valueArray, callback) {
    if (columnNameArray.length !== valueArray.length) {
      return callback(new Error('The number of columns does not match the number of values.'));
    }

    var sql = util.format('INSERT INTO "%s" ', tableName);
    var columnNames = '(';
    var values = 'VALUES (';

    for (var index in columnNameArray) {
      columnNames += columnNameArray[index];

      if (typeof(valueArray[index]) === 'string') {
        values += "'" + this.escape(valueArray[index]) + "'";
      } else {
        values += valueArray[index];
      }

      if (index != columnNameArray.length - 1) {
       columnNames += ",";
       values +=  ",";
      }
    }

    sql += columnNames + ') '+ values + ');';
    this.runSql(sql, callback);
  },

  removeIndex: function(tableName, indexName, callback) {
    if (arguments.length === 2 && typeof(indexName) === 'function') {
      callback = indexName;
      indexName = tableName;
    } else if (arguments.length === 1 && typeof(tableName) === 'string') {
      indexName = tableName;
    }

    var sql = util.format('DROP INDEX "%s"', indexName);
    this.runSql(sql, callback);
  },

  addForeignKey: function() {
    throw new Error('not implemented');
  },

  removeForeignKey: function() {
    throw new Error('not implemented');
  },

  normalizeColumnSpec: function(obj) {
    if (typeof(obj) === 'string') {
      return { type: obj };
    } else {
      return obj;
    }
  },

  addMigrationRecord: function (name, callback) {
    this.runSql('INSERT INTO "' + global.migrationTable + '" (name, run_on) VALUES (?, ?)', [name, new Date()], callback);
  },

  startMigration: function(cb){ return Promise.resolve().nodeify(cb); },
  endMigration: function(cb){ return Promise.resolve().nodeify(cb); },
  // sql, params, callback
  // sql, callback
  runSql: function() {
    throw new Error('not implemented');
  },

  /**
    * Queries the migrations table
    *
    * @param callback
    */
  allLoadedMigrations: function(callback) {
    var sql = 'SELECT * FROM "' + global.migrationTable + '" ORDER BY run_on DESC, name DESC';
    return this.all(sql, callback);
  },

  /**
    * Deletes a migration
    *
    * @param migrationName   - The name of the migration to be deleted
    */
  deleteMigration: function(migrationName, callback) {
    var sql = 'DELETE FROM "' + global.migrationTable + '" WHERE name = ?';
    this.runSql(sql, [migrationName], callback);
  },

  all: function(sql, params, callback) {
    throw new Error('not implemented');
  },

  escape: function(str) {
    return str.replace(/'/g, "''");
  }
});
<commit_msg>[Bugfix] addColumn missing defaultOptionalities<commit_after>var util = require('util');
var events = require('events');
var type = require('../data_type');
var log = require('../log');
var Class = require('../class');
var Promise = require('bluebird');

module.exports = Base = Class.extend({
  init: function() {
    this.eventEmmiter = new events.EventEmitter();
    for(var n in events.EventEmitter.prototype) {
      this[n] = events.EventEmitter.prototype[n];
    }
  },

  close: function() {
    throw new Error('not yet implemented');
  },

  mapDataType: function(str) {
    switch(str) {
      case type.STRING:
        return 'VARCHAR';
      case type.TEXT:
        return 'TEXT';
      case type.INTEGER:
        return 'INTEGER';
      case type.BIG_INTEGER:
        return 'BIGINT';
      case type.DATE_TIME:
        return 'INTEGER';
      case type.REAL:
        return 'REAL';
      case type.BLOB:
        return 'BLOB';
      case type.TIMESTAMP:
        return 'TIMESTAMP';
      case type.BINARY:
        return 'BINARY';
      case type.BOOLEAN:
        return 'BOOLEAN';
      case type.DECIMAL:
        return 'DECIMAL';
      case type.CHAR:
        return 'CHAR';
      case type.DATE:
        return 'DATE';
      case type.SMALLINT:
        return 'SMALLINT';
      default:
        var unknownType = str.toUpperCase();
        log.warn('Using unknown data type', unknownType);
        return unknownType;
    }
  },

  createDatabase: function() {

    throw new Error('not implemented');
  },

  switchDatabase: function() {
    throw new Error('not implemented');
  },

  dropDatabase: function() {
    throw new Error('not implemented');
  },

  recurseCallbackArray: function(foreignKeys, callback)
  {
    var self = this;

    if (foreignKeys.length > 0)
      (foreignKeys.pop())(function() { self.recurseCallbackArray(foreignKeys, callback); } );
    else
      callback();
  },

  bindForeignKey: function(tableName, columnName, fkOptions) {
    var self = this,
        mapping = {};

    if(typeof(fkOptions.mapping) === 'string')
      mapping[columnName] = fkOptions.mapping;
    else
      mapping = fkOptions.mapping;

    return function (callback) { self.addForeignKey(tableName, fkOptions.table,
        fkOptions.name, mapping, fkOptions.rules, callback); };
  },

  createColumnDef: function(name, spec, options) {
    name = '"' + name + '"';
    var type       = this.mapDataType(spec.type);
    var len        = spec.length ? util.format('(%s)', spec.length) : '';
    var constraint = this.createColumnConstraint(spec, options);

    return { foreignKey: null,
                 constraints: [name, type, len, constraint].join(' ') };
  },

  createMigrationsTable: function(callback) {
    var options = {
      columns: {
        'id': { type: type.INTEGER, notNull: true, primaryKey: true, autoIncrement: true },
        'name': { type: type.STRING, length: 255, notNull: true},
        'run_on': { type: type.DATE_TIME, notNull: true}
      },
      ifNotExists: true
    };
    this.createTable(global.migrationTable, options, callback);
  },

  createTable: function(tableName, options, callback) {
    log.verbose('creating table:', tableName);
    var columnSpecs = options;
    var tableOptions = {};

    if (options.columns !== undefined) {
      columnSpecs = options.columns;
      delete options.columns;
      tableOptions = options;
    }

    var ifNotExistsSql = "";
    if(tableOptions.ifNotExists) {
      ifNotExistsSql = "IF NOT EXISTS";
    }

    var primaryKeyColumns = [];
    var columnDefOptions = {
      emitPrimaryKey: false
    };

    for (var columnName in columnSpecs) {
      var columnSpec = this.normalizeColumnSpec(columnSpecs[columnName]);
      columnSpecs[columnName] = columnSpec;
      if (columnSpec.primaryKey) {
        primaryKeyColumns.push(columnName);
      }
    }

    var pkSql = '';
    if (primaryKeyColumns.length > 1) {
      pkSql = util.format(', PRIMARY KEY (%s)', this.quoteArr(primaryKeyColumns).join(', '));
    } else {
      columnDefOptions.emitPrimaryKey = true;
    }

    var columnDefs = [];
    var foreignKeys = [];

    for (var columnName in columnSpecs) {
      var columnSpec = columnSpecs[columnName];
      var constraint = this.createColumnDef(columnName, columnSpec, columnDefOptions, tableName);

      columnDefs.push(constraint.constraints);
      if (constraint.foreignKey)
        foreignKeys.push(constraint.foreignKey);
    }

    var sql = util.format('CREATE TABLE %s "%s" (%s%s)', ifNotExistsSql, tableName, columnDefs.join(', '), pkSql);

    this.runSql(sql, function()
    {

        this.recurseCallbackArray(foreignKeys, callback);
    }.bind(this));
  },

  dropTable: function(tableName, options, callback) {

    if (arguments.length < 3) {
      callback = options;
      options = {};
    }

    var ifExistsSql = '';
    if (options.ifExists) {
      ifExistsSql = 'IF EXISTS';
    }
    var sql = util.format('DROP TABLE %s "%s"', ifExistsSql, tableName);
    this.runSql(sql, callback);
  },

  renameTable: function(tableName, newTableName, callback) {
    throw new Error('not yet implemented');
  },

  addColumn: function(tableName, columnName, columnSpec, callback) {

    var def = this.createColumnDef(columnName, this.normalizeColumnSpec(columnSpec), {}, tableName);
    var sql = util.format('ALTER TABLE "%s" ADD COLUMN %s', tableName, def.constraints);

    this.runSql(sql, function()
    {
      if(def.foreignKey)
        def.foreignKey(callback);
      else
        callback();
    });
  },

  removeColumn: function(tableName, columnName, callback) {
    throw new Error('not yet implemented');
  },

  renameColumn: function(tableName, oldColumnName, newColumnName, callback) {
    throw new Error('not yet implemented');
  },

  changeColumn: function(tableName, columnName, columnSpec, callback) {
    throw new Error('not yet implemented');
  },

  quoteArr: function(arr) {

      for(var i = 0; i < arr.length; ++i)
        arr[i] = '"' + arr[i] + '"';

      return arr;
  },

  addIndex: function(tableName, indexName, columns, unique, callback) {
    if (typeof(unique) === 'function') {
      callback = unique;
      unique = false;
    }

    if (!Array.isArray(columns)) {
      columns = [columns];
    }
    var sql = util.format('CREATE %s INDEX "%s" ON "%s" (%s)', (unique ? 'UNIQUE' : ''),
      indexName, tableName, this.quoteArr(columns).join(', '));

    this.runSql(sql, callback);
  },

  insert: function(tableName, columnNameArray, valueArray, callback) {
    if (columnNameArray.length !== valueArray.length) {
      return callback(new Error('The number of columns does not match the number of values.'));
    }

    var sql = util.format('INSERT INTO "%s" ', tableName);
    var columnNames = '(';
    var values = 'VALUES (';

    for (var index in columnNameArray) {
      columnNames += columnNameArray[index];

      if (typeof(valueArray[index]) === 'string') {
        values += "'" + this.escape(valueArray[index]) + "'";
      } else {
        values += valueArray[index];
      }

      if (index != columnNameArray.length - 1) {
       columnNames += ",";
       values +=  ",";
      }
    }

    sql += columnNames + ') '+ values + ');';
    this.runSql(sql, callback);
  },

  removeIndex: function(tableName, indexName, callback) {
    if (arguments.length === 2 && typeof(indexName) === 'function') {
      callback = indexName;
      indexName = tableName;
    } else if (arguments.length === 1 && typeof(tableName) === 'string') {
      indexName = tableName;
    }

    var sql = util.format('DROP INDEX "%s"', indexName);
    this.runSql(sql, callback);
  },

  addForeignKey: function() {
    throw new Error('not implemented');
  },

  removeForeignKey: function() {
    throw new Error('not implemented');
  },

  normalizeColumnSpec: function(obj) {
    if (typeof(obj) === 'string') {
      return { type: obj };
    } else {
      return obj;
    }
  },

  addMigrationRecord: function (name, callback) {
    this.runSql('INSERT INTO "' + global.migrationTable + '" (name, run_on) VALUES (?, ?)', [name, new Date()], callback);
  },

  startMigration: function(cb){ return Promise.resolve().nodeify(cb); },
  endMigration: function(cb){ return Promise.resolve().nodeify(cb); },
  // sql, params, callback
  // sql, callback
  runSql: function() {
    throw new Error('not implemented');
  },

  /**
    * Queries the migrations table
    *
    * @param callback
    */
  allLoadedMigrations: function(callback) {
    var sql = 'SELECT * FROM "' + global.migrationTable + '" ORDER BY run_on DESC, name DESC';
    return this.all(sql, callback);
  },

  /**
    * Deletes a migration
    *
    * @param migrationName   - The name of the migration to be deleted
    */
  deleteMigration: function(migrationName, callback) {
    var sql = 'DELETE FROM "' + global.migrationTable + '" WHERE name = ?';
    this.runSql(sql, [migrationName], callback);
  },

  all: function(sql, params, callback) {
    throw new Error('not implemented');
  },

  escape: function(str) {
    return str.replace(/'/g, "''");
  }
});
<|endoftext|>


<commit_before>'use strict';

var errorSpec = [{
  name: 'INVALID_BACKUP',
  message: 'Invalid Backup'
}, {
  name: 'WALLET_DOES_NOT_EXIST',
  message: 'Wallet does not exist. Need to recreate'
}, {
  name: 'MISSING_PRIVATE_KEY',
  message: 'Missing private keys to sign'
}, {
  name: 'ENCRYPTED_PRIVATE_KEY',
  message: 'Private key is encrypted, cannot sign'
}, {
  name: 'SERVER_COMPROMISED',
  message: 'Server response could not be verified'
}, {
  name: 'COULD_NOT_BUILD_TRANSACTION',
  message: 'Could not build transaction'
}, {
  name: 'INSUFFICIENT_FUNDS',
  message: 'Insufficient funds'
}, {
  name: 'CONNECTION_ERROR',
  message: 'connection error'
}, {
  name: 'NOT_FOUND',
  message: 'not found'
}, {
  name: 'ECONNRESET_ERROR',
  message: 'ECONNRESET, body: {0}'
}, {
  name: 'WALLET_ALREADY_EXISTS',
  message: 'wallet already exists'
}, {
  name: 'COPAYER_IN_WALLET',
  message: 'copayer in wallet'
}, {
  name: 'WALLET_FULL',
  message: 'wallet is full'
}, {
  name: 'WALLET_NOT_FOUND',
  message: 'wallet not found'
}, {
  name: 'INSUFFICIENT_FUNDS_FOR_FEE',
  message: 'insufficient funds for fee'
}, {
  name: 'LOCKED_FUNDS',
  message: 'locked funds'
}, {
  name: 'DUST_AMOUNT',
  message: 'Amount below dust threshold'
}, {
  name: 'COPAYER_VOTED',
  message: 'Copayer already voted on this transaction proposal'
}, {
  name: 'NOT_AUTHORIZED',
  message: 'not authorized'
}, {
  name: 'UNAVAILABLE_UTXOS',
  message: 'Unavailable unspent outputs'
}, {
  name: 'TX_NOT_FOUND',
  message: 'transaction proposal not found'
}];

module.exports = errorSpec;
<commit_msg>Update error messages to be more UI friendly.<commit_after>'use strict';

var errorSpec = [{
  name: 'INVALID_BACKUP',
  message: 'Invalid Backup.'
}, {
  name: 'WALLET_DOES_NOT_EXIST',
  message: 'Wallet does not exist.'
}, {
  name: 'MISSING_PRIVATE_KEY',
  message: 'Missing private keys to sign.'
}, {
  name: 'ENCRYPTED_PRIVATE_KEY',
  message: 'Private key is encrypted, cannot sign transaction.'
}, {
  name: 'SERVER_COMPROMISED',
  message: 'Server response could not be verified.'
}, {
  name: 'COULD_NOT_BUILD_TRANSACTION',
  message: 'Could not build the transaction.'
}, {
  name: 'INSUFFICIENT_FUNDS',
  message: 'Insufficient funds.'
}, {
  name: 'CONNECTION_ERROR',
  message: 'Wallet service connection error.'
}, {
  name: 'NOT_FOUND',
  message: 'Wallet service not found.'
}, {
  name: 'ECONNRESET_ERROR',
  message: 'ECONNRESET, body: {0}'
}, {
  name: 'WALLET_ALREADY_EXISTS',
  message: 'Wallet already exists.'
}, {
  name: 'COPAYER_IN_WALLET',
  message: 'Copayer in wallet.'
}, {
  name: 'WALLET_FULL',
  message: 'Wallet is full.'
}, {
  name: 'WALLET_NOT_FOUND',
  message: 'Wallet not found.'
}, {
  name: 'INSUFFICIENT_FUNDS_FOR_FEE',
  message: 'Insufficient funds for fee.'
}, {
  name: 'LOCKED_FUNDS',
  message: 'Locked funds.'
}, {
  name: 'DUST_AMOUNT',
  message: 'Amount below dust threshold.'
}, {
  name: 'COPAYER_VOTED',
  message: 'Copayer already voted on this transaction proposal.'
}, {
  name: 'NOT_AUTHORIZED',
  message: 'Not authorized.'
}, {
  name: 'UNAVAILABLE_UTXOS',
  message: 'Unavailable unspent outputs.'
}, {
  name: 'TX_NOT_FOUND',
  message: 'Transaction proposal not found.'
}];

module.exports = errorSpec;
<|endoftext|>