<commit_before>'use strict';

var path = require('path');
var util = require('util');
var async = require('async');
var _ = require('lodash');
var uuid = require('uuid');
var fs = require('fs');
var os = require('os');

var lpad = require('./lpad');

function Parallelizer(grunt, task) {
  this.grunt_ = grunt;
  this.task_ = task;
  this.cpCache_ = [];
}

Parallelizer.prototype.kill = function() {
  this.cpCache_.forEach(function(el) {
    el.kill();
  });
};

Parallelizer.prototype.exec = function(task, target) {
  var cb = this.task_.async();
  var splittedFilesSrc = this.getSplittedFilesSrc_(task, target);

  var spawnOptions;
  // Optionally log the task output
  // if (options.logConcurrentOutput) {
  //   spawnOptions = { stdio: 'inherit' };
  // }

  var self = this;
  // create /tmp if not exists
  fs.mkdir(os.tmpdir(), function (err) {
    lpad('    ');
    var ok = true;
    async.forEach(splittedFilesSrc, function(filesSrc, next) {
      // need to put filesSrc in a temp file because of command line arg data limit
      var tmpFile = path.join(os.tmpdir(), task + target + uuid.v4());
      fs.writeFile(tmpFile, JSON.stringify(filesSrc), function (err) {
        if (err) { throw err; }
        var filesOption = '--grunt-parallelize-child-filesSrc=' + tmpFile;
        var cp = self.grunt_.util.spawn({
          grunt: true,
          args: [['parallelize', task, target].join(':')].concat(self.grunt_.option.flags(), filesOption),
          opts: spawnOptions
        }, function(err, result, code) {
          if ((err || code > 0)) {
            ok = false;
            if (result.stderr) {
              self.grunt_.warn(result.stderr);
            }
          }
          self.grunt_.log.write('\n' + self.filterOutput_(result.stdout, task, target) + '\n');
          next();
        });
        self.cpCache_.push(cp);
      });
    }, function() {
      lpad();
      if (!ok) {
        self.grunt_.log.writeln('');
      }
      cb(ok);
    });
  });
};

Parallelizer.prototype.filterOutput_ = function(output, task, target) {
  var regex = new RegExp(util.format('^.*Running "parallelize:%s:%s".*\n\n', task, target), 'g');
  return output.replace(regex, '');
};

Parallelizer.prototype.getProcesses_ = function(task, target) {
  var processes = this.grunt_.config(['parallelize', task, target]);
  if (typeof processes === 'number') {
    return processes;
  } else if (processes) {
    processes = this.grunt_.config(['parallelize', task, 'options', 'processes']);
    if (typeof processes === 'number') {
      return processes;
    }
    processes = this.grunt_.config(['parallelize', 'options', 'processes']);
    if (typeof processes === 'number') {
      return processes;
    }
  }

  throw new Error('"processes" option not found');
};

Parallelizer.prototype.getSplittedFilesSrc_ = function(task, target) {
  var filesSrc = this.getNormalizedFilesSrc_(task, target);
  var processes = this.getProcesses_(task, target);
  if (processes < 0) {
    throw new Error('"processes" option shoud be positive');
  } else if (!processes) {
    return [];
  }
  var remain = filesSrc.length % processes;
  var per = (filesSrc.length - remain) / processes;
  var splittedFilesSrc = [];
  while (filesSrc.length) {
    splittedFilesSrc.push(filesSrc.splice(0, remain-- > 0 ? per + 1 : per));
  }
  return splittedFilesSrc;
};

Parallelizer.prototype.getNormalizedFilesSrc_ = function(task, target) {
  var configPath = [task, target];
  var config = this.grunt_.config(configPath);
  var files = this.grunt_.task.normalizeMultiTaskFiles(config);
  // if any file objects have a destination, can assume that not all src files
  // can be merged into single list
  var hasDest = false;
  files.forEach(function (fileObj) {
    if (fileObj.dest !== undefined){ hasDest = true; }
  });
  var normalizedFiles;
  if (hasDest){
    normalizedFiles = files;
  } else {
    normalizedFiles = _(files).chain().pluck('src').flatten().uniq().value();
    normalizedFiles = normalizedFiles.map(function (srcFile) {
      return { src: srcFile, };
    });
  }

  return normalizedFiles;
};

module.exports = Parallelizer;
<commit_msg>fix(parallelizer): change internal file format<commit_after>'use strict';

var path = require('path');
var util = require('util');
var async = require('async');
var _ = require('lodash');
var uuid = require('uuid');
var fs = require('fs');
var os = require('os');

var lpad = require('./lpad');

function Parallelizer(grunt, task) {
  this.grunt_ = grunt;
  this.task_ = task;
  this.cpCache_ = [];
}

Parallelizer.prototype.kill = function() {
  this.cpCache_.forEach(function(el) {
    el.kill();
  });
};

Parallelizer.prototype.exec = function(task, target) {
  var cb = this.task_.async();
  var splittedFilesSrc = this.getSplittedFilesSrc_(task, target);

  var spawnOptions;
  // Optionally log the task output
  // if (options.logConcurrentOutput) {
  //   spawnOptions = { stdio: 'inherit' };
  // }

  var self = this;
  // create /tmp if not exists
  fs.mkdir(os.tmpdir(), function (err) {
    lpad('    ');
    var ok = true;
    async.forEach(splittedFilesSrc, function(filesSrc, next) {
      // need to put filesSrc in a temp file because of command line arg data limit
      var tmpFile = path.join(os.tmpdir(), task + target + uuid.v4());
      fs.writeFile(tmpFile, JSON.stringify(filesSrc), function (err) {
        if (err) { throw err; }
        var filesOption = '--grunt-parallelize-child-filesSrc=' + tmpFile;
        var cp = self.grunt_.util.spawn({
          grunt: true,
          args: [['parallelize', task, target].join(':')].concat(self.grunt_.option.flags(), filesOption),
          opts: spawnOptions
        }, function(err, result, code) {
          if ((err || code > 0)) {
            ok = false;
            if (result.stderr) {
              self.grunt_.warn(result.stderr);
            }
          }
          self.grunt_.log.write('\n' + self.filterOutput_(result.stdout, task, target) + '\n');
          next();
        });
        self.cpCache_.push(cp);
      });
    }, function() {
      lpad();
      if (!ok) {
        self.grunt_.log.writeln('');
      }
      cb(ok);
    });
  });
};

Parallelizer.prototype.filterOutput_ = function(output, task, target) {
  var regex = new RegExp(util.format('^.*Running "parallelize:%s:%s".*\n\n', task, target), 'g');
  return output.replace(regex, '');
};

Parallelizer.prototype.getProcesses_ = function(task, target) {
  var processes = this.grunt_.config(['parallelize', task, target]);
  if (typeof processes === 'number') {
    return processes;
  } else if (processes) {
    processes = this.grunt_.config(['parallelize', task, 'options', 'processes']);
    if (typeof processes === 'number') {
      return processes;
    }
    processes = this.grunt_.config(['parallelize', 'options', 'processes']);
    if (typeof processes === 'number') {
      return processes;
    }
  }

  throw new Error('"processes" option not found');
};

Parallelizer.prototype.getSplittedFilesSrc_ = function(task, target) {
  var files = this.getNormalizedFiles_(task, target);
  var processes = this.getProcesses_(task, target);

  // if any file objects have a destination, can assume that not all src files
  // can be merged into single list
  if (this.hasDest_(files)) {
    return this.splitArray_(files, processes);
  } else {
    var filesSrc = _(files).chain().pluck('src').flatten().uniq().value();
    return this.splitArray_(filesSrc, processes).map(function(src) {
      return {
        src: src
      };
    });
  }
};

Parallelizer.prototype.getNormalizedFiles_ = function(task, target) {
  var configPath = [task, target];
  var config = this.grunt_.config(configPath);
  return this.grunt_.task.normalizeMultiTaskFiles(config);
};

Parallelizer.prototype.hasDest_ = function(files) {
  return files.some(function(fileObj) {
    return fileObj.dest !== undefined;
  });
};

Parallelizer.prototype.splitArray_ = function(arr, processes) {
  if (processes < 0) {
    throw new Error('"processes" option shoud be positive');
  } else if (!processes) {
    return [];
  }

  var remain = arr.length % processes;
  var per = (arr.length - remain) / processes;
  var splitted = [];
  while (arr.length) {
    splitted.push(arr.splice(0, remain-- > 0 ? per + 1 : per));
  }
  return splitted;
};

module.exports = Parallelizer;
<|endoftext|>


<commit_before>import * as mobx from 'mobx';
import React from 'react';
import {unstable_batchedUpdates as rdBatched} from 'react-dom';
import {unstable_batchedUpdates as rnBatched} from 'react-native';

let TARGET_LIB_NAME;
if (__TARGET__ === 'browser') TARGET_LIB_NAME = 'mobx-react';
if (__TARGET__ === 'native') TARGET_LIB_NAME = 'mobx-react/native';
if (__TARGET__ === 'custom') TARGET_LIB_NAME = 'mobx-react/custom';

if (!mobx)
  throw new Error(TARGET_LIB_NAME + ' requires the MobX package');
if (!React)
  throw new Error(TARGET_LIB_NAME + ' requires React to be available');

if (__TARGET__ === 'browser' && typeof rdBatched === "function")
  mobx.extras.setReactionScheduler(rdBatched);
if (__TARGET__ === 'native' && typeof rnBatched === "function")
  mobx.extras.setReactionScheduler(rnBatched);

export {
  observer,
  Observer,
  renderReporter,
  componentByNodeRegistery,
  trackComponents,
  useStaticRendering
} from './observer';

export { default as Provider } from './Provider';
export { default as inject } from './inject';

import * as propTypes from './propTypes';
export { propTypes };
export { propTypes as PropTypes };

import { errorsReporter } from './observer';
export const onError = fn => errorsReporter.on(fn);

export default module.exports;

/* DevTool support */
if (typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__ === 'object') {
  __MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobxReact(module.exports, mobx)
}
<commit_msg>fix rollup umd runtime error re: module is not defined<commit_after>import * as mobx from 'mobx';
import React from 'react';
import {unstable_batchedUpdates as rdBatched} from 'react-dom';
import {unstable_batchedUpdates as rnBatched} from 'react-native';

