<commit_before>var AWS = require('./core');
require('./sequential_executor');
require('./service_interface/json');
require('./service_interface/query');
require('./service_interface/rest');
require('./service_interface/rest_json');
require('./service_interface/rest_xml');

/**
 * The namespace used to register global event listeners for request building
 * and sending.
 */
AWS.EventListeners = {
  /**
   * @!attribute VALIDATE_CREDENTIALS
   *   A request listener that validates whether the request is being
   *   sent with credentials.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating credentials
   *     var listener = AWS.EventListeners.Core.VALIDATE_CREDENTIALS;
   *     request.removeListener('validate', listener);
   *   @readonly
   *   @return [Function]
   * @!attribute VALIDATE_REGION
   *   A request listener that validates whether the region is set
   *   for a request.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating region configuration
   *     var listener = AWS.EventListeners.Core.VALIDATE_REGION;
   *     request.removeListener('validate', listener);
   *   @readonly
   *   @return [Function]
   * @!attribute VALIDATE_PARAMETERS
   *   A request listener that validates input parameters in a request.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating parameters
   *     var listener = AWS.EventListeners.Core.VALIDATE_PARAMETERS;
   *     request.removeListener('validate', listener);
   *   @example Disable parameter validation globally
   *     AWS.EventListeners.Core.removeListener('validate',
   *       AWS.EventListeners.Core.VALIDATE_REGION);
   *   @readonly
   *   @return [Function]
   * @!attribute SEND
   *   A request listener that initiates the HTTP connection for a
   *   request being sent. Handles the {AWS.Request~send 'send' Request event}
   *   @example Replacing the HTTP handler
   *     var listener = AWS.EventListeners.Core.SEND;
   *     request.removeListener('send', listener);
   *     request.on('send', function(response) {
   *       customHandler.send(response);
   *     });
   *   @return [Function]
   *   @readonly
   * @!attribute HTTP_DATA
   *   A request listener that reads data from the HTTP connection in order
   *   to build the response data.
   *   Handles the {AWS.Request~httpData 'httpData' Request event}.
   *   Remove this handler if you are overriding the 'httpData' event and
   *   do not want extra data processing and buffering overhead.
   *   @example Disabling default data processing
   *     var listener = AWS.EventListeners.Core.HTTP_DATA;
   *     request.removeListener('httpData', listener);
   *   @return [Function]
   *   @readonly
   */
  Core: {} /* doc hack */
};

AWS.EventListeners = {
  Core: new AWS.SequentialExecutor().addNamedListeners(function(add, addAsync) {
    addAsync('VALIDATE_CREDENTIALS', 'validate',
        function VALIDATE_CREDENTIALS(req, done) {
      req.service.config.getCredentials(function(err) {
        if (err) {
          req.response.err = AWS.util.error(err,
            {code: 'SigningError', message: 'Missing credentials in config'});
        }
        done();
      });
    });

    add('VALIDATE_REGION', 'validate', function VALIDATE_REGION(req) {
      if (!req.service.config.region && !req.service.hasGlobalEndpoint()) {
        req.response.error = AWS.util.error(new Error(),
          {code: 'SigningError', message: 'Missing region in config'});
      }
    });

    add('VALIDATE_PARAMETERS', 'validate', function VALIDATE_PARAMETERS(req) {
      var rules = req.service.api.operations[req.operation].input;
      new AWS.ParamValidator().validate(rules, req.params);
    });

    add('SET_CONTENT_LENGTH', 'afterBuild', function SET_CONTENT_LENGTH(req) {
      if (req.httpRequest.headers['Content-Length'] === undefined) {
        var length = AWS.util.string.byteLength(req.httpRequest.body);
        req.httpRequest.headers['Content-Length'] = length;
      }
    });

    add('SET_HTTP_HOST', 'afterBuild', function SET_HTTP_HOST(req) {
      req.httpRequest.headers['Host'] = req.httpRequest.endpoint.host;
    });

    addAsync('SIGN', 'sign', function SIGN(req, done) {
      if (!req.service.api.signatureVersion) return done(); // none

      req.service.config.getCredentials(function (err, credentials) {
        if (err) {
          req.response.error = err;
          return done();
        }

        try {
          var date = AWS.util.date.getDate();
          var SignerClass = req.service.getSignerClass(req);
          var signer = new SignerClass(req.httpRequest,
            req.service.api.signingName || req.service.api.endpointPrefix);

          // clear old authorization headers
          delete req.httpRequest.headers['Authorization'];
          delete req.httpRequest.headers['Date'];
          delete req.httpRequest.headers['X-Amz-Date'];

          // add new authorization
          signer.addAuthorization(credentials, date);
        } catch (e) {
          req.response.error = e;
        }
        done();
      });
    });

    add('VALIDATE_RESPONSE', 'validateResponse', function VALIDATE_RESPONSE(resp) {
      if (this.service.successfulResponse(resp, this)) {
        resp.data = {};
        resp.error = null;
      } else {
        resp.data = null;
        resp.error = AWS.util.error(new Error(),
          {code: 'UnknownError', message: 'An unknown error occurred.'});
      }
    });

    addAsync('SEND', 'send', function SEND(resp, done) {
      resp.httpResponse._abortCallback = done;

      function callback(httpResp) {
        resp.httpResponse.stream = httpResp;

        httpResp.on('headers', function onHeaders(statusCode, headers) {
          resp.request.emit('httpHeaders', [statusCode, headers, resp]);

          if (!resp.request.httpRequest._streaming) {
            if (AWS.HttpClient.streamsApiVersion === 2) { // streams2 API check
              httpResp.on('readable', function onReadable() {
                var data = httpResp.read();
                if (data !== null) {
                  resp.request.emit('httpData', [data, resp]);
                }
              });
            } else { // legacy streams API
              httpResp.on('data', function onData(data) {
                resp.request.emit('httpData', [data, resp]);
              });
            }
          }
        });

        httpResp.on('end', function onEnd() {
          resp.request.emit('httpDone');
          done();
        });
      }

      function progress(httpResp) {
        httpResp.on('sendProgress', function onSendProgress(progress) {
          resp.request.emit('httpUploadProgress', [progress, resp]);
        });

        httpResp.on('receiveProgress', function onReceiveProgress(progress) {
          resp.request.emit('httpDownloadProgress', [progress, resp]);
        });
      }

      function error(err) {
        resp.error = AWS.util.error(err, {
          code: 'NetworkingError',
          region: resp.request.httpRequest.region,
          hostname: resp.request.httpRequest.endpoint.hostname,
          retryable: true
        });
        resp.request.emit('httpError', [resp.error, resp], function() {
          done();
        });
      }

      resp.error = null;
      resp.data = null;

      var http = AWS.HttpClient.getInstance();
      var httpOptions = resp.request.service.config.httpOptions || {};
      var s = http.handleRequest(this.httpRequest, httpOptions, callback, error);
      progress(s);
    });

    add('HTTP_HEADERS', 'httpHeaders',
        function HTTP_HEADERS(statusCode, headers, resp) {
      resp.httpResponse.statusCode = statusCode;
      resp.httpResponse.headers = headers;
      resp.httpResponse.body = new AWS.util.Buffer('');
      resp.httpResponse.buffers = [];
      resp.httpResponse.numBytes = 0;
    });

    add('HTTP_DATA', 'httpData', function HTTP_DATA(chunk, resp) {
      if (chunk) {
        if (AWS.util.isNode()) {
          resp.httpResponse.numBytes += chunk.length;

          var total = resp.httpResponse.headers['content-length'];
          var progress = { loaded: resp.httpResponse.numBytes, total: total };
          resp.request.emit('httpDownloadProgress', [progress, resp]);
        }

        resp.httpResponse.buffers.push(new AWS.util.Buffer(chunk));
      }
    });

    add('HTTP_DONE', 'httpDone', function HTTP_DONE(resp) {
      // convert buffers array into single buffer
      if (resp.httpResponse.buffers && resp.httpResponse.buffers.length > 0) {
        var body = AWS.util.buffer.concat(resp.httpResponse.buffers);
        resp.httpResponse.body = body;
      }
      delete resp.httpResponse.numBytes;
      delete resp.httpResponse.buffers;
    });

    add('FINALIZE_ERROR', 'retry', function FINALIZE_ERROR(resp) {
      if (resp.httpResponse.statusCode) {
        resp.error.statusCode = resp.httpResponse.statusCode;
        if (resp.error.retryable === undefined) {
          resp.error.retryable = this.service.retryableError(resp.error, this);
        }
      }
    });

    add('INVALIDATE_CREDENTIALS', 'retry', function INVALIDATE_CREDENTIALS(resp) {
      switch (resp.error.code) {
        case 'RequestExpired': // EC2 only
        case 'ExpiredTokenException':
        case 'ExpiredToken':
          resp.error.retryable = true;
          resp.request.service.config.credentials.expired = true;
      }
    });

    add('REDIRECT', 'retry', function REDIRECT(resp) {
      if (resp.error && resp.error.statusCode >= 300 &&
          resp.error.statusCode < 400 && resp.httpResponse.headers['location']) {
        this.httpRequest.endpoint =
          new AWS.Endpoint(resp.httpResponse.headers['location']);
        resp.error.redirect = true;
        resp.error.retryable = true;
      }
    });

    add('RETRY_CHECK', 'retry', function RETRY_CHECK(resp) {
      if (resp.error) {
        if (resp.error.redirect && resp.redirectCount < resp.maxRedirects) {
          resp.error.retryDelay = 0;
          resp.redirectCount++;
          resp.error._willRetry = true;
        } else if (resp.error.retryable && resp.retryCount < resp.maxRetries) {
          var delays = this.service.retryDelays();
          resp.error.retryDelay = delays[resp.retryCount] || 0;
          resp.retryCount++;
          resp.error._willRetry = true;
        } else {
          resp.error._willRetry = false;
        }
      }
    });

    addAsync('RESET_RETRY_STATE', 'afterRetry', function RESET_RETRY_STATE(resp, done) {
      if (resp.error && resp.error._willRetry) {
        var delay = resp.error.retryDelay || 0;
        resp.error = null;
        setTimeout(done, delay);
      } else {
        done();
      }
    });

  }),

  CorePost: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    add('EXTRACT_REQUEST_ID', 'extractData', function EXTRACT_REQUEST_ID(resp) {
      resp.requestId = resp.httpResponse.headers['x-amz-request-id'] ||
                       resp.httpResponse.headers['x-amzn-requestid'];
    });
  }),

  Logger: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    add('LOG_REQUEST', 'complete', function LOG_REQUEST(resp) {
      var req = resp.request;
      var logger = req.service.config.logger;
      if (!logger) return;

      function buildMessage() {
        var time = AWS.util.date.getDate().getTime();
        var delta = (time - req.startTime.getTime()) / 1000;
        var ansi = logger.isTTY ? true : false;
        var status = resp.httpResponse.statusCode;
        var params = require('util').inspect(req.params, true, true);

        var message = '';
        if (ansi) message += '\x1B[33m';
        message += '[AWS ' + req.service.serviceIdentifier + ' ' + status;
        message += ' ' + delta.toString() + 's ' + resp.retryCount + ' retries]';
        if (ansi) message += '\x1B[0;1m';
        message += ' ' + req.operation + '(' + params + ')';
        if (ansi) message += '\x1B[0m';
        return message;
      }

      var line = buildMessage();
      if (typeof logger.log === 'function') {
        logger.log(line);
      } else if (typeof logger.write === 'function') {
        logger.write(line + '\n');
      }
    });
  }),

  Json: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Json;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  Rest: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Rest;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  RestJson: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.RestJson;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  RestXml: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.RestXml;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  Query: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Query;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  })
};
<commit_msg>Re-sign inside send if we took to long to get to send event<commit_after>var AWS = require('./core');
require('./sequential_executor');
require('./service_interface/json');
require('./service_interface/query');
require('./service_interface/rest');
require('./service_interface/rest_json');
require('./service_interface/rest_xml');