let TARGET_LIB_NAME;
if (__TARGET__ === 'browser') TARGET_LIB_NAME = 'mobx-react';
if (__TARGET__ === 'native') TARGET_LIB_NAME = 'mobx-react/native';
if (__TARGET__ === 'custom') TARGET_LIB_NAME = 'mobx-react/custom';

if (!mobx)
  throw new Error(TARGET_LIB_NAME + ' requires the MobX package');
if (!React)
  throw new Error(TARGET_LIB_NAME + ' requires React to be available');

if (__TARGET__ === 'browser' && typeof rdBatched === "function")
  mobx.extras.setReactionScheduler(rdBatched);
if (__TARGET__ === 'native' && typeof rnBatched === "function")
  mobx.extras.setReactionScheduler(rnBatched);

export {
  observer,
  Observer,
  renderReporter,
  componentByNodeRegistery,
  trackComponents,
  useStaticRendering
} from './observer';

export { default as Provider } from './Provider';
export { default as inject } from './inject';

import * as propTypes from './propTypes';
export { propTypes };
export { propTypes as PropTypes };

import { errorsReporter } from './observer';
export const onError = fn => errorsReporter.on(fn);

export default exports;

/* DevTool support */
if (typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__ === 'object') {
  __MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobxReact(exports, mobx)
}
<|endoftext|>


<commit_before>const R = require("ramda");
const { makeExecutableSchema } = require("graphql-tools");

const typeDefs = `
  enum SshKeyType {
    SSH_RSA
    SSH_ED25519
  }

  type SshKey {
    id: Int
    name: String
    keyValue: String
    keyType: String
    created: String
  }

  type Customer {
    id: Int
    name: String
    comment: String
    private_key: String
    sshKeys: [SshKey]
    created: String
  }

  type Openshift {
    id: Int
    name: String
    console_url: String
    token: String
    router_pattern: String
    project_user: String
    created: String
  }

  type NotificationSlack {
    id: Int
    name: String
    webhook: String
    channel: String
  }

  union Notification = NotificationSlack

  type Project {
    id: Int
    name: String
    customer: Customer
    git_url: String
    notifications(type: String): [Notification]
    active_systems_deploy: String
    active_systems_remove: String
    branches: String
    production_environment: String
    pullrequests: Boolean
    openshift: Openshift
    sshKeys: [SshKey]
    environments: [Environment]
    created: String
  }

  type Environment {
    id: Int
    name: String
    project: Project
    git_type: String
    environment_type: String
    openshift_projectname: String
    updated: String
    created: String
  }

  input DeleteEnvironmentInput {
    name: String!
    project: String!
  }

  type Query {
    projectByName(name: String!): Project
    projectByGitUrl(gitUrl: String!): Project
    allProjects(createdAfter: String, gitUrl: String): [Project]
    allCustomers(createdAfter: String): [Customer]
    allOpenshifts: [Openshift]
  }

  input SshKeyInput {
    name: String!
    keyValue: String!
    keyType: String
  }

  input DeleteSshKeyInput {
    name: String!
  }

  input ProjectInput {
    name: String!
    customer: String!
    git_url: String!
    openshift: String!
    active_systems_deploy: String
    active_systems_remove: String
    branches: String
    pullrequests: Boolean
    production_environment: String
    sshKeys: [String]
  }

  input EnvironmentInput {
    name: String!
    project: String!
    git_type: String!
    environment_type: String!
    openshift_projectname: String!
  }

  input CustomerInput {
    name: String!
    comment: String
    private_key: String
    sshKeys: [String]
  }

  input OpenshiftInput {
    name: String!
    console_url: String!
    token: String
    router_pattern: String
    project_user: String
  }

  input DeleteOpenshiftInput {
    name: String!
  }

  input DeleteCustomerInput {
    name: String!
  }

  input NotificationSlackInput {
    name: String!
    webhook: String!
    channel: String!
  }

  input DeleteNotificationSlackInput {
    name: String!
  }

  input NotificationToProjectInput {
    project: String!
    notificationType: String!
    notificationName: String!
  }

  input RemoveNotificationFromProjectInput {
    project: String!
    notificationType: String!
    notificationName: String!
  }

  input DeleteProjectInput {
    name: String!
  }

  type Mutation {
    addProject(input: ProjectInput!): Project
    deleteProject(input: DeleteProjectInput!): String
    addOrUpdateEnvironment(input: EnvironmentInput!): Environment
    deleteEnvironment(input: DeleteEnvironmentInput!): String
    addSshKey(input: SshKeyInput!): SshKey
    deleteSshKey(input: DeleteSshKeyInput!): String
    addCustomer(input: CustomerInput!): Customer
    deleteCustomer(input: DeleteCustomerInput!): String
    addOpenshift(input: OpenshiftInput!): Openshift
    deleteOpenshift(input: DeleteOpenshiftInput!): String
    addNotificationSlack(input: NotificationSlackInput!): NotificationSlack
    deleteNotificationSlack(input: DeleteNotificationSlackInput!): String
    addNotificationToProject(input: NotificationToProjectInput!): Project
    removeNotificationFromProject(input: RemoveNotificationFromProjectInput!): Project
    truncateTable(tableName: String!): String
  }
`;

const getCtx = req => req.app.get("context");
const getDao = req => getCtx(req).dao;

const resolvers = {
  Project: {
    customer: async (project, args, req) => {
      const dao = getDao(req);
      return await dao.getCustomerByProjectId(req.credentials, project.customer);
    },
    sshKeys: async (project, args, req) => {
      const dao = getDao(req);
      return await dao.getSshKeysByProjectId(req.credentials, project.id)
    },
    notifications: async (project, args, req) => {
      const dao = getDao(req);
      return await dao.getNotificationsByProjectId(req.credentials, project.id, args)
    },
    openshift: async (project, args, req) => {
      const dao = getDao(req);
      return await dao.getOpenshiftByProjectId(req.credentials, project.id);
    },
    environments: async (project, args, req) => {
      const dao = getDao(req);
      return await dao.getEnvironmentsByProjectId(req.credentials, project.id);
    }
  },
  Environment: {
    project: async (environment, args, req) => {
      const dao = getDao(req);
      return await dao.getProjectByEnvironmentId(req.credentials, environment.id);
    }
  },
  Notification: {
    __resolveType(obj, context, info){
      switch (obj.type) {
        case 'slack':
          return 'NotificationSlack';
        default:
          return null;
      }
    },
  },
  Customer: {
    sshKeys: async (customer, args, req) => {
      const dao = getDao(req);
      return await dao.getSshKeysByCustomerId(req.credentials, customer.id)
    }
  },
  Query: {
    projectByGitUrl: async (root, args, req) => {
      const dao = getDao(req);
      return await dao.getProjectByGitUrl(req.credentials, args);
    },
    projectByName: async (root, args, req) => {
      const dao = getDao(req);
      return await dao.getProjectByName(req.credentials, args);
    },
    allProjects: async (root, args, req) => {
      const dao = getDao(req);
      return await dao.getAllProjects(req.credentials, args);
    },
    allCustomers: async (root, args, req) => {
      const dao = getDao(req);
      return await dao.getAllCustomers(req.credentials, args);
    },
    allOpenshifts: async (root, args, req) => {
      const dao = getDao(req);
      return await dao.getAllOpenshifts(req.credentials, args);
    }
  },
  Mutation: {
    addProject: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addProject(req.credentials, args.input);
      return ret;
    },
    deleteProject: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteProject(req.credentials, args.input);
      return ret;
    },
    addSshKey: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addSshKey(req.credentials, args.input);
      return ret;
    },
    deleteSshKey: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteSshKey(req.credentials, args.input);
      return ret;
    },
    addCustomer: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addCustomer(req.credentials, args.input);
      return ret;
    },
    deleteCustomer: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteCustomer(req.credentials, args.input);
      return ret;
    },
    addOpenshift: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addOpenshift(req.credentials, args.input);
      return ret;
    },
    deleteOpenshift: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteOpenshift(req.credentials, args.input);
      return ret;
    },
    addNotificationSlack: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addNotificationSlack(req.credentials, args.input);
      return ret;
    },
    deleteNotificationSlack: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteNotificationSlack(req.credentials, args.input);
      return ret;
    },
    addNotificationToProject: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addNotificationToProject(req.credentials, args.input);
      return ret;
    },
    removeNotificationFromProject: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.removeNotificationFromProject(req.credentials, args.input);
      return ret;
    },
    addOrUpdateEnvironment: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addOrUpdateEnvironment(req.credentials, args.input);
      return ret;
    },
    deleteEnvironment: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteEnvironment(req.credentials, args.input);
      return ret;
    },
    truncateTable: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.truncateTable(req.credentials, args);
      return ret;
    }
  }
};

module.exports = makeExecutableSchema({ typeDefs, resolvers });
<commit_msg>bugfix: inject projectID into getCustomerByProjectId not customer ID<commit_after>const R = require("ramda");
const { makeExecutableSchema } = require("graphql-tools");