/**
 * The namespace used to register global event listeners for request building
 * and sending.
 */
AWS.EventListeners = {
  /**
   * @!attribute VALIDATE_CREDENTIALS
   *   A request listener that validates whether the request is being
   *   sent with credentials.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating credentials
   *     var listener = AWS.EventListeners.Core.VALIDATE_CREDENTIALS;
   *     request.removeListener('validate', listener);
   *   @readonly
   *   @return [Function]
   * @!attribute VALIDATE_REGION
   *   A request listener that validates whether the region is set
   *   for a request.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating region configuration
   *     var listener = AWS.EventListeners.Core.VALIDATE_REGION;
   *     request.removeListener('validate', listener);
   *   @readonly
   *   @return [Function]
   * @!attribute VALIDATE_PARAMETERS
   *   A request listener that validates input parameters in a request.
   *   Handles the {AWS.Request~validate 'validate' Request event}
   *   @example Sending a request without validating parameters
   *     var listener = AWS.EventListeners.Core.VALIDATE_PARAMETERS;
   *     request.removeListener('validate', listener);
   *   @example Disable parameter validation globally
   *     AWS.EventListeners.Core.removeListener('validate',
   *       AWS.EventListeners.Core.VALIDATE_REGION);
   *   @readonly
   *   @return [Function]
   * @!attribute SEND
   *   A request listener that initiates the HTTP connection for a
   *   request being sent. Handles the {AWS.Request~send 'send' Request event}
   *   @example Replacing the HTTP handler
   *     var listener = AWS.EventListeners.Core.SEND;
   *     request.removeListener('send', listener);
   *     request.on('send', function(response) {
   *       customHandler.send(response);
   *     });
   *   @return [Function]
   *   @readonly
   * @!attribute HTTP_DATA
   *   A request listener that reads data from the HTTP connection in order
   *   to build the response data.
   *   Handles the {AWS.Request~httpData 'httpData' Request event}.
   *   Remove this handler if you are overriding the 'httpData' event and
   *   do not want extra data processing and buffering overhead.
   *   @example Disabling default data processing
   *     var listener = AWS.EventListeners.Core.HTTP_DATA;
   *     request.removeListener('httpData', listener);
   *   @return [Function]
   *   @readonly
   */
  Core: {} /* doc hack */
};

AWS.EventListeners = {
  Core: new AWS.SequentialExecutor().addNamedListeners(function(add, addAsync) {
    addAsync('VALIDATE_CREDENTIALS', 'validate',
        function VALIDATE_CREDENTIALS(req, done) {
      req.service.config.getCredentials(function(err) {
        if (err) {
          req.response.err = AWS.util.error(err,
            {code: 'SigningError', message: 'Missing credentials in config'});
        }
        done();
      });
    });

    add('VALIDATE_REGION', 'validate', function VALIDATE_REGION(req) {
      if (!req.service.config.region && !req.service.hasGlobalEndpoint()) {
        req.response.error = AWS.util.error(new Error(),
          {code: 'SigningError', message: 'Missing region in config'});
      }
    });

    add('VALIDATE_PARAMETERS', 'validate', function VALIDATE_PARAMETERS(req) {
      var rules = req.service.api.operations[req.operation].input;
      new AWS.ParamValidator().validate(rules, req.params);
    });

    add('SET_CONTENT_LENGTH', 'afterBuild', function SET_CONTENT_LENGTH(req) {
      if (req.httpRequest.headers['Content-Length'] === undefined) {
        var length = AWS.util.string.byteLength(req.httpRequest.body);
        req.httpRequest.headers['Content-Length'] = length;
      }
    });

    add('SET_HTTP_HOST', 'afterBuild', function SET_HTTP_HOST(req) {
      req.httpRequest.headers['Host'] = req.httpRequest.endpoint.host;
    });

    addAsync('SIGN', 'sign', function SIGN(req, done) {
      if (!req.service.api.signatureVersion) return done(); // none

      req.service.config.getCredentials(function (err, credentials) {
        if (err) {
          req.response.error = err;
          return done();
        }

        try {
          var date = AWS.util.date.getDate();
          var SignerClass = req.service.getSignerClass(req);
          var signer = new SignerClass(req.httpRequest,
            req.service.api.signingName || req.service.api.endpointPrefix);

          // clear old authorization headers
          delete req.httpRequest.headers['Authorization'];
          delete req.httpRequest.headers['Date'];
          delete req.httpRequest.headers['X-Amz-Date'];

          // add new authorization
          signer.addAuthorization(credentials, date);
        } catch (e) {
          req.response.error = e;
        }
        done();
      });
    });

    add('VALIDATE_RESPONSE', 'validateResponse', function VALIDATE_RESPONSE(resp) {
      if (this.service.successfulResponse(resp, this)) {
        resp.data = {};
        resp.error = null;
      } else {
        resp.data = null;
        resp.error = AWS.util.error(new Error(),
          {code: 'UnknownError', message: 'An unknown error occurred.'});
      }
    });

    addAsync('SEND', 'send', function SEND(resp, done) {
      resp.httpResponse._abortCallback = done;
      resp.error = null;
      resp.data = null;

      function callback(httpResp) {
        resp.httpResponse.stream = httpResp;

        httpResp.on('headers', function onHeaders(statusCode, headers) {
          resp.request.emit('httpHeaders', [statusCode, headers, resp]);

          if (!resp.request.httpRequest._streaming) {
            if (AWS.HttpClient.streamsApiVersion === 2) { // streams2 API check
              httpResp.on('readable', function onReadable() {
                var data = httpResp.read();
                if (data !== null) {
                  resp.request.emit('httpData', [data, resp]);
                }
              });
            } else { // legacy streams API
              httpResp.on('data', function onData(data) {
                resp.request.emit('httpData', [data, resp]);
              });
            }
          }
        });

        httpResp.on('end', function onEnd() {
          resp.request.emit('httpDone');
          done();
        });
      }

      function progress(httpResp) {
        httpResp.on('sendProgress', function onSendProgress(progress) {
          resp.request.emit('httpUploadProgress', [progress, resp]);
        });

        httpResp.on('receiveProgress', function onReceiveProgress(progress) {
          resp.request.emit('httpDownloadProgress', [progress, resp]);
        });
      }

      function error(err) {
        resp.error = AWS.util.error(err, {
          code: 'NetworkingError',
          region: resp.request.httpRequest.region,
          hostname: resp.request.httpRequest.endpoint.hostname,
          retryable: true
        });
        resp.request.emit('httpError', [resp.error, resp], function() {
          done();
        });
      }

      function executeSend() {
        var http = AWS.HttpClient.getInstance();
        var httpOptions = resp.request.service.config.httpOptions || {};
        var stream = http.handleRequest(resp.request.httpRequest, httpOptions,
                                        callback, error);
        progress(stream);
      }

      var signDateHeader = this.httpRequest.headers['X-Amz-Date'];
      var signDate = AWS.util.date.parseTimestamp(signDateHeader);
      var timeDiff = (new Date() - signDate) / 1000;
      if (timeDiff >= 60 * 10) { // if we signed 10min ago, re-sign
        this.emit('sign', [this], function(err) {
          if (err) done(err);
          else executeSend();
        });
      } else {
        executeSend();
      }
    });

    add('HTTP_HEADERS', 'httpHeaders',
        function HTTP_HEADERS(statusCode, headers, resp) {
      resp.httpResponse.statusCode = statusCode;
      resp.httpResponse.headers = headers;
      resp.httpResponse.body = new AWS.util.Buffer('');
      resp.httpResponse.buffers = [];
      resp.httpResponse.numBytes = 0;
    });

    add('HTTP_DATA', 'httpData', function HTTP_DATA(chunk, resp) {
      if (chunk) {
        if (AWS.util.isNode()) {
          resp.httpResponse.numBytes += chunk.length;

          var total = resp.httpResponse.headers['content-length'];
          var progress = { loaded: resp.httpResponse.numBytes, total: total };
          resp.request.emit('httpDownloadProgress', [progress, resp]);
        }

        resp.httpResponse.buffers.push(new AWS.util.Buffer(chunk));
      }
    });

    add('HTTP_DONE', 'httpDone', function HTTP_DONE(resp) {
      // convert buffers array into single buffer
      if (resp.httpResponse.buffers && resp.httpResponse.buffers.length > 0) {
        var body = AWS.util.buffer.concat(resp.httpResponse.buffers);
        resp.httpResponse.body = body;
      }
      delete resp.httpResponse.numBytes;
      delete resp.httpResponse.buffers;
    });

    add('FINALIZE_ERROR', 'retry', function FINALIZE_ERROR(resp) {
      if (resp.httpResponse.statusCode) {
        resp.error.statusCode = resp.httpResponse.statusCode;
        if (resp.error.retryable === undefined) {
          resp.error.retryable = this.service.retryableError(resp.error, this);
        }
      }
    });

    add('INVALIDATE_CREDENTIALS', 'retry', function INVALIDATE_CREDENTIALS(resp) {
      switch (resp.error.code) {
        case 'RequestExpired': // EC2 only
        case 'ExpiredTokenException':
        case 'ExpiredToken':
          resp.error.retryable = true;
          resp.request.service.config.credentials.expired = true;
      }
    });

    add('REDIRECT', 'retry', function REDIRECT(resp) {
      if (resp.error && resp.error.statusCode >= 300 &&
          resp.error.statusCode < 400 && resp.httpResponse.headers['location']) {
        this.httpRequest.endpoint =
          new AWS.Endpoint(resp.httpResponse.headers['location']);
        resp.error.redirect = true;
        resp.error.retryable = true;
      }
    });

    add('RETRY_CHECK', 'retry', function RETRY_CHECK(resp) {
      if (resp.error) {
        if (resp.error.redirect && resp.redirectCount < resp.maxRedirects) {
          resp.error.retryDelay = 0;
          resp.redirectCount++;
          resp.error._willRetry = true;
        } else if (resp.error.retryable && resp.retryCount < resp.maxRetries) {
          var delays = this.service.retryDelays();
          resp.error.retryDelay = delays[resp.retryCount] || 0;
          resp.retryCount++;
          resp.error._willRetry = true;
        } else {
          resp.error._willRetry = false;
        }
      }
    });

    addAsync('RESET_RETRY_STATE', 'afterRetry', function RESET_RETRY_STATE(resp, done) {
      if (resp.error && resp.error._willRetry) {
        var delay = resp.error.retryDelay || 0;
        resp.error = null;
        setTimeout(done, delay);
      } else {
        done();
      }
    });

  }),

  CorePost: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    add('EXTRACT_REQUEST_ID', 'extractData', function EXTRACT_REQUEST_ID(resp) {
      resp.requestId = resp.httpResponse.headers['x-amz-request-id'] ||
                       resp.httpResponse.headers['x-amzn-requestid'];
    });
  }),

  Logger: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    add('LOG_REQUEST', 'complete', function LOG_REQUEST(resp) {
      var req = resp.request;
      var logger = req.service.config.logger;
      if (!logger) return;

      function buildMessage() {
        var time = AWS.util.date.getDate().getTime();
        var delta = (time - req.startTime.getTime()) / 1000;
        var ansi = logger.isTTY ? true : false;
        var status = resp.httpResponse.statusCode;
        var params = require('util').inspect(req.params, true, true);

        var message = '';
        if (ansi) message += '\x1B[33m';
        message += '[AWS ' + req.service.serviceIdentifier + ' ' + status;
        message += ' ' + delta.toString() + 's ' + resp.retryCount + ' retries]';
        if (ansi) message += '\x1B[0;1m';
        message += ' ' + req.operation + '(' + params + ')';
        if (ansi) message += '\x1B[0m';
        return message;
      }

      var line = buildMessage();
      if (typeof logger.log === 'function') {
        logger.log(line);
      } else if (typeof logger.write === 'function') {
        logger.write(line + '\n');
      }
    });
  }),

  Json: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Json;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  Rest: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Rest;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  RestJson: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.RestJson;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  RestXml: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.RestXml;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  }),

  Query: new AWS.SequentialExecutor().addNamedListeners(function(add) {
    var svc = AWS.ServiceInterface.Query;
    add('BUILD', 'build', svc.buildRequest);
    add('EXTRACT_DATA', 'extractData', svc.extractData);
    add('EXTRACT_ERROR', 'extractError', svc.extractError);
  })
};
<|endoftext|>


<commit_before>'use strict';

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

module.exports = function(existing, app) {
  existing = utils.arrayify(existing);

  return {
    type: ['array'],
    normalize: function(val, key, config, schema) {
      if (!val) return;

      if (typeof val === 'string') {
        val = val.split(',');
      }

      if (utils.isObject(val)) {
        for (var prop in val) {
          var value = val[prop];
          if (typeof value === 'boolean') {
            val = [prop];
          }
        }
      }

      if (Array.isArray(val)) {
        val = utils.union([], existing, val);
        if (val.length) {
          return val;
        }
      }
      return null;
    }
  };
};
<commit_msg>update value on `config` in case the reference is broken<commit_after>'use strict';

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

module.exports = function(existing, app) {
  existing = utils.arrayify(existing);

  return {
    type: ['array'],
    normalize: function(val, key, config, schema) {
      if (!val) return;

      if (typeof val === 'string') {
        val = val.split(',');
      }

      if (utils.isObject(val)) {
        for (var prop in val) {
          var value = val[prop];
          if (typeof value === 'boolean') {
            val = [prop];
          }
        }
      }

      if (Array.isArray(val)) {
        val = utils.union([], existing, val);
        if (val.length) {
          config[key] = val;
          return val;
        }
      }
      return null;
    }
  };
};
<|endoftext|>


<commit_before>const run = require('./utils/run-cli-cmd.js')
const fs = require('fs')
const UglifyJS = require('uglify-js')
const packageInfo = require('../../package.json')
const preamble = require('../build/preamble.js')

const version = packageInfo.version
const distName = `base-query-${version}`
const deployTargetDir = `code.archilogic.com`

run([

  // build
  `npm run build`,
  // empty distribution folder
  'rm -f dist/*',
  // copy build files to distribution folder
  `cp build/base-query.js dist/${distName}.js`,
  `cp build/base-query.js.map dist/${distName}.js.map`,
  // uglify
  () => {
    const code = fs.readFileSync(`dist/${distName}.js`, `utf8`)
    const map  = fs.readFileSync(`dist/${distName}.js.map`, `utf8`)
    const ugly = UglifyJS.minify(code, {
      warnings: true,
      mangle: true,
      ie8: false,
      compress: { dead_code: true, toplevel: true, passes: 3 },
      output: { preamble: preamble, beautify: false },
      sourceMap: { content: map, url: `${distName}.min.js.map` }
    })
    if (ugly.warnings) console.log('UGLIFY WARNINGS: ', ugly.warnings)
    if (ugly.error) return Promise.reject(ugly.error)
    fs.writeFileSync(`dist/${distName}.min.js`, ugly.code)
    fs.writeFileSync(`dist/${distName}.min.js.map`, ugly.map)
  },
  // gzip uglified files
  `gzip -9 dist/${distName}.min.js dist/${distName}.min.js.map`,
  // remove .gz extension
  `mv dist/${distName}.min.js.gz dist/${distName}.min.js`,
  `mv dist/${distName}.min.js.map.gz dist/${distName}.min.js.map`,
  // deploy to S3
  `aws s3 cp ./dist/${distName}.js s3://${deployTargetDir}/${distName}.js`,
  `aws s3 cp ./dist/${distName}.js.map s3://${deployTargetDir}/${distName}.js.map`,
  `aws s3 cp --content-encoding=gzip ./dist/${distName}.min.js s3://${deployTargetDir}/${distName}.min.js`,
  `aws s3 cp --content-encoding=gzip ./dist/${distName}.min.js.map s3://${deployTargetDir}/${distName}.min.js.map`

]).catch((err) => {
  console.error(err)
})<commit_msg>refactors code for readability<commit_after>const run = require('./utils/run-cli-cmd.js')
const fs = require('fs')
const UglifyJS = require('uglify-js')
const packageInfo = require('../../package.json')
const preamble = require('../build/preamble.js')

// TODO: replace custom task runner with GULP 4

// configs
const distName = `base-query-${packageInfo.version}`
const deployTargetDir = `code.archilogic.com`

run([
  // build
  `npm run build`,
  // empty distribution folder
  //'rm -f dist/*',
  // copy build files to distribution folder
  `cp build/base-query.js dist/${distName}.js`,
  `cp build/base-query.js.map dist/${distName}.js.map`,
  // uglify
  () => {
    const ugly = UglifyJS.minify(read(`dist/${distName}.js`), {
      warnings: true, mangle: true, ie8: false,
      compress: {dead_code: true, toplevel: true, passes: 3},
      output: {preamble: preamble, beautify: false},
      sourceMap: {content: read(`dist/${distName}.js.map`), url: `${distName}.min.js.map`}
    })
    if (ugly.warnings) console.log('UGLIFY WARNINGS: ', ugly.warnings)
    if (ugly.error) return Promise.reject(ugly.error)
    fs.writeFileSync(`dist/${distName}.min.js`, ugly.code)
    fs.writeFileSync(`dist/${distName}.min.js.map`, ugly.map)
  }
  // gzip uglified files
  `gzip -9 dist/${distName}.min.js dist/${distName}.min.js.map`,
  // remove .gz extension
  `mv dist/${distName}.min.js.gz dist/${distName}.min.js`,
  `mv dist/${distName}.min.js.map.gz dist/${distName}.min.js.map`,
  // deploy to S3
  `aws s3 cp ./dist/${distName}.js s3://${deployTargetDir}/${distName}.js`,
  `aws s3 cp ./dist/${distName}.js.map s3://${deployTargetDir}/${distName}.js.map`,
  `aws s3 cp --content-encoding=gzip ./dist/${distName}.min.js s3://${deployTargetDir}/${distName}.min.js`,
  `aws s3 cp --content-encoding=gzip ./dist/${distName}.min.js.map s3://${deployTargetDir}/${distName}.min.js.map`
]).catch(console.error)

// helpers

function read (path) {
  return fs.readFileSync(path, `utf8`)
}<|endoftext|>


<commit_before>/*
 * monitor.js: Core functionality for the Monitor object.
 *
 * (C) 2010 Charlie Robbins
 * MIT LICENCE
 *
 */

var util = require('util'),
    fs = require('fs'),
    path = require('path'),
    events = require('events'),
    spawn = require('child_process').spawn,
    winston = require('winston'),
    forever = require('../forever');

//
// ### function Monitor (script, options)
// #### @script {string} Location of the target script to run.
// #### @options {Object} Configuration for this instance.
// Creates a new instance of forever with specified params.
//
var Monitor = exports.Monitor = function (script, options) {
  var self = this;
  events.EventEmitter.call(this);

  //
  // Setup basic configuration options
  //
  options          = options || {};
  this.silent      = options.silent || false;
  this.forever     = options.forever || false;
  this.uid         = options.uid || forever.randomString(24);
  this.pidFile     = options.pidFile || path.join(forever.config.get('pidPath'), this.uid + '.pid');
  this.max         = options.max;
  this.childExists = false;
  this.times       = 0;

  //
  // Setup restart timing. These options control how quickly forever restarts
  // a child process as well as when to kill a "spinning" process
  //
  this.minUptime     = typeof options.minUptime !== 'number' ? 0 : options.minUptime;
  this.spinSleepTime = options.spinSleepTime || null;

  //
  // Setup the command to spawn and the options to pass
  // to that command.
  //
  this.command   = options.command || 'node';
  this.options   = options.options || [];
  this.spawnWith = options.spawnWith || {};
  this.sourceDir = options.sourceDir;
  this.cwd       = options.cwd || null;
  this.env       = options.env || {};
  this.hideEnv   = options.hideEnv || [];
  this._hideEnv  = {};

  //
  // Create a simple mapping of `this.hideEnv` to an easily indexable
  // object
  //
  this.hideEnv.forEach(function (key) {
    self._hideEnv[key] = true;
  });

  //
  // Setup log files and logger for this instance.
  //
  this.logFile = options.logFile || path.join(forever.config.get('root'), this.uid + '.log');
  this.outFile = options.outFile;
  this.errFile = options.errFile;
  this.logger  = options.logger || new (winston.Logger)({
    transports: [new winston.transports.Console({ silent: this.silent })]
  });

  //
  // Extend from the winston logger.
  //
  this.logger.extend(this);

  if (Array.isArray(script)) {
    this.command = script[0];
    this.options = script.slice(1);
  }
  else {
    this.options.unshift(script);
  }

  if (this.sourceDir) {
    this.options[0] = path.join(this.sourceDir, this.options[0]);
  }

  // If we should log stdout, open a file buffer
  if (this.outFile) {
    this.stdout = fs.createWriteStream(this.outFile, { flags: 'a+', encoding: 'utf8', mode: 0666 });
  }

  // If we should log stderr, open a file buffer
  if (this.errFile) {
    this.stderr = fs.createWriteStream(this.errFile, { flags: 'a+', encoding: 'utf8', mode: 0666 });
  }

  //
  // Last if any hooks have been passed in attach
  // this instance to them
  //
  if (options.hooks && options.hooks.length > 0) {
    options.hooks.forEach(function (hook) {
      if (typeof hook === 'function') {
        return hook(self);
      }

      hook.attach(self);
    });
  }
};

// Inherit from events.EventEmitter
util.inherits(Monitor, events.EventEmitter);