const typeDefs = `
  enum SshKeyType {
    SSH_RSA
    SSH_ED25519
  }

  type SshKey {
    id: Int
    name: String
    keyValue: String
    keyType: String
    created: String
  }

  type Customer {
    id: Int
    name: String
    comment: String
    private_key: String
    sshKeys: [SshKey]
    created: String
  }

  type Openshift {
    id: Int
    name: String
    console_url: String
    token: String
    router_pattern: String
    project_user: String
    created: String
  }

  type NotificationSlack {
    id: Int
    name: String
    webhook: String
    channel: String
  }

  union Notification = NotificationSlack

  type Project {
    id: Int
    name: String
    customer: Customer
    git_url: String
    notifications(type: String): [Notification]
    active_systems_deploy: String
    active_systems_remove: String
    branches: String
    production_environment: String
    pullrequests: Boolean
    openshift: Openshift
    sshKeys: [SshKey]
    environments: [Environment]
    created: String
  }

  type Environment {
    id: Int
    name: String
    project: Project
    git_type: String
    environment_type: String
    openshift_projectname: String
    updated: String
    created: String
  }

  input DeleteEnvironmentInput {
    name: String!
    project: String!
  }

  type Query {
    projectByName(name: String!): Project
    projectByGitUrl(gitUrl: String!): Project
    allProjects(createdAfter: String, gitUrl: String): [Project]
    allCustomers(createdAfter: String): [Customer]
    allOpenshifts: [Openshift]
  }

  input SshKeyInput {
    name: String!
    keyValue: String!
    keyType: String
  }

  input DeleteSshKeyInput {
    name: String!
  }

  input ProjectInput {
    name: String!
    customer: String!
    git_url: String!
    openshift: String!
    active_systems_deploy: String
    active_systems_remove: String
    branches: String
    pullrequests: Boolean
    production_environment: String
    sshKeys: [String]
  }

  input EnvironmentInput {
    name: String!
    project: String!
    git_type: String!
    environment_type: String!
    openshift_projectname: String!
  }

  input CustomerInput {
    name: String!
    comment: String
    private_key: String
    sshKeys: [String]
  }

  input OpenshiftInput {
    name: String!
    console_url: String!
    token: String
    router_pattern: String
    project_user: String
  }

  input DeleteOpenshiftInput {
    name: String!
  }

  input DeleteCustomerInput {
    name: String!
  }

  input NotificationSlackInput {
    name: String!
    webhook: String!
    channel: String!
  }

  input DeleteNotificationSlackInput {
    name: String!
  }

  input NotificationToProjectInput {
    project: String!
    notificationType: String!
    notificationName: String!
  }

  input RemoveNotificationFromProjectInput {
    project: String!
    notificationType: String!
    notificationName: String!
  }

  input DeleteProjectInput {
    name: String!
  }

  type Mutation {
    addProject(input: ProjectInput!): Project
    deleteProject(input: DeleteProjectInput!): String
    addOrUpdateEnvironment(input: EnvironmentInput!): Environment
    deleteEnvironment(input: DeleteEnvironmentInput!): String
    addSshKey(input: SshKeyInput!): SshKey
    deleteSshKey(input: DeleteSshKeyInput!): String
    addCustomer(input: CustomerInput!): Customer
    deleteCustomer(input: DeleteCustomerInput!): String
    addOpenshift(input: OpenshiftInput!): Openshift
    deleteOpenshift(input: DeleteOpenshiftInput!): String
    addNotificationSlack(input: NotificationSlackInput!): NotificationSlack
    deleteNotificationSlack(input: DeleteNotificationSlackInput!): String
    addNotificationToProject(input: NotificationToProjectInput!): Project
    removeNotificationFromProject(input: RemoveNotificationFromProjectInput!): Project
    truncateTable(tableName: String!): String
  }
`;

const getCtx = req => req.app.get("context");
const getDao = req => getCtx(req).dao;

const resolvers = {
  Project: {
    customer: async (project, args, req) => {
      const dao = getDao(req);
      return await dao.getCustomerByProjectId(req.credentials, project.id);
    },
    sshKeys: async (project, args, req) => {
      const dao = getDao(req);
      return await dao.getSshKeysByProjectId(req.credentials, project.id)
    },
    notifications: async (project, args, req) => {
      const dao = getDao(req);
      return await dao.getNotificationsByProjectId(req.credentials, project.id, args)
    },
    openshift: async (project, args, req) => {
      const dao = getDao(req);
      return await dao.getOpenshiftByProjectId(req.credentials, project.id);
    },
    environments: async (project, args, req) => {
      const dao = getDao(req);
      return await dao.getEnvironmentsByProjectId(req.credentials, project.id);
    }
  },
  Environment: {
    project: async (environment, args, req) => {
      const dao = getDao(req);
      return await dao.getProjectByEnvironmentId(req.credentials, environment.id);
    }
  },
  Notification: {
    __resolveType(obj, context, info){
      switch (obj.type) {
        case 'slack':
          return 'NotificationSlack';
        default:
          return null;
      }
    },
  },
  Customer: {
    sshKeys: async (customer, args, req) => {
      const dao = getDao(req);
      return await dao.getSshKeysByCustomerId(req.credentials, customer.id)
    }
  },
  Query: {
    projectByGitUrl: async (root, args, req) => {
      const dao = getDao(req);
      return await dao.getProjectByGitUrl(req.credentials, args);
    },
    projectByName: async (root, args, req) => {
      const dao = getDao(req);
      return await dao.getProjectByName(req.credentials, args);
    },
    allProjects: async (root, args, req) => {
      const dao = getDao(req);
      return await dao.getAllProjects(req.credentials, args);
    },
    allCustomers: async (root, args, req) => {
      const dao = getDao(req);
      return await dao.getAllCustomers(req.credentials, args);
    },
    allOpenshifts: async (root, args, req) => {
      const dao = getDao(req);
      return await dao.getAllOpenshifts(req.credentials, args);
    }
  },
  Mutation: {
    addProject: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addProject(req.credentials, args.input);
      return ret;
    },
    deleteProject: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteProject(req.credentials, args.input);
      return ret;
    },
    addSshKey: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addSshKey(req.credentials, args.input);
      return ret;
    },
    deleteSshKey: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteSshKey(req.credentials, args.input);
      return ret;
    },
    addCustomer: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addCustomer(req.credentials, args.input);
      return ret;
    },
    deleteCustomer: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteCustomer(req.credentials, args.input);
      return ret;
    },
    addOpenshift: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addOpenshift(req.credentials, args.input);
      return ret;
    },
    deleteOpenshift: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteOpenshift(req.credentials, args.input);
      return ret;
    },
    addNotificationSlack: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addNotificationSlack(req.credentials, args.input);
      return ret;
    },
    deleteNotificationSlack: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteNotificationSlack(req.credentials, args.input);
      return ret;
    },
    addNotificationToProject: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addNotificationToProject(req.credentials, args.input);
      return ret;
    },
    removeNotificationFromProject: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.removeNotificationFromProject(req.credentials, args.input);
      return ret;
    },
    addOrUpdateEnvironment: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.addOrUpdateEnvironment(req.credentials, args.input);
      return ret;
    },
    deleteEnvironment: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.deleteEnvironment(req.credentials, args.input);
      return ret;
    },
    truncateTable: async (root, args, req) => {
      const dao = getDao(req);
      const ret = await dao.truncateTable(req.credentials, args);
      return ret;
    }
  }
};

module.exports = makeExecutableSchema({ typeDefs, resolvers });
<|endoftext|>


<commit_before>import deepEqual from 'deep-equal';
import linearRegression from 'simple-statistics/src/linear_regression';
import linearRegressionLine from 'simple-statistics/src/linear_regression_line';

const COMPONENT_NAME = 'click-drag';
const DRAG_START_EVENT = 'dragstart';
const DRAG_MOVE_EVENT = 'dragmove';
const DRAG_END_EVENT = 'dragend';

const TIME_TO_KEEP_LOG = 300;

function forceWorldUpdate(threeElement) {

  let element = threeElement;
  while (element.parent) {
    element = element.parent;
  }

  element.updateMatrixWorld(true);
}

function cameraPositionToVec3(camera, vec3) {

  let element = camera;

  vec3.set(
    element.components.position.data.x,
    element.components.position.data.y,
    element.components.position.data.z
  );

  while (element.attachedToParent) {

    element = element.parentElement;

    if (element.components && element.components.position) {
      vec3.set(
        vec3.x + element.components.position.data.x,
        vec3.y + element.components.position.data.y,
        vec3.z + element.components.position.data.z
      );
    }

  }

}

function localToWorld(THREE, threeCamera, vector) {
  forceWorldUpdate(threeCamera);
  return threeCamera.localToWorld(vector);
}

const {unproject} = (function unprojectFunction() {

  let initialized = false;

  let matrix;

  function initialize(THREE) {
    matrix = new THREE.Matrix4();

    return true;
  }

  return {

    unproject(THREE, vector, camera) {

      const threeCamera = camera.components.camera.camera;

      initialized = initialized || initialize(THREE);

      vector.applyProjection(matrix.getInverse(threeCamera.projectionMatrix));

      return localToWorld(THREE, threeCamera, vector);

    },
  };
}());

function clientCoordsTo3DCanvasCoords(
  clientX,
  clientY,
  offsetX,
  offsetY,
  clientWidth,
  clientHeight
) {
  return {
    x: (((clientX - offsetX) / clientWidth) * 2) - 1,
    y: (-((clientY - offsetY) / clientHeight) * 2) + 1,
  };
}

const {screenCoordsToDirection} = (function screenCoordsToDirectionFunction() {

  let initialized = false;

  let mousePosAsVec3;
  let cameraPosAsVec3;

  function initialize(THREE) {
    mousePosAsVec3 = new THREE.Vector3();
    cameraPosAsVec3 = new THREE.Vector3();

    return true;
  }

  return {
    screenCoordsToDirection(
      THREE,
      aframeCamera,
      {x: clientX, y: clientY}
    ) {

      initialized = initialized || initialize(THREE);

      // scale mouse coordinates down to -1 <-> +1
      const {x: mouseX, y: mouseY} = clientCoordsTo3DCanvasCoords(
        clientX, clientY,
        0, 0, // TODO: Replace with canvas position
        window.innerWidth,
        window.innerHeight
      );

      mousePosAsVec3.set(mouseX, mouseY, -1);

      // apply camera transformation from near-plane of mouse x/y into 3d space
      // NOTE: This should be replaced with THREE code directly once the aframe bug
      // is fixed:
/*
      cameraPositionToVec3(aframeCamera, cameraPosAsVec3);
      const {x, y, z} = new THREE
       .Vector3(mouseX, mouseY, -1)
       .unproject(aframeCamera.components.camera.camera)
       .sub(cameraPosAsVec3)
       .normalize();
*/
      const projectedVector = unproject(THREE, mousePosAsVec3, aframeCamera);

      cameraPositionToVec3(aframeCamera, cameraPosAsVec3);

      // Get the unit length direction vector from the camera's position
      const {x, y, z} = projectedVector.sub(cameraPosAsVec3).normalize();
      return {x, y, z};
    },
  };
}());

/**
 * @param planeNormal {THREE.Vector3}
 * @param planeConstant {Float} Distance from origin of the plane
 * @param rayDirection {THREE.Vector3} Direction of ray from the origin
 *
 * @return {THREE.Vector3} The intersection point of the ray and plane
 */
function rayPlaneIntersection(planeNormal, planeConstant, rayDirection) {
  // A line from the camera position toward (and through) the plane
  const distanceToPlane = planeConstant / planeNormal.dot(rayDirection);
  return rayDirection.multiplyScalar(distanceToPlane);
}