//
// ### function start ([restart])
// #### @restart {boolean} Value indicating whether this is a restart.
// Start the process that this instance is configured for
//
Monitor.prototype.start = function (restart) {
  var self = this;

  if (this.running && !restart) {
    process.nextTick(function () {
      self.emit('error', new Error('Cannot start process that is already running.'));
    });
  }

  var child = this.trySpawn();
  if (!child) {
    process.nextTick(function () {
      self.emit('error', new Error('Target script does not exist: ' + self.options[0]));
    });
    return this;
  }

  this.ctime = Date.now();
  this.child = child;
  this.running = true;

  process.nextTick(function () {
    self.emit(restart ? 'restart' : 'start', self, self.data);
  });

  // Hook all stream data and process it
  function listenTo (stream) {
    function ldata (data) {
      if (!self.silent && !self[stream]) {
        //
        // If we haven't been silenced, and we don't have a file stream
        // to output to write to the process stdout stream
        //
        process.stdout.write(data);
      }
      else if (self[stream]) {
        //
        // If we have been given an output file for the stream, write to it
        //
        self[stream].write(data);
      }

      self.emit(stream, data);
    }

    child[stream].on('data', ldata);

    child.on('exit', function () {
      child[stream].removeListener('data', ldata);
    });
  }

  // Listen to stdout and stderr
  listenTo('stdout');
  listenTo('stderr');

  child.on('exit', function (code) {
    var spinning = Date.now() - self.ctime < self.minUptime;
    self.warn('Forever detected script exited with code: ' + code);

    function letChildDie() {
      self.running = false;
      self.forceStop = false;

      //
      // If had to write to an stdout file, close it
      //
      if (self.stdout) {
        self.stdout.end();
      }

      //
      // If had to write to an stderr file, close it
      //
      if (self.stderr) {
        self.stderr.end();
      }

      self.emit('exit', self, spinning);
    }

    function restartChild() {
      self.forceRestart = false;
      process.nextTick(function () {
        self.warn('Forever restarting script for ' + self.times + ' time');
        self.start(true);
      });
    }

    self.times++;

    if (self.forceStop || (!self.forever && self.times >= self.max)
      || (spinning && typeof self.spinSleepTime !== 'number') && !self.forceRestart) {
      letChildDie();
    }
    else if (spinning) {
      setTimeout(restartChild, self.spinSleepTime);
    }
    else {
      restartChild();
    }
  });

  return this;
};

//
// ### function trySpawn()
// Tries to spawn the target Forever child process. Depending on
// configuration, it checks the first argument of the options
// to see if the file exists. This is useful is you are
// trying to execute a script with an env: e.g. node myfile.js
//
Monitor.prototype.trySpawn = function () {
  if (this.command === 'node' || (this.checkFile && !this.childExists)) {
    try {
      var stats = fs.statSync(this.options[0]);
      this.childExists = true;
    }
    catch (ex) {
      return false;
    }
  }

  this.spawnWith.cwd = this.cwd || this.spawnWith.cwd;
  this.spawnWith.env = this._getEnv();

  return spawn(this.command, this.options, this.spawnWith);
};

//
// ### @data {Object}
// Responds with the appropriate information about
// this `Monitor` instance and it's associated child process.
//
Monitor.prototype.__defineGetter__('data', function () {
  var self = this;

  if (!this.running) {
    //
    // TODO: Return settings from this forever instance
    // with a state indicator that it is currently stopped.
    //
    return {};
  }

  var childData = {
    ctime: this.ctime,
    command: this.command,
    file: this.options[0],
    foreverPid: process.pid,
    logFile: this.logFile,
    options: this.options.slice(1),
    pid: this.child.pid,
    silent: this.silent,
    uid: this.uid
  };

  ['pidFile', 'outFile', 'errFile', 'env', 'cwd'].forEach(function (key) {
    if (self[key]) {
      childData[key] = self[key];
    }
  });

  if (this.sourceDir) {
    childData.sourceDir = this.sourceDir;
    childData.file = childData.file.replace(this.sourceDir + '/', '');
  }

  this.childData = childData;
  return this.childData;

  //
  // Setup the forever process to listen to
  // SIGINT and SIGTERM events so that we can
  // clean up the *.pid file
  //
  // Remark: This should work, but the fd gets screwed up
  //         with the daemon process.
  //
  // process.on('SIGINT', function () {
  //   process.exit(0);
  // });
  //
  // process.on('SIGTERM', function () {
  //   process.exit(0);
  // });
  // process.on('exit', function () {
  //   fs.unlinkSync(childPath);
  // });
});

//
// ### function restart ()
// Restarts the target script associated with this instance.
//
Monitor.prototype.restart = function () {
  this.forceRestart = true;
  return this.kill(false);
};

//
// ### function stop ()
// Stops the target script associated with this instance. Prevents it from auto-respawning
//
Monitor.prototype.stop = function () {
  return this.kill(true);
};

//
// ### function kill (forceStop)
// #### @forceStop {boolean} Value indicating whether short circuit forever auto-restart.
// Kills the ChildProcess object associated with this instance.
//
Monitor.prototype.kill = function (forceStop) {
  var self = this;

  if (!this.child || !this.running) {
    process.nextTick(function () {
      self.emit('error', new Error('Cannot stop process that is not running.'));
    });
  }
  else {
    //
    // Set an instance variable here to indicate this
    // stoppage is forced so that when `child.on('exit', ..)`
    // fires in `Monitor.prototype.start` we can short circuit
    // and prevent auto-restart
    //
    if (forceStop) {
      this.forceStop = true;
    }

    this.child.kill();
    this.emit('stop', this.childData);
  }

  return this;
};