const {directionToWorldCoords} = (function directionToWorldCoordsFunction() {

  let initialized = false;

  let direction;
  let cameraPosAsVec3;

  function initialize(THREE) {
    direction = new THREE.Vector3();
    cameraPosAsVec3 = new THREE.Vector3();

    return true;
  }

  return {
    /**
     * @param camera Three.js Camera instance
     * @param Object Position of the camera
     * @param Object position of the mouse (scaled to be between -1 to 1)
     * @param depth Depth into the screen to calculate world coordinates for
     */
    directionToWorldCoords(
      THREE,
      aframeCamera,
      camera,
      {x: directionX, y: directionY, z: directionZ},
      depth
    ) {

      initialized = initialized || initialize(THREE);

      cameraPositionToVec3(aframeCamera, cameraPosAsVec3);
      direction.set(directionX, directionY, directionZ);

      // A line from the camera position toward (and through) the plane
      const newPosition = rayPlaneIntersection(
        camera.getWorldDirection(),
        depth,
        direction
      );

      // Reposition back to the camera position
      const {x, y, z} = newPosition.add(cameraPosAsVec3);

      return {x, y, z};

    },
  };
}());

const {selectItem} = (function selectItemFunction() {

  let initialized = false;

  let cameraPosAsVec3;
  let directionAsVec3;
  let raycaster;
  let plane;

  function initialize(THREE) {
    plane = new THREE.Plane();
    cameraPosAsVec3 = new THREE.Vector3();
    directionAsVec3 = new THREE.Vector3();
    raycaster = new THREE.Raycaster();

    // TODO: From camera values?
    raycaster.far = Infinity;
    raycaster.near = 0;

    return true;
  }

  return {
    selectItem(THREE, selector, camera, clientX, clientY) {

      initialized = initialized || initialize(THREE);

      const {x: directionX, y: directionY, z: directionZ} = screenCoordsToDirection(
        THREE,
        camera,
        {x: clientX, y: clientY}
      );

      cameraPositionToVec3(camera, cameraPosAsVec3);
      directionAsVec3.set(directionX, directionY, directionZ);

      raycaster.set(cameraPosAsVec3, directionAsVec3);

      // Push meshes onto list of objects to intersect.
      // TODO: Can we do this at some other point instead of every time a ray is
      // cast? Is that a micro optimization?
      const objects = Array.from(
        camera.sceneEl.querySelectorAll(`[${selector}]`)
      ).map(object => object.object3D);

      const recursive = true;

      const intersected = raycaster
        .intersectObjects(objects, recursive)
        // Only keep intersections against objects that have a reference to an entity.
        .filter(intersection => !!intersection.object.el)
        // Only keep ones that are visible
        .filter(intersection => intersection.object.parent.visible)
        // The first element is the closest
        [0]; // eslint-disable-line no-unexpected-multiline

      if (!intersected) {
        return {};
      }

      const {point, object} = intersected;

      // Aligned to the world direction of the camera
      // At the specified intersection point
      plane.setFromNormalAndCoplanarPoint(
        camera.components.camera.camera.getWorldDirection().clone().negate(),
        point.clone().sub(cameraPosAsVec3)
      );

      const depth = plane.constant;

      const offset = point.sub(object.getWorldPosition());

      return {depth, offset, element: object.el};

    },
  };
}());

function dragItem(THREE, element, offset, camera, depth, mouseInfo) {

  const {x: offsetX, y: offsetY, z: offsetZ} = offset;
  const lastCameraRotation = camera.components.camera.camera.rotation.clone();
  let lastMouseInfo = mouseInfo;

  function onMouseMove({clientX, clientY}) {

    lastMouseInfo = {clientX, clientY};

    const direction = screenCoordsToDirection(
      THREE,
      camera,
      {x: clientX, y: clientY}
    );

    const {x, y, z} = directionToWorldCoords(
      THREE,
      camera,
      camera.components.camera.camera,
      direction,
      depth
    );

    const nextPosition = {x: x - offsetX, y: y - offsetY, z: z - offsetZ};

    element.emit(DRAG_MOVE_EVENT, {nextPosition, clientX, clientY});

    element.setAttribute('position', nextPosition);
  }

  function onCameraChange({detail}) {
    if (
      (detail.name === 'position' || detail.name === 'rotation')
      && !deepEqual(detail.oldData, detail.newData)
    ) {
      onMouseMove(lastMouseInfo);
    }
  }

  document.addEventListener('mousemove', onMouseMove);
  camera.addEventListener('componentchanged', onCameraChange);

  // The "unlisten" function
  return _ => {
    document.removeEventListener('mousemove', onMouseMove);
    camera.removeEventListener('componentchanged', onCameraChange);
  };
}

// Closure to close over the removal of the event listeners
const {initialize, tearDown} = (function closeOverInitAndTearDown() {

  let removeClickListeners;

  return {
    initialize(THREE, componentName) {

      // TODO: Based on a scene from the element passed in?
      const scene = document.querySelector('a-scene');
      // delay loading of this as we're not 100% if the scene has loaded yet or not
      let camera;
      let removeDragListeners;
      let draggedElement;
      let dragInfo;
      const positionLog = [];

      function cleanUpPositionLog() {
        const now = performance.now();
        while (positionLog.length && now - positionLog[0].time > TIME_TO_KEEP_LOG) {
          // remove the first element;
          positionLog.shift();
        }
      }

      function onDragged({detail: {nextPosition}}) {
        // Continuously clean up so we don't get huge logs built up
        cleanUpPositionLog();
        positionLog.push({
          position: Object.assign({}, nextPosition),
          time: performance.now(),
        });
      }

      function onMouseDown({clientX, clientY}) {

        const {depth, offset, element} = selectItem(THREE, componentName, camera, clientX, clientY);

        if (element) {
          // Can only drag one item at a time, so no need to check if any
          // listener is already set up
          let removeDragItemListeners = dragItem(
            THREE,
            element,
            offset,
            camera,
            depth,
            {
              clientX,
              clientY,
            }
          );

          draggedElement = element;

          dragInfo = {
            offset: {x: offset.x, y: offset.y, z: offset.z},
            depth,
            clientX,
            clientY,
          };

          element.emit(DRAG_START_EVENT, dragInfo);

          element.addEventListener(DRAG_MOVE_EVENT, onDragged);

          removeDragListeners = _ => {
            element.removeEventListener(DRAG_MOVE_EVENT, onDragged);
            // eslint-disable-next-line no-unused-expressions
            removeDragItemListeners && removeDragItemListeners();
            // in case this removal function gets called more than once
            removeDragItemListeners = null;
          };
        }
      }

      function fitLineToVelocity(dimension) {

        if (positionLog.length < 2) {
          return 0;
        }

        const velocities = positionLog

          // Pull out just the x, y, or z values
          .map(log => ({time: log.time, value: log.position[dimension]}))

          // Then convert that into an array of array pairs [time, value]
          .reduce((memo, log, index, collection) => {

            // skip the first item (we're looking for pairs)
            if (index === 0) {
              return memo;
            }

            const deltaPosition = log.value - collection[index - 1].value;
            const deltaTime = (log.time - collection[index - 1].time) / 1000;

            // The new value is the change in position
            memo.push([log.time, deltaPosition / deltaTime]);

            return memo;

          }, []);

        // Calculate the line function
        const lineFunction = linearRegressionLine(linearRegression(velocities));

        // Calculate what the point was at the end of the line
        // ie; the velocity at the time the drag stopped
        return lineFunction(positionLog[positionLog.length - 1].time);
      }

      function onMouseUp({clientX, clientY}) {

        cleanUpPositionLog();

        const velocity = {
          x: fitLineToVelocity('x'),
          y: fitLineToVelocity('y'),
          z: fitLineToVelocity('z'),
        };

        draggedElement.emit(
          DRAG_END_EVENT,
          Object.assign({}, dragInfo, {clientX, clientY, velocity})
        );

        removeDragListeners && removeDragListeners(); // eslint-disable-line no-unused-expressions
        removeDragListeners = undefined;
      }

      function run() {

        camera = scene.camera.el;

        // TODO: Attach to canvas?
        document.addEventListener('mousedown', onMouseDown);
        document.addEventListener('mouseup', onMouseUp);

        removeClickListeners = _ => {
          document.removeEventListener('mousedown', onMouseDown);
          document.removeEventListener('mouseup', onMouseUp);
        };

      }

      if (scene.hasLoaded) {
        run();
      } else {
        scene.addEventListener('loaded', run);
      }

    },

    tearDown() {
      removeClickListeners && removeClickListeners(); // eslint-disable-line no-unused-expressions
      removeClickListeners = undefined;
    },
  };
}());

const {didMount, didUnmount} = (function getDidMountAndUnmount() {

  const cache = [];

  return {
    didMount(element, THREE, componentName) {

      if (cache.length === 0) {
        initialize(THREE, componentName);
      }

      if (cache.indexOf(element) === -1) {
        cache.push(element);
      }
    },

    didUnmount(element) {

      const cacheIndex = cache.indexOf(element);

      if (cacheIndex === -1) {
        return;
      }

      // remove that element
      cache.splice(cacheIndex, 1);

      if (cache.length === 0) {
        tearDown();
      }

    },
  };
}());

/**
 * @param aframe {Object} The Aframe instance to register with
 * @param componentName {String} The component name to use. Default: 'click-drag'
 */
export default function aframeDraggableComponent(aframe, componentName = COMPONENT_NAME) {

  const THREE = aframe.THREE;

  /**
   * Draggable component for A-Frame.
   */
  aframe.registerComponent(componentName, {
    schema: {
      lockToLocalRotation: {default: true},
    },

    /**
     * Called once when component is attached. Generally for initial setup.
     */
    init() {
      didMount(this, THREE, componentName);
    },

    /**
     * Called when component is attached and when component data changes.
     * Generally modifies the entity based on the data.
     *
     * @param oldData
     */
    update() { },

    /**
     * Called when a component is removed (e.g., via removeAttribute).
     * Generally undoes all modifications to the entity.
     */
    remove() {
      didUnmount();
    },

    /**
     * Called when entity pauses.
     * Use to stop or remove any dynamic or background behavior such as events.
     */
    pause() {
      didUnmount();
    },

    /**
     * Called when entity resumes.
     * Use to continue or add any dynamic or background behavior such as events.
     */
    play() {
      didMount(this, THREE, componentName);
    },
  });
}
<commit_msg>Correctly rotate object when locked to camera<commit_after>import deepEqual from 'deep-equal';
import linearRegression from 'simple-statistics/src/linear_regression';
import linearRegressionLine from 'simple-statistics/src/linear_regression_line';

const COMPONENT_NAME = 'click-drag';
const DRAG_START_EVENT = 'dragstart';
const DRAG_MOVE_EVENT = 'dragmove';
const DRAG_END_EVENT = 'dragend';

const TIME_TO_KEEP_LOG = 300;

function forceWorldUpdate(threeElement) {

  let element = threeElement;
  while (element.parent) {
    element = element.parent;
  }

  element.updateMatrixWorld(true);
}

function cameraPositionToVec3(camera, vec3) {

  let element = camera;

  vec3.set(
    element.components.position.data.x,
    element.components.position.data.y,
    element.components.position.data.z
  );

  while (element.attachedToParent) {

    element = element.parentElement;

    if (element.components && element.components.position) {
      vec3.set(
        vec3.x + element.components.position.data.x,
        vec3.y + element.components.position.data.y,
        vec3.z + element.components.position.data.z
      );
    }

  }

}

function localToWorld(THREE, threeCamera, vector) {
  forceWorldUpdate(threeCamera);
  return threeCamera.localToWorld(vector);
}

const {unproject} = (function unprojectFunction() {

  let initialized = false;

  let matrix;

  function initialize(THREE) {
    matrix = new THREE.Matrix4();

    return true;
  }

  return {

    unproject(THREE, vector, camera) {

      const threeCamera = camera.components.camera.camera;

      initialized = initialized || initialize(THREE);

      vector.applyProjection(matrix.getInverse(threeCamera.projectionMatrix));

      return localToWorld(THREE, threeCamera, vector);

    },
  };
}());

function clientCoordsTo3DCanvasCoords(
  clientX,
  clientY,
  offsetX,
  offsetY,
  clientWidth,
  clientHeight
) {
  return {
    x: (((clientX - offsetX) / clientWidth) * 2) - 1,
    y: (-((clientY - offsetY) / clientHeight) * 2) + 1,
  };
}

const {screenCoordsToDirection} = (function screenCoordsToDirectionFunction() {

  let initialized = false;

  let mousePosAsVec3;
  let cameraPosAsVec3;

  function initialize(THREE) {
    mousePosAsVec3 = new THREE.Vector3();
    cameraPosAsVec3 = new THREE.Vector3();

    return true;
  }

  return {
    screenCoordsToDirection(
      THREE,
      aframeCamera,
      {x: clientX, y: clientY}
    ) {

      initialized = initialized || initialize(THREE);

      // scale mouse coordinates down to -1 <-> +1
      const {x: mouseX, y: mouseY} = clientCoordsTo3DCanvasCoords(
        clientX, clientY,
        0, 0, // TODO: Replace with canvas position
        window.innerWidth,
        window.innerHeight
      );

      mousePosAsVec3.set(mouseX, mouseY, -1);

      // apply camera transformation from near-plane of mouse x/y into 3d space
      // NOTE: This should be replaced with THREE code directly once the aframe bug
      // is fixed:
/*
      cameraPositionToVec3(aframeCamera, cameraPosAsVec3);
      const {x, y, z} = new THREE
       .Vector3(mouseX, mouseY, -1)
       .unproject(aframeCamera.components.camera.camera)
       .sub(cameraPosAsVec3)
       .normalize();
*/
      const projectedVector = unproject(THREE, mousePosAsVec3, aframeCamera);

      cameraPositionToVec3(aframeCamera, cameraPosAsVec3);

      // Get the unit length direction vector from the camera's position
      const {x, y, z} = projectedVector.sub(cameraPosAsVec3).normalize();
      return {x, y, z};
    },
  };
}());

/**
 * @param planeNormal {THREE.Vector3}
 * @param planeConstant {Float} Distance from origin of the plane
 * @param rayDirection {THREE.Vector3} Direction of ray from the origin
 *
 * @return {THREE.Vector3} The intersection point of the ray and plane
 */
function rayPlaneIntersection(planeNormal, planeConstant, rayDirection) {
  // A line from the camera position toward (and through) the plane
  const distanceToPlane = planeConstant / planeNormal.dot(rayDirection);
  return rayDirection.multiplyScalar(distanceToPlane);
}

const {directionToWorldCoords} = (function directionToWorldCoordsFunction() {

  let initialized = false;

  let direction;
  let cameraPosAsVec3;

  function initialize(THREE) {
    direction = new THREE.Vector3();
    cameraPosAsVec3 = new THREE.Vector3();

    return true;
  }

  return {
    /**
     * @param camera Three.js Camera instance
     * @param Object Position of the camera
     * @param Object position of the mouse (scaled to be between -1 to 1)
     * @param depth Depth into the screen to calculate world coordinates for
     */
    directionToWorldCoords(
      THREE,
      aframeCamera,
      camera,
      {x: directionX, y: directionY, z: directionZ},
      depth
    ) {

      initialized = initialized || initialize(THREE);

      cameraPositionToVec3(aframeCamera, cameraPosAsVec3);
      direction.set(directionX, directionY, directionZ);

      // A line from the camera position toward (and through) the plane
      const newPosition = rayPlaneIntersection(
        camera.getWorldDirection(),
        depth,
        direction
      );

      // Reposition back to the camera position
      const {x, y, z} = newPosition.add(cameraPosAsVec3);

      return {x, y, z};

    },
  };
}());

const {selectItem} = (function selectItemFunction() {

  let initialized = false;

  let cameraPosAsVec3;
  let directionAsVec3;
  let raycaster;
  let plane;

  function initialize(THREE) {
    plane = new THREE.Plane();
    cameraPosAsVec3 = new THREE.Vector3();
    directionAsVec3 = new THREE.Vector3();
    raycaster = new THREE.Raycaster();

    // TODO: From camera values?
    raycaster.far = Infinity;
    raycaster.near = 0;

    return true;
  }

  return {
    selectItem(THREE, selector, camera, clientX, clientY) {

      initialized = initialized || initialize(THREE);

      const {x: directionX, y: directionY, z: directionZ} = screenCoordsToDirection(
        THREE,
        camera,
        {x: clientX, y: clientY}
      );

      cameraPositionToVec3(camera, cameraPosAsVec3);
      directionAsVec3.set(directionX, directionY, directionZ);

      raycaster.set(cameraPosAsVec3, directionAsVec3);

      // Push meshes onto list of objects to intersect.
      // TODO: Can we do this at some other point instead of every time a ray is
      // cast? Is that a micro optimization?
      const objects = Array.from(
        camera.sceneEl.querySelectorAll(`[${selector}]`)
      ).map(object => object.object3D);

      const recursive = true;

      const intersected = raycaster
        .intersectObjects(objects, recursive)
        // Only keep intersections against objects that have a reference to an entity.
        .filter(intersection => !!intersection.object.el)
        // Only keep ones that are visible
        .filter(intersection => intersection.object.parent.visible)
        // The first element is the closest
        [0]; // eslint-disable-line no-unexpected-multiline

      if (!intersected) {
        return {};
      }

      const {point, object} = intersected;

      // Aligned to the world direction of the camera
      // At the specified intersection point
      plane.setFromNormalAndCoplanarPoint(
        camera.components.camera.camera.getWorldDirection().clone().negate(),
        point.clone().sub(cameraPosAsVec3)
      );

      const depth = plane.constant;

      const offset = point.sub(object.getWorldPosition());

      return {depth, offset, element: object.el};

    },
  };
}());

function dragItem(THREE, element, offset, camera, depth, mouseInfo) {

  const {x: offsetX, y: offsetY, z: offsetZ} = offset;
  const threeCamera = camera.components.camera.camera;

  // Setting up for rotation calculations
  const startCameraRotationInverse = threeCamera.getWorldQuaternion().inverse();
  const startElementRotation = element.object3D.getWorldQuaternion();
  const elementRotationOrder = element.object3D.rotation.order;

  const rotationQuaternion = new THREE.Quaternion();
  const rotationEuler = new THREE.Euler();
  let lastMouseInfo = mouseInfo;

  function onMouseMove({clientX, clientY}) {

    lastMouseInfo = {clientX, clientY};

    const direction = screenCoordsToDirection(
      THREE,
      camera,
      {x: clientX, y: clientY}
    );

    const {x, y, z} = directionToWorldCoords(
      THREE,
      camera,
      camera.components.camera.camera,
      direction,
      depth
    );

    // 1. Store initial element rotation
    // 2. Store initial camera rotation
    // 3. Calculate difference in camera rotation, inverted
    // 4. Add #3 + #1
    // 5. Set element rotation to #4

    // Start by rotating backwards from the initial camera rotation
    const rotationDiff = rotationQuaternion.copy(startCameraRotationInverse)
      // Then add the current camera rotation
      .multiply(threeCamera.getWorldQuaternion())
      // And correctly offset rotation
      .multiply(startElementRotation);

    rotationEuler.setFromQuaternion(rotationDiff, elementRotationOrder);

    const nextRotation = {
      x: THREE.Math.radToDeg(rotationEuler.x),
      y: THREE.Math.radToDeg(rotationEuler.y),
      z: THREE.Math.radToDeg(rotationEuler.z),
    };

    const nextPosition = {x: x - offsetX, y: y - offsetY, z: z - offsetZ};

    element.emit(DRAG_MOVE_EVENT, {nextPosition, nextRotation, clientX, clientY});

    element.setAttribute('position', nextPosition);
    element.setAttribute('rotation', nextRotation);
  }

  function onCameraChange({detail}) {
    if (
      (detail.name === 'position' || detail.name === 'rotation')
      && !deepEqual(detail.oldData, detail.newData)
    ) {
      onMouseMove(lastMouseInfo);
    }
  }

  document.addEventListener('mousemove', onMouseMove);
  camera.addEventListener('componentchanged', onCameraChange);

  // The "unlisten" function
  return _ => {
    document.removeEventListener('mousemove', onMouseMove);
    camera.removeEventListener('componentchanged', onCameraChange);
  };
}