//
// ### @private function _getEnv ()
// Returns the environment variables that should be passed along
// to the target process spawned by this instance.
//
Monitor.prototype._getEnv = function () {
  var self = this,
      merged = {};

  function addKey (key, source) {
    merged[key] = source[key];
  }

  //
  // Mixin the key:value pairs from `process.env` and the custom
  // environment variables in `this.env`.
  //
  Object.keys(process.env).forEach(function (key) {
    if (!self._hideEnv[key]) {
      addKey(key, process.env);
    }
  });

  Object.keys(this.env).forEach(function (key) {
    addKey(key, self.env);
  });

  return merged;
};
<commit_msg>[api] simplest possible file watcher (ref #41)<commit_after>/*
 * monitor.js: Core functionality for the Monitor object.
 *
 * (C) 2010 Charlie Robbins
 * MIT LICENCE
 *
 */

var util = require('util'),
    fs = require('fs'),
    path = require('path'),
    events = require('events'),
    spawn = require('child_process').spawn,
    winston = require('winston'),
    watch = require('watch'),
    forever = require('../forever');

//
// ### function Monitor (script, options)
// #### @script {string} Location of the target script to run.
// #### @options {Object} Configuration for this instance.
// Creates a new instance of forever with specified params.
//
var Monitor = exports.Monitor = function (script, options) {
  var self = this;
  events.EventEmitter.call(this);

  //
  // Setup basic configuration options
  //
  options          = options || {};
  this.silent      = options.silent || false;
  this.forever     = options.forever || false;
  this.uid         = options.uid || forever.randomString(24);
  this.pidFile     = options.pidFile || path.join(forever.config.get('pidPath'), this.uid + '.pid');
  this.max         = options.max;
  this.childExists = false;
  this.times       = 0;

  //
  // Setup restart timing. These options control how quickly forever restarts
  // a child process as well as when to kill a "spinning" process
  //
  this.minUptime     = typeof options.minUptime !== 'number' ? 0 : options.minUptime;
  this.spinSleepTime = options.spinSleepTime || null;

  //
  // Setup the command to spawn and the options to pass
  // to that command.
  //
  this.command   = options.command || 'node';
  this.options   = options.options || [];
  this.spawnWith = options.spawnWith || {};
  this.sourceDir = options.sourceDir;
  this.cwd       = options.cwd || null;
  this.env       = options.env || {};
  this.hideEnv   = options.hideEnv || [];
  this._hideEnv  = {};

  //
  // Create a simple mapping of `this.hideEnv` to an easily indexable
  // object
  //
  this.hideEnv.forEach(function (key) {
    self._hideEnv[key] = true;
  });

  //
  // Setup log files and logger for this instance.
  //
  this.logFile = options.logFile || path.join(forever.config.get('root'), this.uid + '.log');
  this.outFile = options.outFile;
  this.errFile = options.errFile;
  this.logger  = options.logger || new (winston.Logger)({
    transports: [new winston.transports.Console({ silent: this.silent })]
  });

  //
  // Extend from the winston logger.
  //
  this.logger.extend(this);

  if (Array.isArray(script)) {
    this.command = script[0];
    this.options = script.slice(1);
  }
  else {
    this.options.unshift(script);
  }

  if (this.sourceDir) {
    this.options[0] = path.join(this.sourceDir, this.options[0]);
  }

  // If we should log stdout, open a file buffer
  if (this.outFile) {
    this.stdout = fs.createWriteStream(this.outFile, { flags: 'a+', encoding: 'utf8', mode: 0666 });
  }

  // If we should log stderr, open a file buffer
  if (this.errFile) {
    this.stderr = fs.createWriteStream(this.errFile, { flags: 'a+', encoding: 'utf8', mode: 0666 });
  }

  //
  // Last if any hooks have been passed in attach
  // this instance to them
  //
  if (options.hooks && options.hooks.length > 0) {
    options.hooks.forEach(function (hook) {
      if (typeof hook === 'function') {
        return hook(self);
      }

      hook.attach(self);
    });
  }
};

// Inherit from events.EventEmitter
util.inherits(Monitor, events.EventEmitter);

//
// ### function start ([restart])
// #### @restart {boolean} Value indicating whether this is a restart.
// Start the process that this instance is configured for
//
Monitor.prototype.start = function (restart) {
  var self = this;

  if (this.running && !restart) {
    process.nextTick(function () {
      self.emit('error', new Error('Cannot start process that is already running.'));
    });
  }

  var child = this.trySpawn();
  if (!child) {
    process.nextTick(function () {
      self.emit('error', new Error('Target script does not exist: ' + self.options[0]));
    });
    return this;
  }

  this.ctime = Date.now();
  this.child = child;
  this.running = true;

  process.nextTick(function () {
    self.emit(restart ? 'restart' : 'start', self, self.data);
  });

  // Hook all stream data and process it
  function listenTo (stream) {
    function ldata (data) {
      if (!self.silent && !self[stream]) {
        //
        // If we haven't been silenced, and we don't have a file stream
        // to output to write to the process stdout stream
        //
        process.stdout.write(data);
      }
      else if (self[stream]) {
        //
        // If we have been given an output file for the stream, write to it
        //
        self[stream].write(data);
      }

      self.emit(stream, data);
    }

    child[stream].on('data', ldata);

    child.on('exit', function () {
      child[stream].removeListener('data', ldata);
    });
  }

  // Listen to stdout and stderr
  listenTo('stdout');
  listenTo('stderr');

  child.on('exit', function (code) {
    var spinning = Date.now() - self.ctime < self.minUptime;
    self.warn('Forever detected script exited with code: ' + code);

    function letChildDie() {
      self.running = false;
      self.forceStop = false;

      //
      // If had to write to an stdout file, close it
      //
      if (self.stdout) {
        self.stdout.end();
      }

      //
      // If had to write to an stderr file, close it
      //
      if (self.stderr) {
        self.stderr.end();
      }

      self.emit('exit', self, spinning);
    }

    function restartChild() {
      self.forceRestart = false;
      process.nextTick(function () {
        self.warn('Forever restarting script for ' + self.times + ' time');
        self.start(true);
      });
    }

    self.times++;

    if (self.forceStop || (!self.forever && self.times >= self.max)
      || (spinning && typeof self.spinSleepTime !== 'number') && !self.forceRestart) {
      letChildDie();
    }
    else if (spinning) {
      setTimeout(restartChild, self.spinSleepTime);
    }
    else {
      restartChild();
    }
  });

  return this;
};

//
// ### function trySpawn()
// Tries to spawn the target Forever child process. Depending on
// configuration, it checks the first argument of the options
// to see if the file exists. This is useful is you are
// trying to execute a script with an env: e.g. node myfile.js
//
Monitor.prototype.trySpawn = function () {
  if (this.command === 'node' || (this.checkFile && !this.childExists)) {
    try {
      var stats = fs.statSync(this.options[0]);
      this.childExists = true;
    }
    catch (ex) {
      return false;
    }
  }

  this.spawnWith.cwd = this.cwd || this.spawnWith.cwd;
  this.spawnWith.env = this._getEnv();

  return spawn(this.command, this.options, this.spawnWith);
};

//
// ### @data {Object}
// Responds with the appropriate information about
// this `Monitor` instance and it's associated child process.
//
Monitor.prototype.__defineGetter__('data', function () {
  var self = this;

  if (!this.running) {
    //
    // TODO: Return settings from this forever instance
    // with a state indicator that it is currently stopped.
    //
    return {};
  }

  var childData = {
    ctime: this.ctime,
    command: this.command,
    file: this.options[0],
    foreverPid: process.pid,
    logFile: this.logFile,
    options: this.options.slice(1),
    pid: this.child.pid,
    silent: this.silent,
    uid: this.uid
  };

  ['pidFile', 'outFile', 'errFile', 'env', 'cwd'].forEach(function (key) {
    if (self[key]) {
      childData[key] = self[key];
    }
  });

  if (this.sourceDir) {
    childData.sourceDir = this.sourceDir;
    childData.file = childData.file.replace(this.sourceDir + '/', '');
  }

  this.childData = childData;
  return this.childData;

  //
  // Setup the forever process to listen to
  // SIGINT and SIGTERM events so that we can
  // clean up the *.pid file
  //
  // Remark: This should work, but the fd gets screwed up
  //         with the daemon process.
  //
  // process.on('SIGINT', function () {
  //   process.exit(0);
  // });
  //
  // process.on('SIGTERM', function () {
  //   process.exit(0);
  // });
  // process.on('exit', function () {
  //   fs.unlinkSync(childPath);
  // });
});

//
// ### function restart ()
// Restarts the target script associated with this instance.
//
Monitor.prototype.restart = function () {
  this.forceRestart = true;
  return this.kill(false);
};

//
// ### function stop ()
// Stops the target script associated with this instance. Prevents it from auto-respawning
//
Monitor.prototype.stop = function () {
  return this.kill(true);
};

//
// ### function kill (forceStop)
// #### @forceStop {boolean} Value indicating whether short circuit forever auto-restart.
// Kills the ChildProcess object associated with this instance.
//
Monitor.prototype.kill = function (forceStop) {
  var self = this;

  if (!this.child || !this.running) {
    process.nextTick(function () {
      self.emit('error', new Error('Cannot stop process that is not running.'));
    });
  }
  else {
    //
    // Set an instance variable here to indicate this
    // stoppage is forced so that when `child.on('exit', ..)`
    // fires in `Monitor.prototype.start` we can short circuit
    // and prevent auto-restart
    //
    if (forceStop) {
      this.forceStop = true;
    }

    this.child.kill();
    this.emit('stop', this.childData);
  }

  return this;
};

//
// ### function watch ()
// Starts watching directory tree for changes.
//
Monitor.prototype.watch = function () {
  var self = this;

  watch.createMonitor(process.cwd(), {ignoreDotFiles: true}, function (monitor) {
    monitor.on('changed', function (f, curr, prev) {
      self.info('restaring script because ' + f + ' changed');
      self.restart();
    });
  });
}

//
// ### @private function _getEnv ()
// Returns the environment variables that should be passed along
// to the target process spawned by this instance.
//
Monitor.prototype._getEnv = function () {
  var self = this,
      merged = {};

  function addKey (key, source) {
    merged[key] = source[key];
  }

  //
  // Mixin the key:value pairs from `process.env` and the custom
  // environment variables in `this.env`.
  //
  Object.keys(process.env).forEach(function (key) {
    if (!self._hideEnv[key]) {
      addKey(key, process.env);
    }
  });

  Object.keys(this.env).forEach(function (key) {
    addKey(key, self.env);
  });

  return merged;
};
<|endoftext|>


<commit_before>const request = require('request-promise');
const firebase = require('firebase');

const constants = require('../constants.js');
const pjson = require('../../package.json');

const firebaseJs = require('./firebase.js');

/**
 * Log error
 *
 * @param {Object} err - The error to log.
 * @param {google.auth.OAuth2} auth - An authorized OAuth2 client.
 * @returns {void}
 */
async function log(err, auth) {
    if (err.print) {
        console.log(err.message);
    }

    try {
        err = JSON.parse(JSON.stringify(err, Reflect.ownKeys(err)));
    } catch (error) {
        err = err;
    }

    let userId = 'unknown';
    try {
        await firebaseJs.authWithFirebase(auth);
        userId = firebase.auth().currentUser.uid;
    } catch (error) {}

    try {
        let version = 'unkown';
        if (pjson.version) {
            version = pjson.version;
        }

        const requestData = {
            userId,
            version,
            err,
            timestamp: {
                ".sv": "timestamp",
            },
        };

        const result = await request({
            url: `${constants.FIREBASE_DATABASE_URL}/logs/errors/${version}/${userId}.json`,
            method: "POST",
            json: true,
            headers: {
                "content-type": "application/json",
            },
            body: requestData,
        });
        // console.log(`Error logged: ${result.name}`);
    } catch (error) {}
    return;
}

module.exports = {
    log,
};
<commit_msg>fix firebase logging<commit_after>const request = require('request-promise');
const firebase = require('firebase');

const constants = require('../constants.js');
const pjson = require('../../package.json');

const firebaseJs = require('./firebase.js');

/**
 * Log error
 *
 * @param {Object} err - The error to log.
 * @param {google.auth.OAuth2} auth - An authorized OAuth2 client.
 * @returns {void}
 */
async function log(err, auth) {
    if (err.print) {
        console.log(err.message);
    }

    try {
        err = JSON.parse(JSON.stringify(err, Reflect.ownKeys(err)));
    } catch (error) {
        err = err;
    }

    let userId = 'unknown';
    try {
        await firebaseJs.authWithFirebase(auth);
        userId = firebase.auth().currentUser.uid;
    } catch (error) {}

    try {
        let version = 'unkown';
        if (pjson.version) {
            version = pjson.version.replace(/\./g, '_');
        }

        const requestData = {
            userId,
            version,
            err,
            timestamp: {
                ".sv": "timestamp",
            },
        };

        const result = await request({
            url: `${constants.FIREBASE_DATABASE_URL}/logs/errors/${version}/${userId}.json`,
            method: "POST",
            json: true,
            headers: {
                "content-type": "application/json",
            },
            body: requestData,
        });
        // console.log(`Error logged: ${result.name}`);
    } catch (error) {}
    return;
}

module.exports = {
    log,
};
<|endoftext|>


<commit_before>$.extend(Landmarks, {

  has_op: function(lm_id) {
    return Landmarks.ops(lm_id).length > 0;
  },

  // Returns the most recent op at the specified landmark.
  op: function(lm_id) {
    var ops = Landmarks.ops(lm_id);
    return ops.length > 0 && ops[ops.length - 1];
  },

  ops: function(lm_id) {
    if (!lm_id || lm_id.resource_type() != 'Landmark') return [];
    return Ops.here().grep(function(x){
      return x.site == lm_id;
    });
  },

  radius_options: function(with_any_sys, with_only_sys) {
    if (!with_any_sys && !with_only_sys) with_any_sys = App.current_stream_systems().replace('e', '');
    // [label, meters]
    var options = [ ["1 block", 200],
      ["3 blocks", 600],
      ["1/2 mile", 800],
      ["1 mile", 1600],
      ["2 miles", 3200],
      ["5 miles", 8000],
      ["10 miles", 16000]

    ].map(function(x){
      var agents = Agents.nearby(
        This._item ? This._item.lat : This.click_latlng.lat(),
        This._item ? This._item.lng : This.click_latlng.lng(), x[1]);
      if (with_any_sys || with_only_sys) {
        agents = agents.grep(function(agent){
          if (with_any_sys && with_any_sys.split('').intersect(agent.via_sys).length < 1) return false;
          if (with_only_sys) {
            var n = with_only_sys.split('').intersect(agent.via_sys).length;
            if (n != with_only_sys.length || n != agent.via_sys.length) return false;
          }
          return true;
        });
      }
      if (agents.length == 0) return '';

      var option_label = x[0] + " — " + agents.length + " agents";
      var agent_tags = agents.map('.id').join(' ');
      return "<option value='"+agent_tags+"'>" + option_label + "</option>";
    });

    options.push("<option value='require_selection'>all selected agents</option>");

    return options.join('');
  }
});

Landmark = {
  create: function(lat, lng, title) {
    var lmtag = "l" + StreamLoader.uuid();
    return item(This.city_id, lmtag, title, null, lat, lng, "", "unlatched");
  }
};
<commit_msg>fix bug with radial invite<commit_after>$.extend(Landmarks, {

  has_op: function(lm_id) {
    return Landmarks.ops(lm_id).length > 0;
  },

  // Returns the most recent op at the specified landmark.
  op: function(lm_id) {
    var ops = Landmarks.ops(lm_id);
    return ops.length > 0 && ops[ops.length - 1];
  },

  ops: function(lm_id) {
    if (!lm_id || lm_id.resource_type() != 'Landmark') return [];
    return Ops.here().grep(function(x){
      return x.site == lm_id;
    });
  },

  radius_options: function(with_any_sys, with_only_sys) {
    // if (!with_any_sys && !with_only_sys) with_any_sys = 'mt';
    // if (!with_any_sys && !with_only_sys) with_any_sys = 'App.current_stream_systems().replace('e', '');

    // [label, meters]
    var options = [ ["1 block", 200],
      ["3 blocks", 600],
      ["1/2 mile", 800],
      ["1 mile", 1600],
      ["2 miles", 3200],
      ["5 miles", 8000],
      ["10 miles", 16000]

    ].map(function(x){
      var agents = Agents.nearby(
        This._item ? This._item.lat : This.click_latlng.lat(),
        This._item ? This._item.lng : This.click_latlng.lng(), x[1]);
      if (with_any_sys || with_only_sys) {
        agents = agents.grep(function(agent){
          if (with_any_sys && with_any_sys.split('').intersect(agent.via_sys).length < 1) return false;
          if (with_only_sys) {
            var n = with_only_sys.split('').intersect(agent.via_sys).length;
            if (n != with_only_sys.length || n != agent.via_sys.length) return false;
          }
          return true;
        });
      }
      if (agents.length == 0) return '';

      var option_label = x[0] + " — " + agents.length + " agents";
      var agent_tags = agents.map('.id').join(' ');
      return "<option value='"+agent_tags+"'>" + option_label + "</option>";
    });

    options.push("<option value='require_selection'>all selected agents</option>");

    return options.join('');
  }
});

Landmark = {
  create: function(lat, lng, title) {
    var lmtag = "l" + StreamLoader.uuid();
    return item(This.city_id, lmtag, title, null, lat, lng, "", "unlatched");
  }
};
<|endoftext|>


<commit_before>'use strict';

module.exports = (bot, config) => {
    if (typeof config.data.permissions === 'undefined') {
        config.data.permissions = {};
    }
    const users = config.data.permissions;
    const getUser = (name) => {
        name = name.toLowerCase();
        let result = users[name];
        if (typeof result === 'undefined') {
            result = {admin: false, channels: []};
            users[name] = result;
        }
        return result;
    };
    const saveConfig = () => {
        for (const name in users) {
            const user = users[name];
            if (!user.admin && user.channels.length === 0) {
                delete users[name];
            }
        }
        return config.save();
    };

    for (const name in users) {
        const user = users[name];
        if (typeof user.admin !== 'boolean') {
            user.admin = false;
        }
        if (!Array.isArray(user.channels)) {
            user.channels = [];
        }
    }

    return {
        isAdmin: (name) => {
            return getUser(name).admin;
        },
        isOperator: (name, channel) => {
            return getUser(name).channels.indexOf(channel.toLowerCase()) > -1;
        },
        setAdmin: (name, value) => {
            const user = getUser(name);
            user.admin = !!value;
            return saveConfig();
        },
        setOperator: (name, channel, value) => {
            const user = getUser(name);
            const index = user.channels.indexOf(channel.toLowerCase());
            if (value && index === -1) {
                user.channels.push(channel.toLowerCase());
                return saveConfig();
            } else if (!value && index > -1) {
                user.channels.splice(index, 1);
                return saveConfig();
            }
        },
        getAdmins: () => {
            return new Promise((resolve, reject) => {
                const admins = [];
                for (let user in users) {
                    if (users[user].admin) {
                        admins.push(user)
                    }
                }
                resolve(admins);
            });
        },
        getOperators: (channel) => {
            return new Promise((resolve, reject) => {
                const ops = [];
                for (let user in users) {
                    if (users[user].channels.indexOf(channel.toLowerCase()) >= 0) {
                        ops.push(user)
                    }
                }
                resolve(ops);
            });
        }
    };
};<commit_msg>Null user can't be admin or op<commit_after>'use strict';

module.exports = (bot, config) => {
    if (typeof config.data.permissions === 'undefined') {
        config.data.permissions = {};
    }
    const users = config.data.permissions;
    const getUser = (name) => {
        name = name.toLowerCase();
        let result = users[name];
        if (typeof result === 'undefined') {
            result = {admin: false, channels: []};
            users[name] = result;
        }
        return result;
    };
    const saveConfig = () => {
        for (const name in users) {
            const user = users[name];
            if (!user.admin && user.channels.length === 0) {
                delete users[name];
            }
        }
        return config.save();
    };

    for (const name in users) {
        const user = users[name];
        if (typeof user.admin !== 'boolean') {
            user.admin = false;
        }
        if (!Array.isArray(user.channels)) {
            user.channels = [];
        }
    }

    return {
        isAdmin: (name) => {
            return name !== null && getUser(name).admin;
        },
        isOperator: (name, channel) => {
            return name !== null && getUser(name).channels.indexOf(channel.toLowerCase()) > -1;
        },
        setAdmin: (name, value) => {
            const user = getUser(name);
            user.admin = !!value;
            return saveConfig();
        },
        setOperator: (name, channel, value) => {
            const user = getUser(name);
            const index = user.channels.indexOf(channel.toLowerCase());
            if (value && index === -1) {
                user.channels.push(channel.toLowerCase());
                return saveConfig();
            } else if (!value && index > -1) {
                user.channels.splice(index, 1);
                return saveConfig();
            }
        },
        getAdmins: () => {
            return new Promise((resolve, reject) => {
                const admins = [];
                for (let user in users) {
                    if (users[user].admin) {
                        admins.push(user)
                    }
                }
                resolve(admins);
            });
        },
        getOperators: (channel) => {
            return new Promise((resolve, reject) => {
                const ops = [];
                for (let user in users) {
                    if (users[user].channels.indexOf(channel.toLowerCase()) >= 0) {
                        ops.push(user)
                    }
                }
                resolve(ops);
            });
        }
    };
};<|endoftext|>


<commit_before>function Entity(id, x, y, data){
  this.x = x; //x-coordinate in pixels
  this.y = y; //y-coordinate in pixels
  this.tx = Math.floor(x/32); //target x-coordinate in tiles
  this.ty = Math.floor(y/32); //target y-coordinate in tiles
  this.id = id;
  this.spriteData = data.spriteData;
  this.lightData = [];
  this.sprites = [];
  this.lights = [];
  this.speed = 3.2;
  this.states = [];
  this.layer = data.layer || 3;

  this.container = new PIXI.Container();
  this.container.x = this.x;
  this.container.y = this.y;
  /*
  for (var i=0; i < this.spriteData.length; i++){
    var sData = this.spriteData[i];
    var spr = {
      source: sData.source,
      x: sData.x || 0,
      y: sData.y || 0,
      index: sData.index || 0
    }
    var imagePath = subfolder+"sprites/"+spr.source;
    var tex = getTextureFrame(imagePath,spr.index,32,32);
    var sprite = new PIXI.Sprite(tex);
    this.container.addChild(sprite);
    this.sprites[i] = sprite;

    sprite.x = spr.x;
    sprite.y = spr.y;
  }
  */

  stageEntities.children[this.layer].addChild(this.container);

  this.update(data);
}

Entity.prototype.update = function(data){
  //world.cellSetOverwrite(this.tx,this.ty,{})
  Object.assign(this,data);
  if (data.layer){
    this.changeLayer(data.layer);
  }
  if (data.x != undefined){
    this.tx = Math.floor(data.x/32);
  }
  if (data.y != undefined){
    this.ty = Math.floor(data.y/32);
  }
  if (data.spriteData != undefined){
    for (var i=0; i<this.spriteData.length; i++){
      //var sprite = this.sprites[sprite];
      var sprite = this.sprites[i];
      var sprData = data.spriteData[i];
      var path = subfolder+"sprites/"+sprData.source;
      if (!sprite){
        sprite = new PIXI.Sprite(getTextureFrame(path, sprData.index, sprData.width || 32, sprData.height || 32));
        //this.sprites[sprite] = sprite;
        this.sprites[i] = sprite;
        this.container.addChild(sprite);
      }
      //sprite.setTexture(getTextureFrame(path, data.index, data.width || 32, data.height || 32));
    }
  }
  if (data.lightData != undefined){
    for (var i=0; i<this.lightData.length; i++){
      var data = this.lightData[i];
    }
  }
  if (this.tile){
    world.cellSetOverwrite(this.tx,this.ty,this.tile);
  }
}

Entity.prototype.step = function(delta){
  if (player.mode == "spectator" && this == cam){return false;}

  var spd = this.speed*(delta/10);

  this.x += Math.sign(this.tx*32-this.x)*spd;
  this.y += Math.sign(this.ty*32-this.y)*spd;
  if (Math.abs(this.tx*32-this.x)<spd){this.x = this.tx*32}
  if (Math.abs(this.ty*32-this.y)<spd){this.y = this.ty*32}

  this.container.x = this.x;
  this.container.y = this.y;
  for (var i = 0; i < this.spriteData.length; i++){
    var data = this.spriteData[i];
    var sprite = this.sprites[i];
    var path = subfolder+"sprites/"+data.source;
    sprite.x = data.x || 0;
    sprite.y = data.y || 0;
    sprite.setTexture(getTextureFrame(path, data.index || 0, data.width || 32, data.height || 32));
    if (data.angle){
      sprite.rotation = data.angle * Math.PI / 180;
      sprite.x = 32;
      sprite.y = 16;
    }
    if (data.animation == "jump"){
      var f = ((this.x % 32)/32)+((this.y % 32)/32);
      sprite.y = -(Math.sin(f*Math.PI)*4) + data.y;
    }
    if (data.visible != undefined){
      sprite.visible = data.visible;
    }
    if (data.scale){
      sprite.scale.x = data.scale;
      sprite.scale.y = data.scale;
    }
  }

  if (this.states.includes("burning")){
    if (this.spriteBurnFront == undefined){
      this.spriteBurnFront = new PIXI.Sprite(getTextureFrame("sprites/effects/eff_fire_human_front.png",0,32,32));
      this.spriteBurnBack = new PIXI.Sprite(getTextureFrame("sprites/effects/eff_fire_human_back.png",0,32,32));
      this.container.addChild(this.spriteBurnBack);
      this.container.swapChildren(this.spriteBurnBack, this.sprites[0]);
      this.container.addChild(this.spriteBurnFront);
    }
    var currentTime = (Date.now() % 500);
    var frame = Math.floor(currentTime / 125);
    this.spriteBurnFront.visible = true;
    this.spriteBurnBack.visible = true;
    this.spriteBurnFront.setTexture(getTextureFrame("sprites/effects/eff_fire_human_front.png",frame,32,32));
    this.spriteBurnBack.setTexture(getTextureFrame("sprites/effects/eff_fire_human_back.png",frame,32,32));
  }else{
    if (this.spriteBurnFront){
      this.spriteBurnFront.visible = false;
    }
    if (this.spriteBurnBack){
      this.spriteBurnBack.visible = false;
    }
  }

  if (mouseOverRaw(this.x,this.y,this.x+32,this.y+32)){
    hoverlist.push(this);
  }

}

Entity.prototype.destroy = function(){
  for (var i = 0; i < this.sprites.lenght; i++){
    this.sprites[i].destroy();
  }
  for (var i = 0; i < this.lights.length; i++){
    this.lights[i].destroy();
  }
  this.container.destroy();
  if (this.tile){
    world.cellSetOverwrite(this.tx,this.ty,{})
  }
  if (this.spriteBurnBack){
    this.spriteBurnBack.destroy();
    this.spriteBurnFront.destroy();
  }
}

Entity.prototype.changeLayer = function(layer){
  if (layer != this.layer){
    stageEntities.children[layer].removeChild(this.container);
    this.layer = layer;
    stageEntities.children[layer].addChild(this.container);
  }
}<commit_msg>fixed something with wrong sprites displayed<commit_after>function Entity(id, x, y, data){
  this.x = x; //x-coordinate in pixels
  this.y = y; //y-coordinate in pixels
  this.tx = Math.floor(x/32); //target x-coordinate in tiles
  this.ty = Math.floor(y/32); //target y-coordinate in tiles
  this.id = id;
  this.spriteData = data.spriteData;
  this.lightData = [];
  this.sprites = [];
  this.lights = [];
  this.speed = 3.2;
  this.states = [];
  this.layer = data.layer || 3;

  this.container = new PIXI.Container();
  this.container.x = this.x;
  this.container.y = this.y;
  /*
  for (var i=0; i < this.spriteData.length; i++){
    var sData = this.spriteData[i];
    var spr = {
      source: sData.source,
      x: sData.x || 0,
      y: sData.y || 0,
      index: sData.index || 0
    }
    var imagePath = subfolder+"sprites/"+spr.source;
    var tex = getTextureFrame(imagePath,spr.index,32,32);
    var sprite = new PIXI.Sprite(tex);
    this.container.addChild(sprite);
    this.sprites[i] = sprite;

    sprite.x = spr.x;
    sprite.y = spr.y;
  }
  */

  stageEntities.children[this.layer].addChild(this.container);

  this.update(data);
}

Entity.prototype.update = function(data){
  //world.cellSetOverwrite(this.tx,this.ty,{})
  Object.assign(this,data);
  if (data.layer){
    this.changeLayer(data.layer);
  }
  if (data.x != undefined){
    this.tx = Math.floor(data.x/32);
  }
  if (data.y != undefined){
    this.ty = Math.floor(data.y/32);
  }
  if (data.spriteData != undefined){
    for (var i=0; i<this.spriteData.length; i++){
      //var sprite = this.sprites[sprite];
      var sprite = this.sprites[i];
      var sprData = data.spriteData[i];
      var path = subfolder+"sprites/"+sprData.source;
      if (!sprite){
        sprite = new PIXI.Sprite(getTextureFrame(path, sprData.index, sprData.width || 32, sprData.height || 32));
        //this.sprites[sprite] = sprite;
        this.sprites[i] = sprite;
        this.container.addChild(sprite);
      }
      sprite.setTexture(getTextureFrame(path, data.index, data.width || 32, data.height || 32));
    }
  }
  if (data.lightData != undefined){
    for (var i=0; i<this.lightData.length; i++){
      var data = this.lightData[i];
    }
  }
  if (this.tile){
    world.cellSetOverwrite(this.tx,this.ty,this.tile);
  }
}

Entity.prototype.step = function(delta){
  if (player.mode == "spectator" && this == cam){return false;}

  var spd = this.speed*(delta/10);

  this.x += Math.sign(this.tx*32-this.x)*spd;
  this.y += Math.sign(this.ty*32-this.y)*spd;
  if (Math.abs(this.tx*32-this.x)<spd){this.x = this.tx*32}
  if (Math.abs(this.ty*32-this.y)<spd){this.y = this.ty*32}

  this.container.x = this.x;
  this.container.y = this.y;
  for (var i = 0; i < this.spriteData.length; i++){
    var data = this.spriteData[i];
    var sprite = this.sprites[i];
    var path = subfolder+"sprites/"+data.source;
    sprite.x = data.x || 0;
    sprite.y = data.y || 0;
    sprite.setTexture(getTextureFrame(path, data.index || 0, data.width || 32, data.height || 32));
    if (data.angle){
      sprite.rotation = data.angle * Math.PI / 180;
      sprite.x = 32;
      sprite.y = 16;
    }
    if (data.animation == "jump"){
      var f = ((this.x % 32)/32)+((this.y % 32)/32);
      sprite.y = -(Math.sin(f*Math.PI)*4) + data.y;
    }
    if (data.visible != undefined){
      sprite.visible = data.visible;
    }
    if (data.scale){
      sprite.scale.x = data.scale;
      sprite.scale.y = data.scale;
    }
  }

  if (this.states.includes("burning")){
    if (this.spriteBurnFront == undefined){
      this.spriteBurnFront = new PIXI.Sprite(getTextureFrame("sprites/effects/eff_fire_human_front.png",0,32,32));
      this.spriteBurnBack = new PIXI.Sprite(getTextureFrame("sprites/effects/eff_fire_human_back.png",0,32,32));
      this.container.addChild(this.spriteBurnBack);
      this.container.swapChildren(this.spriteBurnBack, this.sprites[0]);
      this.container.addChild(this.spriteBurnFront);
    }
    var currentTime = (Date.now() % 500);
    var frame = Math.floor(currentTime / 125);
    this.spriteBurnFront.visible = true;
    this.spriteBurnBack.visible = true;
    this.spriteBurnFront.setTexture(getTextureFrame("sprites/effects/eff_fire_human_front.png",frame,32,32));
    this.spriteBurnBack.setTexture(getTextureFrame("sprites/effects/eff_fire_human_back.png",frame,32,32));
  }else{
    if (this.spriteBurnFront){
      this.spriteBurnFront.visible = false;
    }
    if (this.spriteBurnBack){
      this.spriteBurnBack.visible = false;
    }
  }

  if (mouseOverRaw(this.x,this.y,this.x+32,this.y+32)){
    hoverlist.push(this);
  }

}

Entity.prototype.destroy = function(){
  for (var i = 0; i < this.sprites.lenght; i++){
    this.sprites[i].destroy();
  }
  for (var i = 0; i < this.lights.length; i++){
    this.lights[i].destroy();
  }
  this.container.destroy();
  if (this.tile){
    world.cellSetOverwrite(this.tx,this.ty,{})
  }
  if (this.spriteBurnBack){
    this.spriteBurnBack.destroy();
    this.spriteBurnFront.destroy();
  }
}

Entity.prototype.changeLayer = function(layer){
  if (layer != this.layer){
    stageEntities.children[layer].removeChild(this.container);
    this.layer = layer;
    stageEntities.children[layer].addChild(this.container);
  }
}<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var _ = require('lodash');
var async = require('async');
var prompt = require('prompt');
var howto_loadAppModelsAndAdapters = require('./load-user-modules');
var howto_normalizeModelDef = require('./normalize-model');
var howto_buildORM = require('./build-orm');
var howto_backwardsCompatibleConfig = require('./backwards-compatibility/upgrade-sails.config');

module.exports = function(sails) {

  // Hydrate freeze-dried (context-free) modules using the sails app instance
  var loadAppModelsAndAdapters = howto_loadAppModelsAndAdapters(sails);
  var backwardsCompatibleConfig = howto_backwardsCompatibleConfig(sails);
  var normalizeModelDef = howto_normalizeModelDef(sails);
  var buildORM = howto_buildORM(sails);

  /**
   * Hook definition
   */

  var hook = {

    defaults: {

      globals: {
        adapters: true,
        models: true
      },

      // Default model properties
      models: {

        // This default connection (i.e. datasource) for the app
        // will be used for each model unless otherwise specified.
        connection: 'localDiskDb'
      },

      // Connections to data sources, web services, and external APIs.
      // Can be attached to models and/or accessed directly.
      connections: {

        // Built-in disk persistence
        // (by default, creates the file: `.tmp/localDiskDb.db`)
        localDiskDb: {
          adapter: 'sails-disk'
        }
      }
    },

    configure: function() {

      // Backwards compatibilty
      sails.config = backwardsCompatibleConfig(sails.config);

      // Listen for reload events
      sails.on('hook:orm:reload', hook.reload);

      // Listen for lower event, and tear down all of the adapters
      sails.on('lower', hook.teardown);
    },

    ////////////////////////////////////////////////////////////////////////////
    // NOTE: If a user hook needs to add or modify model definitions,
    // the hook should wait until `hook:orm:loaded`, then reload the original
    // model modules `orm/loadUserModules`. Finally, the ORM should be flushed using
    // `reload()` below.
    ////////////////////////////////////////////////////////////////////////////
    initialize: function(cb) {

      async.auto({

        // Load model and adapter definitions defined in the project
        _loadModules: function (next) {
          loadAppModelsAndAdapters(next);
        },

        // Normalize model definitions and merge in defaults from
        // `sails.config.models.*`
        normalizedModelDefs: ['_loadModules', function normalizeModelDefs(next) {
          _.each(sails.models, function (model, identity) {
            normalizeModelDef(model, identity);
          });
          next(null, sails.models);
        }],

        // Before continuing any further to actually start up the ORM,
        // check the migrate settings for each model to (1) use migrate:safe
        // in production and (2) prompt the user to make a decision if no migrate
        // configuration is present.
        _doubleCheckMigration: ['normalizedModelDefs', function (next) {

          // If there are no models, we're good
          if (!_.keys(sails.models).length) {
            return next();
          }

          // If a project-wide migrate setting (sails.config.models.migrate) is defined, we're good.
          if (typeof sails.config.models.migrate !== 'undefined') {
            return next();
          }

          // Otherwise show a prompt
          console.log('-----------------------------------------------------------------');
          console.log();
          prompt.start();
          console.log('',
            'Excuse my interruption, but it looks like this app'+'\n',
            'does not have a project-wide "migrate" setting configured yet.'+'\n',
            '(perhaps this is the first time you\'re lifting it with models?)'+'\n',
            '\n',
            'In short, this setting controls whether/how Sails will attempt to automatically'+'\n',
            'rebuild the tables/collections/sets/etc. in your database schema.\n',
            'You can read more about the "migrate" setting here:'+'\n',
            'http://sailsjs.org/#/documentation/concepts/ORM/model-settings.html?q=migrate\n'
            // 'command(⌘)+click to open links in the terminal'
          );
          console.log('',
            'In a production environment (NODE_ENV==="production") Sails always uses'+'\n',
            'migrate:"safe" to protect inadvertent deletion of your data.\n',
            'However during development, you have a few other options for convenience:'+'\n\n',
            '1. safe  - never auto-migrate my database(s). I will do it myself (by hand)','\n',
            '2. alter - auto-migrate, but attempt to keep my existing data (experimental)\n',
            '3. drop  - wipe/drop ALL my data and rebuild models every time I lift Sails\n'
          );
          console.log('What would you like Sails to do?');
          console.log();
          sails.log.warn('** DO NOT CHOOSE "2" or "3" IF YOU ARE WORKING WITH PRODUCTION DATA **');
          console.log();
          prompt.get(['?'], function(err, result) {
            if (err) return next(err);
            result = +result['?'];

            switch (result) {
              case 2:
                sails.config.models.migrate = 'alter';
                break;
              case 3:
                sails.config.models.migrate = 'drop';
                break;
              default:
                sails.config.models.migrate = 'safe';
                break;
            }

            console.log();
            console.log(' Temporarily setting `sails.config.models.migrate` to "%s"...', sails.config.models.migrate);
            console.log(' (press CTRL+C to cancel-- continuing lift automatically in 2 seconds...)');
            console.log();
            sails.log.info('To skip this prompt, add this project-wide "migrate" setting to your app.');
            sails.log.info('(conventionally, this is set in `config/models.js`)');
            console.log();
            setTimeout(function (){
              return next();
            },2200);
          });

          // async.eachSeries(_.keys(sails.models), function (identity, nextModel) {
          //   // If migrate setting is defined, continue without doing anything else.
          //   if (typeof sails.models[identity].migrate !== 'undefined') {
          //     return nextModel();
          //   }

          //   // If migrate setting is not specififed on this model,
          //   // display a prompt and require the user to make a decision about
          //   // their migration strategy.
          //   var thisModel = sails.models[identity];

          // }, next);

        }],

        // Once all user model and adapter definitions are loaded
        // and normalized, go ahead and initialize the ORM, which
        // creates instantiated model objects and stuffs them in
        // sails.models.
        instantiatedCollections: ['_doubleCheckMigration', function (next, async_data) {
          buildORM(async_data.normalizedModelDefs, next);
        }]

      }, cb);
    },

    // Reload ORM hook
    // (which mostly just runs the hook's `initialize()` fn again)
    reload: function () {

      // Teardown all of the adapters, since initialize() will restart them
      hook.teardown(function() {
        hook.initialize(function(err) {
          if (err) {
            sails.log.error('Failed to reinitialize ORM.');
            sails.log.error(err);
            // TODO: emit "error" on app instance instead of throwing
            throw new Error(err);
          }
          else {
            // If the re-initialization was a success, trigger an event
            // in case something needs to respond to the ORM reload (e.g. pubsub hook)
            sails.emit('hook:orm:reloaded');
          }
        });
      });
    },

    // Teardown ORM hook
    teardown: function (cb) {
      cb = cb || function(err) {
        if (err) {
          sails.log.error('Failed to teardown ORM hook.');
          sails.log.error(err);
        }
      };
      async.forEach(Object.keys(sails.adapters), function(name, cb) {
        var adapter = sails.adapters[name];
        if (adapter.teardown) {
          adapter.teardown(null, cb);
        } else {
          cb();
        }
      }, cb);
    }
  };

  return hook;

};
<commit_msg>Better explanation of setting sails.config.models.migrate.<commit_after>/**
 * Module dependencies.
 */

var _ = require('lodash');
var async = require('async');
var prompt = require('prompt');
var howto_loadAppModelsAndAdapters = require('./load-user-modules');
var howto_normalizeModelDef = require('./normalize-model');
var howto_buildORM = require('./build-orm');
var howto_backwardsCompatibleConfig = require('./backwards-compatibility/upgrade-sails.config');

module.exports = function(sails) {

  // Hydrate freeze-dried (context-free) modules using the sails app instance
  var loadAppModelsAndAdapters = howto_loadAppModelsAndAdapters(sails);
  var backwardsCompatibleConfig = howto_backwardsCompatibleConfig(sails);
  var normalizeModelDef = howto_normalizeModelDef(sails);
  var buildORM = howto_buildORM(sails);

  /**
   * Hook definition
   */

  var hook = {

    defaults: {

      globals: {
        adapters: true,
        models: true
      },

      // Default model properties
      models: {

        // This default connection (i.e. datasource) for the app
        // will be used for each model unless otherwise specified.
        connection: 'localDiskDb'
      },

      // Connections to data sources, web services, and external APIs.
      // Can be attached to models and/or accessed directly.
      connections: {

        // Built-in disk persistence
        // (by default, creates the file: `.tmp/localDiskDb.db`)
        localDiskDb: {
          adapter: 'sails-disk'
        }
      }
    },

    configure: function() {

      // Backwards compatibilty
      sails.config = backwardsCompatibleConfig(sails.config);

      // Listen for reload events
      sails.on('hook:orm:reload', hook.reload);

      // Listen for lower event, and tear down all of the adapters
      sails.on('lower', hook.teardown);
    },

    ////////////////////////////////////////////////////////////////////////////
    // NOTE: If a user hook needs to add or modify model definitions,
    // the hook should wait until `hook:orm:loaded`, then reload the original
    // model modules `orm/loadUserModules`. Finally, the ORM should be flushed using
    // `reload()` below.
    ////////////////////////////////////////////////////////////////////////////
    initialize: function(cb) {

      async.auto({

        // Load model and adapter definitions defined in the project
        _loadModules: function (next) {
          loadAppModelsAndAdapters(next);
        },

        // Normalize model definitions and merge in defaults from
        // `sails.config.models.*`
        normalizedModelDefs: ['_loadModules', function normalizeModelDefs(next) {
          _.each(sails.models, function (model, identity) {
            normalizeModelDef(model, identity);
          });
          next(null, sails.models);
        }],

        // Before continuing any further to actually start up the ORM,
        // check the migrate settings for each model to (1) use migrate:safe
        // in production and (2) prompt the user to make a decision if no migrate
        // configuration is present.
        _doubleCheckMigration: ['normalizedModelDefs', function (next) {

          // If there are no models, we're good
          if (!_.keys(sails.models).length) {
            return next();
          }

          // If a project-wide migrate setting (sails.config.models.migrate) is defined, we're good.
          if (typeof sails.config.models.migrate !== 'undefined') {
            return next();
          }

          // Otherwise show a prompt
          console.log('-----------------------------------------------------------------');
          console.log();
          prompt.start();
          console.log('',
            'Excuse my interruption, but it looks like this app'+'\n',
            'does not have a project-wide "migrate" setting configured yet.'+'\n',
            '(perhaps this is the first time you\'re lifting it with models?)'+'\n',
            '\n',
            'In short, this setting controls whether/how Sails will attempt to automatically'+'\n',
            'rebuild the tables/collections/sets/etc. in your database schema.\n',
            'You can read more about the "migrate" setting here:'+'\n',
            'http://sailsjs.org/#/documentation/concepts/ORM/model-settings.html?q=migrate\n'
            // 'command(⌘)+click to open links in the terminal'
          );
          console.log('',
            'In a production environment (NODE_ENV==="production") Sails always uses'+'\n',
            'migrate:"safe" to protect inadvertent deletion of your data.\n',
            'However during development, you have a few other options for convenience:'+'\n\n',
            '1. safe  - never auto-migrate my database(s). I will do it myself (by hand)','\n',
            '2. alter - auto-migrate, but attempt to keep my existing data (experimental)\n',
            '3. drop  - wipe/drop ALL my data and rebuild models every time I lift Sails\n'
          );
          console.log('What would you like Sails to do?');
          console.log();
          sails.log.info('To skip this prompt in the future, set `sails.config.models.migrate`.');
          sails.log.info('(conventionally, this is done in `config/models.js`)');
          console.log();
          sails.log.warn('** DO NOT CHOOSE "2" or "3" IF YOU ARE WORKING WITH PRODUCTION DATA **');
          console.log();
          prompt.get(['?'], function(err, result) {
            if (err) return next(err);
            result = result['?'];

            switch (result) {
              case 'alter':
              case '2':
                sails.config.models.migrate = 'alter';
                break;
              case 'drop':
              case '3':
                sails.config.models.migrate = 'drop';
                break;
              default:
                sails.config.models.migrate = 'safe';
                break;
            }

            console.log();
            console.log(' Temporarily using `sails.config.models.migrate="%s"...', sails.config.models.migrate);
            console.log(' (press CTRL+C to cancel-- continuing lift automatically in 0.5 seconds...)');
            console.log();
            setTimeout(function (){
              return next();
            },600);
          });

          // async.eachSeries(_.keys(sails.models), function (identity, nextModel) {
          //   // If migrate setting is defined, continue without doing anything else.
          //   if (typeof sails.models[identity].migrate !== 'undefined') {
          //     return nextModel();
          //   }

          //   // If migrate setting is not specififed on this model,
          //   // display a prompt and require the user to make a decision about
          //   // their migration strategy.
          //   var thisModel = sails.models[identity];

          // }, next);

        }],

        // Once all user model and adapter definitions are loaded
        // and normalized, go ahead and initialize the ORM, which
        // creates instantiated model objects and stuffs them in
        // sails.models.
        instantiatedCollections: ['_doubleCheckMigration', function (next, async_data) {
          buildORM(async_data.normalizedModelDefs, next);
        }]

      }, cb);
    },

    // Reload ORM hook
    // (which mostly just runs the hook's `initialize()` fn again)
    reload: function () {

      // Teardown all of the adapters, since initialize() will restart them
      hook.teardown(function() {
        hook.initialize(function(err) {
          if (err) {
            sails.log.error('Failed to reinitialize ORM.');
            sails.log.error(err);
            // TODO: emit "error" on app instance instead of throwing
            throw new Error(err);
          }
          else {
            // If the re-initialization was a success, trigger an event
            // in case something needs to respond to the ORM reload (e.g. pubsub hook)
            sails.emit('hook:orm:reloaded');
          }
        });
      });
    },

    // Teardown ORM hook
    teardown: function (cb) {
      cb = cb || function(err) {
        if (err) {
          sails.log.error('Failed to teardown ORM hook.');
          sails.log.error(err);
        }
      };
      async.forEach(Object.keys(sails.adapters), function(name, cb) {
        var adapter = sails.adapters[name];
        if (adapter.teardown) {
          adapter.teardown(null, cb);
        } else {
          cb();
        }
      }, cb);
    }
  };

  return hook;

};
<|endoftext|>


<commit_before>/**
 * External dependencies.
 */

var extend = require('super').extend;

/**
 * Store `Date` locally since modules like `Timekeeper`
 * can modify it.
 */

var D = Date;

/**
 * Base Test.
 *
 * @param {String} title
 * @param {Function} fn
 * @param {Array} meta
 * @constructor
 */

function Base(title, fn, meta) {
  this.title = title;
  this.meta = meta || [];
  this.fn = fn;
  this.status = null;
  this.error = null;
  this.time = null;
  this.context = {};
  this.meta = Array.isArray(this.meta) ? this.meta : [this.meta];
  this.events = {
    pre: 'pre:test',
    post: 'post:test',
  };

  if (!this.fn) {
    this.pending();
  }
}

/**
 * Extend.
 */

Base.extend = extend;

/**
 * Configure test timeout.
 *
 * @param {Number} ms
 * @api public
 */

Base.prototype.timeout = function(ms) {
  this._timeout = ms;
  return this;
};

/**
 * Mark the test as skipped.
 *
 * @api public
 */

Base.prototype.skip = function(condition) {
  if (arguments.length && !condition) return;
  this.status = 'skipped';
  this.time = 0;
};

/**
 * Mark the test as pending.
 *
 * @returns {Base} self
 * @api public
 */

Base.prototype.pending = function() {
  this.status = 'pending';
  this.time = 0;
  return this;
};

/**
 * Run the test.
 *
 * @param {Object} emitter
 * @param {Function} done
 * @api public
 */

Base.prototype.run = function(emitter, done) {
  var self = this;
  var events = this.events;
  var disabled = this.status === 'pending' || this.status === 'skipped';

  emitter.emit(events.pre, this, function() {
    if (disabled) return emitter.emit(events.post, self, done);
    var start = (new D).getTime();
    self.exec(function(err) {
      self.time = (new D).getTime() - start;
      if (err) self.fail(err);
      else self.pass();
      emitter.emit(events.post, self, done);
    });
  });
};

/**
 * Mark the test as failed.
 *
 * @param {Object} error
 * @returns {Base} self
 * @api private
 */

Base.prototype.fail = function(err) {
  this.status = 'failed';
  this.error = err;
  return this;
};

/**
 * Mark the test as passed.
 *
 * @returns {Base} self
 * @api private
 */

Base.prototype.pass = function() {
  this.status = 'passed';
  return this;
};

/**
 * Primary export.
 */

module.exports = Base;
<commit_msg>Allow tests to be skipped from a plugin<commit_after>/**
 * External dependencies.
 */

var extend = require('super').extend;

/**
 * Store `Date` locally since modules like `Timekeeper`
 * can modify it.
 */

var D = Date;

/**
 * Base Test.
 *
 * @param {String} title
 * @param {Function} fn
 * @param {Array} meta
 * @constructor
 */

function Base(title, fn, meta) {
  this.title = title;
  this.meta = meta || [];
  this.fn = fn;
  this.status = null;
  this.error = null;
  this.time = null;
  this.context = {};
  this.meta = Array.isArray(this.meta) ? this.meta : [this.meta];
  this.events = {
    pre: 'pre:test',
    post: 'post:test',
  };

  if (!this.fn) {
    this.pending();
  }
}

/**
 * Extend.
 */

Base.extend = extend;

/**
 * Configure test timeout.
 *
 * @param {Number} ms
 * @api public
 */

Base.prototype.timeout = function(ms) {
  this._timeout = ms;
  return this;
};

/**
 * Mark the test as skipped.
 *
 * @api public
 */

Base.prototype.skip = function(condition) {
  if (arguments.length && !condition) return;
  this.status = 'skipped';
  this.time = 0;
};

/**
 * Mark the test as pending.
 *
 * @returns {Base} self
 * @api public
 */

Base.prototype.pending = function() {
  this.status = 'pending';
  this.time = 0;
  return this;
};

/**
 * Run the test.
 *
 * @param {Object} emitter
 * @param {Function} done
 * @api public
 */

Base.prototype.run = function(emitter, done) {
  var self = this;
  var events = this.events;
  var disabled = this.status === 'pending' || this.status === 'skipped';

  emitter.emit(events.pre, this, function() {
    var disabled = self.status === 'pending' || self.status === 'skipped';
    if (disabled) return emitter.emit(events.post, self, done);
    var start = (new D).getTime();
    self.exec(function(err) {
      self.time = (new D).getTime() - start;
      if (err) self.fail(err);
      else self.pass();
      emitter.emit(events.post, self, done);
    });
  });
};

/**
 * Mark the test as failed.
 *
 * @param {Object} error
 * @returns {Base} self
 * @api private
 */

Base.prototype.fail = function(err) {
  this.status = 'failed';
  this.error = err;
  return this;
};

/**
 * Mark the test as passed.
 *
 * @returns {Base} self
 * @api private
 */

Base.prototype.pass = function() {
  this.status = 'passed';
  return this;
};

/**
 * Primary export.
 */

module.exports = Base;
<|endoftext|>


<commit_before>exports = module.exports = function() {

  return function username(user, cb) {
    //return cb(null, { username: 'johndoe'});
    return cb(null, { username: '961cb8d93cd9c41725f84c96aa6d65d0' });
    return cb(null, { username: user.username });
  };
};

exports['@singleton'] = true;
exports['@require'] = [];
<commit_msg>Remove username.<commit_after>exports = module.exports = function() {

  return function username(user, cb) {
    //return cb(null, { username: 'johndoe'});
    return cb(null, { username: user.username });
  };
};

exports['@singleton'] = true;
exports['@require'] = [];
<|endoftext|>