// Closure to close over the removal of the event listeners
const {initialize, tearDown} = (function closeOverInitAndTearDown() {

  let removeClickListeners;

  return {
    initialize(THREE, componentName) {

      // TODO: Based on a scene from the element passed in?
      const scene = document.querySelector('a-scene');
      // delay loading of this as we're not 100% if the scene has loaded yet or not
      let camera;
      let removeDragListeners;
      let draggedElement;
      let dragInfo;
      const positionLog = [];

      function cleanUpPositionLog() {
        const now = performance.now();
        while (positionLog.length && now - positionLog[0].time > TIME_TO_KEEP_LOG) {
          // remove the first element;
          positionLog.shift();
        }
      }

      function onDragged({detail: {nextPosition}}) {
        // Continuously clean up so we don't get huge logs built up
        cleanUpPositionLog();
        positionLog.push({
          position: Object.assign({}, nextPosition),
          time: performance.now(),
        });
      }

      function onMouseDown({clientX, clientY}) {

        const {depth, offset, element} = selectItem(THREE, componentName, camera, clientX, clientY);

        if (element) {
          // Can only drag one item at a time, so no need to check if any
          // listener is already set up
          let removeDragItemListeners = dragItem(
            THREE,
            element,
            offset,
            camera,
            depth,
            {
              clientX,
              clientY,
            }
          );

          draggedElement = element;

          dragInfo = {
            offset: {x: offset.x, y: offset.y, z: offset.z},
            depth,
            clientX,
            clientY,
          };

          element.emit(DRAG_START_EVENT, dragInfo);

          element.addEventListener(DRAG_MOVE_EVENT, onDragged);

          removeDragListeners = _ => {
            element.removeEventListener(DRAG_MOVE_EVENT, onDragged);
            // eslint-disable-next-line no-unused-expressions
            removeDragItemListeners && removeDragItemListeners();
            // in case this removal function gets called more than once
            removeDragItemListeners = null;
          };
        }
      }

      function fitLineToVelocity(dimension) {

        if (positionLog.length < 2) {
          return 0;
        }

        const velocities = positionLog

          // Pull out just the x, y, or z values
          .map(log => ({time: log.time, value: log.position[dimension]}))

          // Then convert that into an array of array pairs [time, value]
          .reduce((memo, log, index, collection) => {

            // skip the first item (we're looking for pairs)
            if (index === 0) {
              return memo;
            }

            const deltaPosition = log.value - collection[index - 1].value;
            const deltaTime = (log.time - collection[index - 1].time) / 1000;

            // The new value is the change in position
            memo.push([log.time, deltaPosition / deltaTime]);

            return memo;

          }, []);

        // Calculate the line function
        const lineFunction = linearRegressionLine(linearRegression(velocities));

        // Calculate what the point was at the end of the line
        // ie; the velocity at the time the drag stopped
        return lineFunction(positionLog[positionLog.length - 1].time);
      }

      function onMouseUp({clientX, clientY}) {

        cleanUpPositionLog();

        const velocity = {
          x: fitLineToVelocity('x'),
          y: fitLineToVelocity('y'),
          z: fitLineToVelocity('z'),
        };

        draggedElement.emit(
          DRAG_END_EVENT,
          Object.assign({}, dragInfo, {clientX, clientY, velocity})
        );

        removeDragListeners && removeDragListeners(); // eslint-disable-line no-unused-expressions
        removeDragListeners = undefined;
      }

      function run() {

        camera = scene.camera.el;

        // TODO: Attach to canvas?
        document.addEventListener('mousedown', onMouseDown);
        document.addEventListener('mouseup', onMouseUp);

        removeClickListeners = _ => {
          document.removeEventListener('mousedown', onMouseDown);
          document.removeEventListener('mouseup', onMouseUp);
        };

      }

      if (scene.hasLoaded) {
        run();
      } else {
        scene.addEventListener('loaded', run);
      }

    },

    tearDown() {
      removeClickListeners && removeClickListeners(); // eslint-disable-line no-unused-expressions
      removeClickListeners = undefined;
    },
  };
}());

const {didMount, didUnmount} = (function getDidMountAndUnmount() {

  const cache = [];

  return {
    didMount(element, THREE, componentName) {

      if (cache.length === 0) {
        initialize(THREE, componentName);
      }

      if (cache.indexOf(element) === -1) {
        cache.push(element);
      }
    },

    didUnmount(element) {

      const cacheIndex = cache.indexOf(element);

      if (cacheIndex === -1) {
        return;
      }

      // remove that element
      cache.splice(cacheIndex, 1);

      if (cache.length === 0) {
        tearDown();
      }

    },
  };
}());

/**
 * @param aframe {Object} The Aframe instance to register with
 * @param componentName {String} The component name to use. Default: 'click-drag'
 */
export default function aframeDraggableComponent(aframe, componentName = COMPONENT_NAME) {

  const THREE = aframe.THREE;

  /**
   * Draggable component for A-Frame.
   */
  aframe.registerComponent(componentName, {
    schema: {
      lockToLocalRotation: {default: true},
    },

    /**
     * Called once when component is attached. Generally for initial setup.
     */
    init() {
      didMount(this, THREE, componentName);
    },

    /**
     * Called when component is attached and when component data changes.
     * Generally modifies the entity based on the data.
     *
     * @param oldData
     */
    update() { },

    /**
     * Called when a component is removed (e.g., via removeAttribute).
     * Generally undoes all modifications to the entity.
     */
    remove() {
      didUnmount();
    },

    /**
     * Called when entity pauses.
     * Use to stop or remove any dynamic or background behavior such as events.
     */
    pause() {
      didUnmount();
    },

    /**
     * Called when entity resumes.
     * Use to continue or add any dynamic or background behavior such as events.
     */
    play() {
      didMount(this, THREE, componentName);
    },
  });
}
<|endoftext|>


<commit_before>var agent = require('http-ssh-agent');
var xtend = require('xtend');

var DEFAULT_PORT = 10002;

var parse = function(remote, opts) {
	if (!opts) opts = {};
	if (typeof remote !== 'string') return parse(remote && remote.remote || '127.0.0.1', remote);

	var parts = remote.match(/^(?:([^@]+)@)?([^:]+)(?::(?:(\d+)\+)?(\d+))?$/);

	if (parts[1]) {
		opts.type = 'http+ssh';
		opts.agent = agent(xtend(opts, {
			username:parts[1],
			host:parts[2],
			port:parseInt(parts[3] || 22, 10)
		}));
		opts.host = '127.0.0.1';
	} else {
		opts.host = parts[2];
		opts.type = 'http';
	}

	opts.port = parseInt(parts[4] || opts.port || DEFAULT_PORT, 10);

	return opts;
};

module.exports = parse;<commit_msg>using opts.url instead of opts.remote<commit_after>var agent = require('http-ssh-agent');
var xtend = require('xtend');

var DEFAULT_PORT = 10002;

var parse = function(remote, opts) {
	if (!opts) opts = {};
	if (typeof remote !== 'string') return parse(remote && remote.url || '127.0.0.1', remote);

	var parts = remote.match(/^(?:([^@]+)@)?([^:]+)(?::(?:(\d+)\+)?(\d+))?$/);

	if (parts[1]) {
		opts.type = 'http+ssh';
		opts.agent = agent(xtend(opts, {
			username:parts[1],
			host:parts[2],
			port:parseInt(parts[3] || 22, 10)
		}));
		opts.host = '127.0.0.1';
	} else {
		opts.host = parts[2];
		opts.type = 'http';
	}

	opts.port = parseInt(parts[4] || opts.port || DEFAULT_PORT, 10);

	return opts;
};

module.exports = parse;<|endoftext|>


<commit_before>var has = require("has"),
    freeze = require("freeze"),
    isNull = require("is_null"),
    isUndefined = require("is_undefined"),
    isObject = require("is_object"),
    defineProperty = require("define_property"),
    isEqual = require("is_equal"),
    hashCode = require("hash_code"),
    isArrayLike = require("is_array_like"),
    fastBindThis = require("fast_bind_this"),
    Box = require("./Box"),
    Iterator = require("./Iterator"),
    IteratorValue = require("./IteratorValue"),
    BitmapIndexedNode = require("./BitmapIndexedNode");

var INTERNAL_CREATE = {},

    ITERATOR_SYMBOL = typeof(Symbol) === "function" ? Symbol.iterator : false,
    IS_MAP = "__ImmutableHashMap__",

    NOT_SET = {},
    EMPTY_MAP = new HashMap(INTERNAL_CREATE),

    HashMapPrototype;

module.exports = HashMap;

function HashMap(value) {
    if (!(this instanceof HashMap)) {
        throw new Error("HashMap() must be called with new");
    }

    this.__size = 0;
    this.__root = null;

    if (value !== INTERNAL_CREATE) {
        return HashMap_createHashMap(this, value, arguments);
    } else {
        return this;
    }
}
HashMapPrototype = HashMap.prototype;

HashMap.EMPTY = freeze(EMPTY_MAP);

function HashMap_createHashMap(_this, value, args) {
    var length = args.length;

    if (length === 1) {
        if (isArrayLike(value)) {
            return HashMap_fromArray(_this, value.toArray ? value.toArray() : value);
        } else if (isObject(value)) {
            return HashMap_fromObject(_this, value);
        } else {
            return EMPTY_MAP;
        }
    } else if (length > 1) {
        return HashMap_fromArray(_this, args);
    } else {
        return EMPTY_MAP;
    }
}

function HashMap_fromObject(_this, object) {
    var size = 0,
        root = BitmapIndexedNode.EMPTY,
        key, value, newRoot, addedLeaf;

    for (key in object) {
        if (has(object, key)) {
            value = object[key];

            addedLeaf = new Box(null);
            newRoot = root.set(0, hashCode(key), key, value, addedLeaf);

            if (newRoot !== root) {
                root = newRoot;
                if (!isNull(addedLeaf.value)) {
                    size += 1;
                }
            }
        }
    }

    if (size !== 0) {
        _this.__size = size;
        _this.__root = newRoot;
        return freeze(_this);
    } else {
        return EMPTY_MAP;
    }
}

function HashMap_fromArray(_this, array) {
    var i = 0,
        il = array.length,
        root = BitmapIndexedNode.EMPTY,
        size = 0,
        newRoot, key, value, addedLeaf;

    while (i < il) {
        key = array[i];
        value = array[i + 1];
        addedLeaf = new Box(null);

        newRoot = root.set(0, hashCode(key), key, value, addedLeaf);
        if (newRoot !== root) {
            root = newRoot;
            if (!isNull(addedLeaf.value)) {
                size += 1;
            }
        }

        i += 2;
    }

    if (size !== 0) {
        _this.__root = root;
        _this.__size = size;
        return freeze(_this);
    } else {
        return EMPTY_MAP;
    }
}

HashMap.fromArray = function(array) {
    if (array.length > 0) {
        return HashMap_createHashMap(new HashMap(INTERNAL_CREATE), array[0], array);
    } else {
        return EMPTY_MAP;
    }
};

HashMap.of = function() {
    return HashMap.fromArray(arguments);
};

HashMap.isHashMap = function(value) {
    return value && value[IS_MAP] === true;
};

defineProperty(HashMapPrototype, IS_MAP, {
    configurable: false,
    enumerable: false,
    writable: false,
    value: true
});

HashMapPrototype.size = function() {
    return this.__size;
};

if (defineProperty.hasGettersSetters) {
    defineProperty(HashMapPrototype, "length", {
        get: HashMapPrototype.size
    });
}

HashMapPrototype.count = HashMapPrototype.size;

HashMapPrototype.isEmpty = function() {
    return this.__size === 0;
};

HashMapPrototype.has = function(key) {
    var root = this.__root;
    return isNull(root) ? false : root.get(0, hashCode(key), key, NOT_SET) !== NOT_SET;
};

HashMapPrototype.get = function(key) {
    var root = this.__root;
    return isNull(root) ? undefined : root.get(0, hashCode(key), key);
};

HashMapPrototype.set = function(key, value) {
    var root = this.__root,
        size = this.__size,
        addedLeaf = new Box(null),
        newRoot = (isNull(root) ? BitmapIndexedNode.EMPTY : root).set(0, hashCode(key), key, value, addedLeaf),
        map;

    if (newRoot === root) {
        return this;
    } else {
        map = new HashMap(INTERNAL_CREATE);
        map.__size = isNull(addedLeaf.value) ? size : size + 1;
        map.__root = newRoot;
        return freeze(map);
    }
};

HashMapPrototype.remove = function(key) {
    var root = this.__root,
        size = this.__size,
        newRoot;

    if (isNull(root)) {
        return this;
    } else if (size === 1) {
        return EMPTY_MAP;
    } else {
        newRoot = root.remove(0, hashCode(key), key);

        if (newRoot === root) {
            return this;
        } else {
            map = new HashMap(INTERNAL_CREATE);
            map.__size = size - 1;
            map.__root = newRoot;
            return freeze(map);
        }
    }
};

function hasNext() {
    return false;
}

function next() {
    return new IteratorValue(true, undefined);
}

HashMapPrototype.iterator = function(reverse) {
    var root = this.__root;

    if (isNull(root)) {
        return new Iterator(hasNext, next);
    } else {
        return root.iterator(reverse);
    }
};

if (ITERATOR_SYMBOL) {
    HashMapPrototype[ITERATOR_SYMBOL] = HashMapPrototype.iterator;
}

function HashMap_every(_this, it, callback) {
    var next = it.next(),
        nextValue;

    while (next.done === false) {
        nextValue = next.value;
        if (!callback(nextValue[1], nextValue[0], _this)) {
            return false;
        }
        next = it.next();
    }

    return true;
}

HashMapPrototype.every = function(callback, thisArg) {
    return HashMap_every(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

function HashMap_filter(_this, it, callback) {
    var results = [],
        next = it.next(),
        index = 0,
        nextValue, key, value;

    while (next.done === false) {
        nextValue = next.value;
        key = nextValue[0];
        value = nextValue[1];

        if (callback(value, key, _this)) {
            results[index++] = key;
            results[index++] = value;
        }

        next = it.next();
    }

    return HashMap.of(results);
}

HashMapPrototype.filter = function(callback, thisArg) {
    return HashMap_filter(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

function HashMap_forEach(_this, it, callback) {
    var next = it.next(),
        nextValue;

    while (next.done === false) {
        nextValue = next.value;
        if (callback(nextValue[1], nextValue[0], _this) === false) {
            break;
        }
        next = it.next();
    }

    return _this;
}

HashMapPrototype.forEach = function(callback, thisArg) {
    return HashMap_forEach(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

HashMapPrototype.each = HashMapPrototype.forEach;

function HashMap_forEachRight(_this, it, callback) {
    var next = it.next(),
        nextValue;

    while (next.done === false) {
        nextValue = next.value;
        if (callback(nextValue[1], nextValue[0], _this) === false) {
            break;
        }
        next = it.next();
    }

    return _this;
}

HashMapPrototype.forEachRight = function(callback, thisArg) {
    return HashMap_forEachRight(this, this.iterator(true), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

HashMapPrototype.eachRight = HashMapPrototype.forEachRight;

function HashMap_map(_this, it, callback) {
    var next = it.next(),
        results = new Array(_this.__size * 2),
        index = 0,
        nextValue, key, resultValue;

    while (next.done === false) {
        nextValue = next.value;
        key = nextValue[0];
        resultValue = callback(nextValue[1], key, _this);
        results[index++] = resultValue[0];
        results[index++] = resultValue[1];
        next = it.next();
    }

    return HashMap.of(results);
}

HashMapPrototype.map = function(callback, thisArg) {
    return HashMap_map(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

function HashMap_reduce(_this, it, callback, initialValue) {
    var next = it.next(),
        value = initialValue,
        nextValue, key;

    if (isUndefined(value)) {
        nextValue = next.value;
        key = nextValue[0];
        value = nextValue[1];
        next = it.next();
    }

    while (next.done === false) {
        nextValue = next.value;
        value = callback(value, nextValue[1], key, _this);
        next = it.next();
    }

    return value;
}

HashMapPrototype.reduce = function(callback, initialValue, thisArg) {
    return HashMap_reduce(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 4), initialValue);
};

function HashMap_reduceRight(_this, it, callback, initialValue) {
    var next = it.next(),
        value = initialValue,
        nextValue, key;

    if (isUndefined(value)) {
        nextValue = next.value;
        key = nextValue[0];
        value = nextValue[1];
        next = it.next();
    }

    while (next.done === false) {
        nextValue = next.value;
        value = callback(value, nextValue[1], key, _this);
        next = it.next();
    }

    return value;
}

HashMapPrototype.reduceRight = function(callback, initialValue, thisArg) {
    return HashMap_reduceRight(this, this.iterator(true), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 4), initialValue);
};

function HashMap_some(_this, it, callback) {
    var next = it.next(),
        nextValue;

    while (next.done === false) {
        nextValue = next.value;

        if (callback(nextValue[1], nextValue[0], _this)) {
            return true;
        }
        next = it.next();
    }

    return false;
}

HashMapPrototype.some = function(callback, thisArg) {
    return HashMap_some(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

HashMapPrototype.toArray = function() {
    var it = this.iterator(),
        next = it.next(),
        results = new Array(this.__size * 2),
        index = 0;

    while (next.done === false) {
        nextValue = next.value;
        results[index++] = nextValue[0];
        results[index++] = nextValue[1];
        next = it.next();
    }

    return results;
};

HashMapPrototype.toObject = function() {
    var it = this.iterator(),
        next = it.next(),
        results = {};

    while (next.done === false) {
        nextValue = next.value;
        results[nextValue[0]] = nextValue[1];
        next = it.next();
    }

    return results;
};

HashMapPrototype.join = function(separator, keyValueSeparator) {
    var it = this.iterator(),
        next = it.next(),
        result = "";

    separator = separator || ", ";
    keyValueSeparator = keyValueSeparator || ": ";

    while (true) {
        nextValue = next.value;
        next = it.next();

        if (next.done) {
            result += nextValue[0] + keyValueSeparator + nextValue[1];
            break;
        } else {
            result += nextValue[0] + keyValueSeparator + nextValue[1] + separator;
        }
    }

    return result;
};

HashMapPrototype.toString = function() {
    return "{" + this.join() + "}";
};

HashMapPrototype.inspect = HashMapPrototype.toString;

function HashMap_equal(ait, bit) {
    var anext = ait.next(),
        bnext = bit.next(),
        anextValue, bnextValue;

    while (anext.done === false) {
        anextValue = anext.value;
        bnextValue = bnext.value;

        if (!isEqual(anextValue[0], bnextValue[0]) || !isEqual(anextValue[1], bnextValue[1])) {
            return false;
        }

        anext = ait.next();
        bnext = bit.next();
    }

    return true;
}

HashMap.equal = function(a, b) {
    if (a === b) {
        return true;
    } else if (!a || !b || a.__size !== b.__size) {
        return false;
    } else {
        return HashMap_equal(a.iterator(), b.iterator());
    }
};

HashMapPrototype.equals = function(b) {
    return HashMap.equal(this, b);
};
<commit_msg>updates<commit_after>var has = require("has"),
    freeze = require("freeze"),
    isNull = require("is_null"),
    isUndefined = require("is_undefined"),
    isObject = require("is_object"),
    defineProperty = require("define_property"),
    isEqual = require("is_equal"),
    hashCode = require("hash_code"),
    isArrayLike = require("is_array_like"),
    fastBindThis = require("fast_bind_this"),
    Box = require("./Box"),
    Iterator = require("./Iterator"),
    IteratorValue = require("./IteratorValue"),
    BitmapIndexedNode = require("./BitmapIndexedNode");

var INTERNAL_CREATE = {},

    ITERATOR_SYMBOL = typeof(Symbol) === "function" ? Symbol.iterator : false,
    IS_MAP = "__ImmutableHashMap__",

    NOT_SET = {},
    EMPTY_MAP = new HashMap(INTERNAL_CREATE),

    HashMapPrototype;

module.exports = HashMap;

function HashMap(value) {
    if (!(this instanceof HashMap)) {
        throw new Error("HashMap() must be called with new");
    }

    this.__size = 0;
    this.__root = null;

    if (value !== INTERNAL_CREATE) {
        return HashMap_createHashMap(this, value, arguments);
    } else {
        return this;
    }
}
HashMapPrototype = HashMap.prototype;

HashMap.EMPTY = freeze(EMPTY_MAP);

function HashMap_createHashMap(_this, value, args) {
    var length = args.length;

    if (length === 1) {
        if (isArrayLike(value)) {
            return HashMap_fromArray(_this, value.toArray ? value.toArray() : value);
        } else if (isObject(value)) {
            return HashMap_fromObject(_this, value);
        } else {
            return EMPTY_MAP;
        }
    } else if (length > 1) {
        return HashMap_fromArray(_this, args);
    } else {
        return EMPTY_MAP;
    }
}

function HashMap_fromObject(_this, object) {
    var size = 0,
        root = BitmapIndexedNode.EMPTY,
        key, value, newRoot, addedLeaf;

    for (key in object) {
        if (has(object, key)) {
            value = object[key];

            addedLeaf = new Box(null);
            newRoot = root.set(0, hashCode(key), key, value, addedLeaf);

            if (newRoot !== root) {
                root = newRoot;
                if (!isNull(addedLeaf.value)) {
                    size += 1;
                }
            }
        }
    }

    if (size !== 0) {
        _this.__size = size;
        _this.__root = newRoot;
        return freeze(_this);
    } else {
        return EMPTY_MAP;
    }
}

function HashMap_fromArray(_this, array) {
    var i = 0,
        il = array.length,
        root = BitmapIndexedNode.EMPTY,
        size = 0,
        newRoot, key, value, addedLeaf;

    while (i < il) {
        key = array[i];
        value = array[i + 1];
        addedLeaf = new Box(null);

        newRoot = root.set(0, hashCode(key), key, value, addedLeaf);
        if (newRoot !== root) {
            root = newRoot;
            if (!isNull(addedLeaf.value)) {
                size += 1;
            }
        }

        i += 2;
    }

    if (size !== 0) {
        _this.__root = root;
        _this.__size = size;
        return freeze(_this);
    } else {
        return EMPTY_MAP;
    }
}

HashMap.fromArray = function(array) {
    if (array.length > 0) {
        return HashMap_createHashMap(new HashMap(INTERNAL_CREATE), array[0], array);
    } else {
        return EMPTY_MAP;
    }
};

HashMap.of = function() {
    return HashMap.fromArray(arguments);
};

HashMap.isHashMap = function(value) {
    return value && value[IS_MAP] === true;
};

defineProperty(HashMapPrototype, IS_MAP, {
    configurable: false,
    enumerable: false,
    writable: false,
    value: true
});

HashMapPrototype.size = function() {
    return this.__size;
};

if (defineProperty.hasGettersSetters) {
    defineProperty(HashMapPrototype, "length", {
        get: HashMapPrototype.size
    });
}

HashMapPrototype.count = HashMapPrototype.size;

HashMapPrototype.isEmpty = function() {
    return this.__size === 0;
};

HashMapPrototype.has = function(key) {
    var root = this.__root;
    return isNull(root) ? false : root.get(0, hashCode(key), key, NOT_SET) !== NOT_SET;
};

HashMapPrototype.get = function(key) {
    var root = this.__root;
    return isNull(root) ? undefined : root.get(0, hashCode(key), key);
};

HashMapPrototype.set = function(key, value) {
    var root = this.__root,
        size = this.__size,
        addedLeaf = new Box(null),
        newRoot = (isNull(root) ? BitmapIndexedNode.EMPTY : root).set(0, hashCode(key), key, value, addedLeaf),
        map;

    if (newRoot === root) {
        return this;
    } else {
        map = new HashMap(INTERNAL_CREATE);
        map.__size = isNull(addedLeaf.value) ? size : size + 1;
        map.__root = newRoot;
        return freeze(map);
    }
};

HashMapPrototype.remove = function(key) {
    var root = this.__root,
        size = this.__size,
        newRoot;

    if (isNull(root)) {
        return this;
    } else if (size === 1) {
        return EMPTY_MAP;
    } else {
        newRoot = root.remove(0, hashCode(key), key);

        if (newRoot === root) {
            return this;
        } else {
            map = new HashMap(INTERNAL_CREATE);
            map.__size = size - 1;
            map.__root = newRoot;
            return freeze(map);
        }
    }
};

function hasNext() {
    return false;
}

function next() {
    return new IteratorValue(true, undefined);
}

HashMapPrototype.iterator = function(reverse) {
    var root = this.__root;

    if (isNull(root)) {
        return new Iterator(hasNext, next);
    } else {
        return root.iterator(reverse);
    }
};

if (ITERATOR_SYMBOL) {
    HashMapPrototype[ITERATOR_SYMBOL] = HashMapPrototype.iterator;
}

function HashMap_every(_this, it, callback) {
    var next = it.next(),
        nextValue;

    while (next.done === false) {
        nextValue = next.value;
        if (!callback(nextValue[1], nextValue[0], _this)) {
            return false;
        }
        next = it.next();
    }

    return true;
}

HashMapPrototype.every = function(callback, thisArg) {
    return HashMap_every(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

function HashMap_filter(_this, it, callback) {
    var results = [],
        next = it.next(),
        index = 0,
        nextValue, key, value;

    while (next.done === false) {
        nextValue = next.value;
        key = nextValue[0];
        value = nextValue[1];

        if (callback(value, key, _this)) {
            results[index++] = key;
            results[index++] = value;
        }

        next = it.next();
    }

    return HashMap.of(results);
}

HashMapPrototype.filter = function(callback, thisArg) {
    return HashMap_filter(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

function HashMap_forEach(_this, it, callback) {
    var next = it.next(),
        nextValue;

    while (next.done === false) {
        nextValue = next.value;
        if (callback(nextValue[1], nextValue[0], _this) === false) {
            break;
        }
        next = it.next();
    }

    return _this;
}

HashMapPrototype.forEach = function(callback, thisArg) {
    return HashMap_forEach(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

HashMapPrototype.each = HashMapPrototype.forEach;

function HashMap_forEachRight(_this, it, callback) {
    var next = it.next(),
        nextValue;

    while (next.done === false) {
        nextValue = next.value;
        if (callback(nextValue[1], nextValue[0], _this) === false) {
            break;
        }
        next = it.next();
    }

    return _this;
}

HashMapPrototype.forEachRight = function(callback, thisArg) {
    return HashMap_forEachRight(this, this.iterator(true), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

HashMapPrototype.eachRight = HashMapPrototype.forEachRight;

function HashMap_map(_this, it, callback) {
    var next = it.next(),
        results = new Array(_this.__size * 2),
        index = 0,
        nextValue, key, resultValue;

    while (next.done === false) {
        nextValue = next.value;
        key = nextValue[0];
        resultValue = callback(nextValue[1], key, _this);
        results[index++] = resultValue[0];
        results[index++] = resultValue[1];
        next = it.next();
    }

    return HashMap.of(results);
}

HashMapPrototype.map = function(callback, thisArg) {
    return HashMap_map(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

function HashMap_reduce(_this, it, callback, initialValue) {
    var next = it.next(),
        value = initialValue,
        nextValue, key;

    if (isUndefined(value)) {
        nextValue = next.value;
        key = nextValue[0];
        value = nextValue[1];
        next = it.next();
    }

    while (next.done === false) {
        nextValue = next.value;
        value = callback(value, nextValue[1], key, _this);
        next = it.next();
    }

    return value;
}

HashMapPrototype.reduce = function(callback, initialValue, thisArg) {
    return HashMap_reduce(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 4), initialValue);
};

function HashMap_reduceRight(_this, it, callback, initialValue) {
    var next = it.next(),
        value = initialValue,
        nextValue, key;

    if (isUndefined(value)) {
        nextValue = next.value;
        key = nextValue[0];
        value = nextValue[1];
        next = it.next();
    }

    while (next.done === false) {
        nextValue = next.value;
        value = callback(value, nextValue[1], key, _this);
        next = it.next();
    }

    return value;
}

HashMapPrototype.reduceRight = function(callback, initialValue, thisArg) {
    return HashMap_reduceRight(this, this.iterator(true), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 4), initialValue);
};

function HashMap_some(_this, it, callback) {
    var next = it.next(),
        nextValue;

    while (next.done === false) {
        nextValue = next.value;

        if (callback(nextValue[1], nextValue[0], _this)) {
            return true;
        }
        next = it.next();
    }

    return false;
}

HashMapPrototype.some = function(callback, thisArg) {
    return HashMap_some(this, this.iterator(), isUndefined(thisArg) ? callback : fastBindThis(callback, thisArg, 3));
};

HashMapPrototype.toArray = function() {
    var it = this.iterator(),
        next = it.next(),
        results = new Array(this.__size * 2),
        index = 0;

    while (next.done === false) {
        nextValue = next.value;
        results[index++] = nextValue[0];
        results[index++] = nextValue[1];
        next = it.next();
    }

    return results;
};

HashMapPrototype.toObject = function() {
    var it = this.iterator(),
        next = it.next(),
        results = {};

    while (next.done === false) {
        nextValue = next.value;
        results[nextValue[0]] = nextValue[1];
        next = it.next();
    }

    return results;
};

HashMapPrototype.join = function(separator, keyValueSeparator) {
    var it = this.iterator(),
        next = it.next(),
        result = "";

    separator = separator || ", ";
    keyValueSeparator = keyValueSeparator || ": ";

    while (!next.done) {
        nextValue = next.value;
        next = it.next();

        if (next.done) {
            result += nextValue[0] + keyValueSeparator + nextValue[1];
            break;
        } else {
            result += nextValue[0] + keyValueSeparator + nextValue[1] + separator;
        }
    }

    return result;
};

HashMapPrototype.toString = function() {
    return "{" + this.join() + "}";
};

HashMapPrototype.inspect = HashMapPrototype.toString;

function HashMap_equal(ait, bit) {
    var anext = ait.next(),
        bnext = bit.next(),
        anextValue, bnextValue;

    while (anext.done === false) {
        anextValue = anext.value;
        bnextValue = bnext.value;

        if (!isEqual(anextValue[0], bnextValue[0]) || !isEqual(anextValue[1], bnextValue[1])) {
            return false;
        }

        anext = ait.next();
        bnext = bit.next();
    }

    return true;
}

HashMap.equal = function(a, b) {
    if (a === b) {
        return true;
    } else if (!a || !b || a.__size !== b.__size) {
        return false;
    } else {
        return HashMap_equal(a.iterator(), b.iterator());
    }
};

HashMapPrototype.equals = function(b) {
    return HashMap.equal(this, b);
};
<|endoftext|>