<commit_before>/**
 * @module ScramjetCore
 */

const {PromiseTransformStream} = require('./util/promise-transform-stream');
const scramjet = require('./');

// const cpus = require("os").cpus();

/**
 * DataStream is the primary stream type for Scramjet. When you parse your
 * stream, just pipe it you can then perform calculations on the data objects
 * streamed through your flow.
 *
 * @classdesc
 * @extends stream.PassThrough
 */
class DataStream extends PromiseTransformStream {

    /**
     * Standard options for scramjet streams.
     *
     * @typedef {Object} StreamOptions
     * @property {Number} maxParallel the number of transforms done in parallel
     * @property {DataStream} referrer a referring stream to point to (if possible the transforms will be pushed to it
     *                                 instead of creating a new stream)
     */

    /**
     * Create the DataStream.
     *
     * @param {StreamOptions} opts Stream options passed to superclass
     *
     * @example {@link ../samples/data-stream-constructor.js}
     */
    constructor(opts) {
        super(Object.assign({
            objectMode: true,
            writableObjectMode: true,
            readableObjectMode: true
        }, opts));
    }

    /**
     * Stops merging transform callbacks at the current place in the command chain.
     *
     * @name tap
     * @function
     * @example {@link ../samples/data-stream-tap.js}
     */

    /**
     * Reads a chunk from the stream and resolves the promise when read.
     *
     * @name whenRead
     * @function
     * @return {Promise<Object>}  the read item
     */

    /**
     * Writes a chunk to the stream and returns a Promise resolved when more chunks can be written.
     *
     * @name whenWrote
     * @function
     * @return {Promise<Object>}  the read item
     */

    /**
     *
     * Allows resetting stream options.
     *
     * @name setOptions
     * @function
     * @param {StreamOptions} options
     * @chainable
     */

    /**
     * Returns a new instance of self.
     *
     * Normally this doesn't have to be overridden.
     * When the constructor would use some special arguments this may be used to
     * override the object construction in {@link tee}...
     *
     * @private
     * @return {DataStream}  an empty instance of the same class.
     *
     * @example {@link ../samples/data-stream-selfinstance.js}
     */
    _selfInstance(...args) {
        return new this.constructor(...args);
    }

    /**
     * Calls the passed in place with the stream as first argument, returns result.
     *
     * @param  {Function} func if passed, the function will be called on self
     *                         to add an option to inspect the stream in place,
     *                         while not breaking the transform chain
     * @return {*}  anything the passed function returns
     *
     * @example {@link ../samples/data-stream-use.js}
     */
    use(func) {
        return func && func(this.tap());
    }

    /**
     * @callback TeeCallback
     * @param {DataStream} teed The teed stream
     */

    /**
     * Duplicate the stream
     *
     * Creates a duplicate stream instance and pases it to the callback.
     *
     * @param {TeeCallback} func The duplicate stream will be passed as first argument.
     * @return {DataStream}  self
     *
     * @example {@link ../samples/data-stream-tee.js}
     */
    tee(func) {
        func(this.pipe(this._selfInstance()));
        return this.tap();
    }

    /**
     * @callback ReduceCallback
     * @param {*} acc the accumulator - the object initially passed or retuned
     *                by the previous reduce operation
     * @param {Object} chunk the stream chunk.
     * @return {Promise|*}  accumulator for the next pass
     */

    /**
     * Reduces the stream into a given accumulator
     *
     * Works similarily to Array.prototype.reduce, so whatever you return in the
     * former operation will be the first operand to the latter.
     *
     * This method is serial - meaning that any processing on an entry will
     * occur only after the previous entry is fully processed. This does mean
     * it's much slower than parallel functions.
     *
     * @param  {TransformFunction} func The into object will be passed as the
     * first argument, the data object from the stream as the second.
     * @param  {Object} into Any object passed initally to the transform
     * function
     * @return {Promise}  Promise resolved by the last object returned by the
     * call of the transform function
     *
     * @example {@link ../samples/data-stream-reduce.js}
     */
    reduce(func, into) {

        return new Promise((res, rej) => {

            let last = Promise.resolve(into);

            this.tap().pipe(new PromiseTransformStream({
                parallelTransform: (chunk) => {
                    return last = last.then((acc) => func(acc, chunk));
                },
                referrer: this,
                initial: into
            }))
            .on("end", () => last.then(res))
            .on("error", rej)
            .resume();

        });

    }

    /**
     * Performs an operation on every chunk, without changing the stream
     *
     * This is a shorthand for ```stream.on("data", func)```
     *
     * @chainable
     * @param  {MapCallback} func a callback called for each chunk.
     */
    each(func) {
        this.tap().on("data", func);
        return this;
    }

    /**
     * @callback MapCallback
     * @param {*} chunk the chunk to be mapped
     * @returns {Promise|*}  the mapped object
     */

    /**
     * Transforms stream objects into new ones, just like Array.prototype.map
     * does.
     *
     * @param {MapCallback} func The function that creates the new object
     * @param {Class} Clazz (optional) The class to be mapped to.
     * @return {DataStream}  mapped stream
     *
     * @example {@link ../samples/data-stream-map.js}
     */
    map(func, Clazz) {
        Clazz = Clazz || this.constructor;
        return this.pipe(new Clazz({
            parallelTransform: func,
            referrer: this
        }));
    }

    /**
     * @callback FilterCallback
     * @param {*} chunk the chunk to be filtered or not
     * @returns {Promise|Boolean}  information if the object should remain in
     *                             the filtered stream.
     */

    /**
     * Filters object based on the function outcome, just like
     * Array.prototype.filter.
     *
     * @param  {FilterCallback} func The function that filters the object
     * @return {DataStream}  filtered stream
     *
     * @example {@link ../samples/data-stream-filter.js}
     */
    filter(func) {
        return this.pipe(this._selfInstance({
            parallelTransform: func,
            afterTransform: (chunk, ret) => ret ? chunk : DataStream.filter,
            referrer: this
        }));
    }

    /**
     * Override of node.js Readable pipe.
     *
     * Except for calling overriden method it proxies errors to piped stream.
     *
     * @param  {Writable} to  Writable stream to write to
     * @param  {WritableOptions} options
     * @return {Writable}  the `to` stream
     */
    pipe(to, options) {
        if (to === this) {
            return this;
        }

        this.on("error", (...err) => to.emit("error", ...err));
        return super.pipe(to, options || {end: true});
    }

    /**
     * Creates a BufferStream
     *
     * @param  {MapCallback} serializer A method that converts chunks to buffers
     * @return {BufferStream}  the resulting stream
     *
     * @example {@link ../samples/data-stream-tobufferstream.js}
     */
    toBufferStream(serializer) {
        return this.map(serializer, scramjet.BufferStream);
    }

    /**
     * Creates a StringStream
     *
     * @param  {MapCallback} serializer A method that converts chunks to strings
     * @return {StringStream}  the resulting stream
     *
     * @example {@link ../samples/data-stream-tostringstream.js}
     */
    stringify(serializer) {
        return this.map(serializer, scramjet.StringStream);
    }

    /**
     * Alias for {@link DataStream#stringify}
     * @function toStringStream
     */

    /**
     * Create a DataStream from an Array
     *
     * @param  {Array} arr list of chunks
     * @return {DataStream}  the resulting stream
     *
     * @example {@link ../samples/data-stream-fromarray.js}
     */
    static fromArray(arr) {
        const ret = new DataStream();
        arr = arr.slice();
        process.nextTick(() => {
            arr.forEach((item) => ret.write(item));
            ret.end();
        });
        return ret;
    }

    /**
     * Create a DataStream from an Iterator
     *
     * Doesn't end the stream until it reaches end of the iterator.
     *
     * @param  {Iterator} iter the iterator object
     * @return {DataStream}  the resulting stream
     *
     * @example {@link ../samples/data-stream-fromiterator.js}
     */
    static fromIterator(iter) {
        return new DataStream({
            read() {
                const read = iter.next();
                if (read.done) {
                    this.push(null);
                } else {
                    Promise.resolve(read.value)
                        .then((value) => this.push(value));
                }
            }
        });
    }

    /**
     * Aggregates the stream into a single Array
     *
     * In fact it's just a shorthand for reducing the stream into an Array.
     *
     * @param  {Array} initial Optional array to begin with.
     * @return {Promise}  Promise resolved with the resulting array on stream
     *                    end.
     */
    toArray(initial) {
        return this.reduce(
            (arr, item) => (arr.push(item), arr),
            initial || []
        );
    }

}

DataStream.prototype.toStringStream = DataStream.prototype.stringify;

module.exports = DataStream;
<commit_msg>fix filter by promise rejection<commit_after>/**
 * @module ScramjetCore
 */

const {PromiseTransformStream} = require('./util/promise-transform-stream');
const scramjet = require('./');

// const cpus = require("os").cpus();

/**
 * DataStream is the primary stream type for Scramjet. When you parse your
 * stream, just pipe it you can then perform calculations on the data objects
 * streamed through your flow.
 *
 * @classdesc
 * @extends stream.PassThrough
 */
class DataStream extends PromiseTransformStream {

    /**
     * Standard options for scramjet streams.
     *
     * @typedef {Object} StreamOptions
     * @property {Number} maxParallel the number of transforms done in parallel
     * @property {DataStream} referrer a referring stream to point to (if possible the transforms will be pushed to it
     *                                 instead of creating a new stream)
     */

    /**
     * Create the DataStream.
     *
     * @param {StreamOptions} opts Stream options passed to superclass
     *
     * @example {@link ../samples/data-stream-constructor.js}
     */
    constructor(opts) {
        super(Object.assign({
            objectMode: true,
            writableObjectMode: true,
            readableObjectMode: true
        }, opts));
    }

    /**
     * Stops merging transform callbacks at the current place in the command chain.
     *
     * @name tap
     * @function
     * @example {@link ../samples/data-stream-tap.js}
     */

    /**
     * Reads a chunk from the stream and resolves the promise when read.
     *
     * @name whenRead
     * @function
     * @return {Promise<Object>}  the read item
     */

    /**
     * Writes a chunk to the stream and returns a Promise resolved when more chunks can be written.
     *
     * @name whenWrote
     * @function
     * @return {Promise<Object>}  the read item
     */

    /**
     *
     * Allows resetting stream options.
     *
     * @name setOptions
     * @function
     * @param {StreamOptions} options
     * @chainable
     */

    /**
     * Returns a new instance of self.
     *
     * Normally this doesn't have to be overridden.
     * When the constructor would use some special arguments this may be used to
     * override the object construction in {@link tee}...
     *
     * @private
     * @return {DataStream}  an empty instance of the same class.
     *
     * @example {@link ../samples/data-stream-selfinstance.js}
     */
    _selfInstance(...args) {
        return new this.constructor(...args);
    }

    /**
     * Calls the passed in place with the stream as first argument, returns result.
     *
     * @param  {Function} func if passed, the function will be called on self
     *                         to add an option to inspect the stream in place,
     *                         while not breaking the transform chain
     * @return {*}  anything the passed function returns
     *
     * @example {@link ../samples/data-stream-use.js}
     */
    use(func) {
        return func && func(this.tap());
    }

    /**
     * @callback TeeCallback
     * @param {DataStream} teed The teed stream
     */

    /**
     * Duplicate the stream
     *
     * Creates a duplicate stream instance and pases it to the callback.
     *
     * @param {TeeCallback} func The duplicate stream will be passed as first argument.
     * @return {DataStream}  self
     *
     * @example {@link ../samples/data-stream-tee.js}
     */
    tee(func) {
        func(this.pipe(this._selfInstance()));
        return this.tap();
    }

    /**
     * @callback ReduceCallback
     * @param {*} acc the accumulator - the object initially passed or retuned
     *                by the previous reduce operation
     * @param {Object} chunk the stream chunk.
     * @return {Promise|*}  accumulator for the next pass
     */

    /**
     * Reduces the stream into a given accumulator
     *
     * Works similarily to Array.prototype.reduce, so whatever you return in the
     * former operation will be the first operand to the latter.
     *
     * This method is serial - meaning that any processing on an entry will
     * occur only after the previous entry is fully processed. This does mean
     * it's much slower than parallel functions.
     *
     * @param  {TransformFunction} func The into object will be passed as the
     * first argument, the data object from the stream as the second.
     * @param  {Object} into Any object passed initally to the transform
     * function
     * @return {Promise}  Promise resolved by the last object returned by the
     * call of the transform function
     *
     * @example {@link ../samples/data-stream-reduce.js}
     */
    reduce(func, into) {

        return new Promise((res, rej) => {

            let last = Promise.resolve(into);

            this.tap().pipe(new PromiseTransformStream({
                parallelTransform: (chunk) => {
                    return last = last.then((acc) => func(acc, chunk));
                },
                referrer: this,
                initial: into
            }))
            .on("end", () => last.then(res))
            .on("error", rej)
            .resume();

        });

    }

    /**
     * Performs an operation on every chunk, without changing the stream
     *
     * This is a shorthand for ```stream.on("data", func)```
     *
     * @chainable
     * @param  {MapCallback} func a callback called for each chunk.
     */
    each(func) {
        this.tap().on("data", func);
        return this;
    }

    /**
     * @callback MapCallback
     * @param {*} chunk the chunk to be mapped
     * @returns {Promise|*}  the mapped object
     */

    /**
     * Transforms stream objects into new ones, just like Array.prototype.map
     * does.
     *
     * @param {MapCallback} func The function that creates the new object
     * @param {Class} Clazz (optional) The class to be mapped to.
     * @return {DataStream}  mapped stream
     *
     * @example {@link ../samples/data-stream-map.js}
     */
    map(func, Clazz) {
        Clazz = Clazz || this.constructor;
        return this.pipe(new Clazz({
            parallelTransform: func,
            referrer: this
        }));
    }

    /**
     * @callback FilterCallback
     * @param {*} chunk the chunk to be filtered or not
     * @returns {Promise|Boolean}  information if the object should remain in
     *                             the filtered stream.
     */

    /**
     * Filters object based on the function outcome, just like
     * Array.prototype.filter.
     *
     * @param  {FilterCallback} func The function that filters the object
     * @return {DataStream}  filtered stream
     *
     * @example {@link ../samples/data-stream-filter.js}
     */
    filter(func) {
        return this.pipe(this._selfInstance({
            parallelTransform: func,
            afterTransform: (chunk, ret) => ret ? chunk : Promise.reject(DataStream.filter),
            referrer: this
        }));
    }

    /**
     * Override of node.js Readable pipe.
     *
     * Except for calling overriden method it proxies errors to piped stream.
     *
     * @param  {Writable} to  Writable stream to write to
     * @param  {WritableOptions} options
     * @return {Writable}  the `to` stream
     */
    pipe(to, options) {
        if (to === this) {
            return this;
        }

        this.on("error", (...err) => to.emit("error", ...err));
        return super.pipe(to, options || {end: true});
    }

    /**
     * Creates a BufferStream
     *
     * @param  {MapCallback} serializer A method that converts chunks to buffers
     * @return {BufferStream}  the resulting stream
     *
     * @example {@link ../samples/data-stream-tobufferstream.js}
     */
    toBufferStream(serializer) {
        return this.map(serializer, scramjet.BufferStream);
    }

    /**
     * Creates a StringStream
     *
     * @param  {MapCallback} serializer A method that converts chunks to strings
     * @return {StringStream}  the resulting stream
     *
     * @example {@link ../samples/data-stream-tostringstream.js}
     */
    stringify(serializer) {
        return this.map(serializer, scramjet.StringStream);
    }

    /**
     * Alias for {@link DataStream#stringify}
     * @function toStringStream
     */

    /**
     * Create a DataStream from an Array
     *
     * @param  {Array} arr list of chunks
     * @return {DataStream}  the resulting stream
     *
     * @example {@link ../samples/data-stream-fromarray.js}
     */
    static fromArray(arr) {
        const ret = new DataStream();
        arr = arr.slice();
        process.nextTick(() => {
            arr.forEach((item) => ret.write(item));
            ret.end();
        });
        return ret;
    }

    /**
     * Create a DataStream from an Iterator
     *
     * Doesn't end the stream until it reaches end of the iterator.
     *
     * @param  {Iterator} iter the iterator object
     * @return {DataStream}  the resulting stream
     *
     * @example {@link ../samples/data-stream-fromiterator.js}
     */
    static fromIterator(iter) {
        return new DataStream({
            read() {
                const read = iter.next();
                if (read.done) {
                    this.push(null);
                } else {
                    Promise.resolve(read.value)
                        .then((value) => this.push(value));
                }
            }
        });
    }

    /**
     * Aggregates the stream into a single Array
     *
     * In fact it's just a shorthand for reducing the stream into an Array.
     *
     * @param  {Array} initial Optional array to begin with.
     * @return {Promise}  Promise resolved with the resulting array on stream
     *                    end.
     */
    toArray(initial) {
        return this.reduce(
            (arr, item) => (arr.push(item), arr),
            initial || []
        );
    }

}

DataStream.prototype.toStringStream = DataStream.prototype.stringify;

module.exports = DataStream;
<|endoftext|>


<commit_before>const blessed = require('blessed');
const timestamp = require('../util/timestamp');

function Timestamp(createdAt) {
  const date = new Date();
  return blessed.box({
    tags: true,
    style,
    content: timestamp(createdAt, date),
  });
}

module.exports = Timestamp;
<commit_msg>Fix timestamps<commit_after>const blessed = require('blessed');
const timestamp = require('../util/timestamp');

function Timestamp(createdAt) {
  const date = new Date();
  return blessed.box({
    tags: true,
    content: timestamp(createdAt, date)
  });
}

module.exports = Timestamp;
<|endoftext|>


<commit_before>function Star() {
  this.x = (Math.random() * (field.x)| 0);
  this.y = (Math.random() * (field.y)| 0);

  this.img = (function() {
    var canvas = document.createElement('canvas'),
      context = canvas.getContext('2d');
    canvas.height = canvas.width = 10;
    context.beginPath();
    var radius = Math.random() * 3 |0;
    context.arc(2, 2, radius, 0, 2 * Math.PI, false);
    context.fillStyle = 'white';
    context.fill();
    context.closePath();
    return canvas;
  })();
}

function Planet() {
  this.x = (Math.random() * (field.x)| 0);
  this.y = (Math.random() * (field.y)| 0);

  var img = new Image();
  img.onload = function () {
    var r = Math.random() * 255 | 0,
      g = Math.random() * 255 | 0,
      b = Math.random() * 255 | 0;
    this.img = colorImage(img, r, g, b, 64);
  }.bind(this);
  img.src = '/img/gas.png';
  this.img = document.createElement('canvas');
}

inherits(Star, CanvasItem);
inherits(Planet, CanvasItem);
<commit_msg>small indentation fix<commit_after>function Star() {
  this.x = (Math.random() * (field.x)| 0);
  this.y = (Math.random() * (field.y)| 0);

  this.img = (function() {
    var canvas = document.createElement('canvas'),
      context = canvas.getContext('2d');
    canvas.height = canvas.width = 10;
    context.beginPath();
    var radius = Math.random() * 3 |0;
    context.arc(2, 2, radius, 0, 2 * Math.PI, false);
    context.fillStyle = 'white';
    context.fill();
    context.closePath();
    return canvas;
  })();
}

function Planet() {
  this.x = (Math.random() * (field.x)| 0);
  this.y = (Math.random() * (field.y)| 0);

  var img = new Image();
  img.onload = function () {
    var r = Math.random() * 255 | 0,
        g = Math.random() * 255 | 0,
        b = Math.random() * 255 | 0;
    this.img = colorImage(img, r, g, b, 64);
  }.bind(this);
  img.src = '/img/gas.png';
  this.img = document.createElement('canvas');
}

inherits(Star, CanvasItem);
inherits(Planet, CanvasItem);
<|endoftext|>


<commit_before>/**
 * @copyright Copyright (c) Sematext Group, Inc. - All Rights Reserved
 *
 * @licence SPM for Docker is free-to-use, proprietary software.
 * THIS IS PROPRIETARY SOURCE CODE OF Sematext Group, Inc. (Sematext)
 * This source code may not be copied, reverse engineered, or altered for any purpose.
 * This source code is to be used exclusively by users and customers of Sematext.
 * Please see the full license (found in LICENSE in this distribution) for details on its license and the licenses of its dependencies.
 */
'use strict'
var monitor = require('./dockerMonitor.js')
var Agent = require('spm-agent/lib/agent.js')
var SpmAgent = require('spm-agent')
var DockerEventForwarder = require('./dockerEventForwarder.js')
var containerCount = 0
var POD = /^POD$/
var ignoreImageVersion = !(process.env.IGNORE_IMAGE_VERSION === 'false')
global.spmSenderUrlParameters = '&containerCount=' + containerCount

function parseKubernetesInfo (containerName, k8sInfo) {
  // containers managed by Kubernetes have a prefix "k8s_", reference:
  // https://github.com/kubernetes/kubernetes/blob/f5d9c430e9168cf5c41197b8a4e457981cb031df/pkg/kubelet/dockertools/docker.go#L85
  if (!/k8s_/.test(containerName)) {
    return null
  }
  var fields = containerName.split('_')
  if (fields.length >= 4) {
    // example: k8s_sematext-agent.c56a873d_sematext-agent-qo2yf_default_e94b48c5-e63b-11e5-a8ec-0401b386ea01_8898bc93
    k8sInfo.kubernetes = {}
    k8sInfo.kubernetes.container_name = fields[1]
    k8sInfo.kubernetes.pod_name = fields[2]
    k8sInfo.kubernetes.namespace = fields[3]
    k8sInfo.kubernetes.uid = fields[4]
    return k8sInfo
  } else {
    return null
  }
}

function parseSwarmInfo (containerName, swarmInfo) {
  // Format: ID-swarmServiceName.ContainerNumber.TaskId
  if (!/\S{12}-\S+\.\d+\.\S+/.test(containerName)) {
    return null
  }
  var fields = containerName.split('.')
  if (fields.length === 3) {
    // remove ID with 13 characters
    if (fields[0]) {
      var idLength = containerName.indexOf('-')
      swarmInfo.service_name = fields[0].substring(idLength + 1, fields[0].length)
    }
    swarmInfo.container_number = fields[1]
    swarmInfo.task_id = fields[2]
    return swarmInfo
  } else {
    return null
  }
}

function dockerAgent () {
  var da = new Agent(
    {
      start: function (agent) {
        this.dockerListener = function (stats) {
          if (!stats) {
            return
          }
          if (stats.dockerId) {
            var containerName = stats.dockerId
            if (stats.name) {
              containerName = containerName + '-' + stats.name
            }
            var imageName = stats.image
            if (ignoreImageVersion && imageName) {
              imageName = imageName.split(':')[0]
            }
            var metric = {
              ts: new Date().getTime(),
              type: 'container',
              filters: [imageName, containerName],
              name: 'docker',
              value: stats.value,
              sct: 'APP'
            }
            var k8sInfo = parseKubernetesInfo(containerName, {})
            var swarmInfo = null
            if (!k8sInfo) {
              // check Docker Swarm
              swarmInfo = parseSwarmInfo(containerName, {})
            }

            if (k8sInfo && k8sInfo.kubernetes && k8sInfo.kubernetes.pod_name && k8sInfo.kubernetes.container_name && k8sInfo.kubernetes.uid) {
              // GKE does not report k8s.container_name, we find instead a static string "POD"
              if (!POD.test(k8sInfo.kubernetes.container_name)) {
                // use docker containerID-containerName
                k8sInfo.kubernetes.container_name = containerName
              }
              metric.filters = [
                // use  podName + namespace instead of "image name" as filter
                k8sInfo.kubernetes.pod_name + '_' + k8sInfo.kubernetes.namespace,
                // use kubernetes container name + uid to have a unique identifier
                k8sInfo.kubernetes.container_name + '_' + k8sInfo.kubernetes.uid
              ]
            }
            if (swarmInfo && swarmInfo.service_name) {
              metric.filters = [
                // aggregate by service instead of image_name
                swarmInfo.service_name,
                // use full container name
                containerName
              ]
            }

            SpmAgent.Logger.debug(agent.formatLine(metric))
            agent.addMetrics(metric)
          } else {
            var ccMetric = {name: stats.name, type: stats.type, value: stats.value, ts: new Date().getTime(), filters: ['no-filter'], sct: 'APP'}
            SpmAgent.Logger.debug(agent.formatLine(ccMetric))
            if (stats.name === 'count') {
              agent.addMetrics(ccMetric)
              if (containerCount === 0) {
                // init
                containerCount = stats.value
                global.spmSenderUrlParameters = '&containerCount=' + containerCount
              }
              containerCount = stats.value
              SpmAgent.Logger.debug('container count = ' + stats.value)
            }
            if (stats.name === 'totalcpu') {
              agent.addMetrics(ccMetric)
            }
          }
        }
        if (SpmAgent.Config.tokens.spm) {
          monitor(this.dockerListener)
        } else {
          console.log('SPM_TOKEN is missing, no metrics will be collected')
        }
      },
      stop: function () {
        // TODO: stop streaming docker stats, terminate timer
      },
      eventForwarder: new DockerEventForwarder()
    }
  )
  return da
}
setInterval(function () {
  global.spmSenderUrlParameters = '&containerCount=' + containerCount
}, 30000)

module.exports = dockerAgent
<commit_msg>fix k8s .id naming<commit_after>/**
 * @copyright Copyright (c) Sematext Group, Inc. - All Rights Reserved
 *
 * @licence SPM for Docker is free-to-use, proprietary software.
 * THIS IS PROPRIETARY SOURCE CODE OF Sematext Group, Inc. (Sematext)
 * This source code may not be copied, reverse engineered, or altered for any purpose.
 * This source code is to be used exclusively by users and customers of Sematext.
 * Please see the full license (found in LICENSE in this distribution) for details on its license and the licenses of its dependencies.
 */
'use strict'
var monitor = require('./dockerMonitor.js')
var Agent = require('spm-agent/lib/agent.js')
var SpmAgent = require('spm-agent')
var DockerEventForwarder = require('./dockerEventForwarder.js')
var containerCount = 0
var POD = /^POD$/
var ignoreImageVersion = !(process.env.IGNORE_IMAGE_VERSION === 'false')
global.spmSenderUrlParameters = '&containerCount=' + containerCount

function parseKubernetesInfo (containerName, k8sInfo) {
  // containers managed by Kubernetes have a prefix "k8s_", reference:
  // https://github.com/kubernetes/kubernetes/blob/f5d9c430e9168cf5c41197b8a4e457981cb031df/pkg/kubelet/dockertools/docker.go#L85
  if (!/k8s_/.test(containerName)) {
    return null
  }
  var fields = containerName.split('_')
  if (fields.length >= 4) {
    // example: k8s_sematext-agent.c56a873d_sematext-agent-qo2yf_default_e94b48c5-e63b-11e5-a8ec-0401b386ea01_8898bc93
    k8sInfo.kubernetes = {}
    k8sInfo.kubernetes.container_name = fields[1]
    k8sInfo.kubernetes.pod_name = fields[2]
    k8sInfo.kubernetes.namespace = fields[3]
    k8sInfo.kubernetes.uid = fields[4]
    return k8sInfo
  } else {
    return null
  }
}

function parseSwarmInfo (containerName, swarmInfo) {
  // Format: ID-swarmServiceName.ContainerNumber.TaskId
  if (!/\S{12}-\S+\.\d+\.\S+/.test(containerName)) {
    return null
  }
  var fields = containerName.split('.')
  if (fields.length === 3) {
    // remove ID with 13 characters
    if (fields[0]) {
      var idLength = containerName.indexOf('-')
      swarmInfo.service_name = fields[0].substring(idLength + 1, fields[0].length)
    }
    swarmInfo.container_number = fields[1]
    swarmInfo.task_id = fields[2]
    return swarmInfo
  } else {
    return null
  }
}

function dockerAgent () {
  var da = new Agent(
    {
      start: function (agent) {
        this.dockerListener = function (stats) {
          if (!stats) {
            return
          }
          if (stats.dockerId) {
            var containerName = stats.dockerId
            if (stats.name) {
              containerName = containerName + '-' + stats.name
            }
            var imageName = stats.image
            if (ignoreImageVersion && imageName) {
              imageName = imageName.split(':')[0]
            }
            var metric = {
              ts: new Date().getTime(),
              type: 'container',
              filters: [imageName, containerName],
              name: 'docker',
              value: stats.value,
              sct: 'APP'
            }
            var k8sInfo = parseKubernetesInfo(containerName, {})
            var swarmInfo = null
            if (!k8sInfo) {
              // check Docker Swarm
              swarmInfo = parseSwarmInfo(containerName, {})
            }

            if (k8sInfo && k8sInfo.kubernetes && k8sInfo.kubernetes.pod_name && k8sInfo.kubernetes.container_name && k8sInfo.kubernetes.uid) {
              // GKE does not report k8s.container_name, we find instead a static string "POD"
              if (POD.test(k8sInfo.kubernetes.container_name)) {
                // use docker containerID-containerName
                k8sInfo.kubernetes.container_name = containerName
              }
              metric.filters = [
                // use  podName + namespace instead of "image name" as filter
                k8sInfo.kubernetes.pod_name + '_' + k8sInfo.kubernetes.namespace,
                // use kubernetes container name + uid to have a unique identifier
                k8sInfo.kubernetes.container_name + '_' + k8sInfo.kubernetes.uid
              ]
            }
            if (swarmInfo && swarmInfo.service_name) {
              metric.filters = [
                // aggregate by service instead of image_name
                swarmInfo.service_name,
                // use full container name
                containerName
              ]
            }

            SpmAgent.Logger.debug(agent.formatLine(metric))
            agent.addMetrics(metric)
          } else {
            var ccMetric = {name: stats.name, type: stats.type, value: stats.value, ts: new Date().getTime(), filters: ['no-filter'], sct: 'APP'}
            SpmAgent.Logger.debug(agent.formatLine(ccMetric))
            if (stats.name === 'count') {
              agent.addMetrics(ccMetric)
              if (containerCount === 0) {
                // init
                containerCount = stats.value
                global.spmSenderUrlParameters = '&containerCount=' + containerCount
              }
              containerCount = stats.value
              SpmAgent.Logger.debug('container count = ' + stats.value)
            }
            if (stats.name === 'totalcpu') {
              agent.addMetrics(ccMetric)
            }
          }
        }
        if (SpmAgent.Config.tokens.spm) {
          monitor(this.dockerListener)
        } else {
          console.log('SPM_TOKEN is missing, no metrics will be collected')
        }
      },
      stop: function () {
        // TODO: stop streaming docker stats, terminate timer
      },
      eventForwarder: new DockerEventForwarder()
    }
  )
  return da
}
setInterval(function () {
  global.spmSenderUrlParameters = '&containerCount=' + containerCount
}, 30000)

module.exports = dockerAgent
<|endoftext|>


<commit_before>import describeModule    from 'ember-mocha/describe-module';
import describeComponent from 'ember-mocha/describe-component';
import describeModel     from 'ember-mocha/describe-model';
import setupTestFactory  from 'ember-mocha/setup-test-factory';
import { it }            from 'mocha';
import {
  setResolver,
  TestModule,
  TestModuleForModel,
  TestModuleForComponent,
} from 'ember-test-helpers';

const setupModuleTest = setupTestFactory(TestModule);
const setupComponentTest = setupTestFactory(TestModuleForComponent);
const setupModelTest = setupTestFactory(TestModuleForModel);

export {
  describeModule,
  describeComponent,
  describeModel,
  setupModuleTest,
  setupComponentTest,
  setupModelTest,
  it,
  setResolver
};
<commit_msg>Extract setupAcceptanceTest() function<commit_after>import describeModule    from 'ember-mocha/describe-module';
import describeComponent from 'ember-mocha/describe-component';
import describeModel     from 'ember-mocha/describe-model';
import setupTestFactory  from 'ember-mocha/setup-test-factory';
import { it }            from 'mocha';
import {
  setResolver,
  TestModule,
  TestModuleForModel,
  TestModuleForComponent,
  TestModuleForAcceptance
} from 'ember-test-helpers';

const setupModuleTest = setupTestFactory(TestModule);
const setupAcceptanceTest = setupTestFactory(TestModuleForAcceptance);
const setupComponentTest = setupTestFactory(TestModuleForComponent);
const setupModelTest = setupTestFactory(TestModuleForModel);

export {
  describeModule,
  describeComponent,
  describeModel,
  setupModuleTest,
  setupAcceptanceTest,
  setupComponentTest,
  setupModelTest,
  it,
  setResolver
};
<|endoftext|>


<commit_before>
var contexts = require('./contexts');

var methods = {
    number: {
        to_s: function () { return this.toString(); }
    },
    string: {
        to_i: function () { return parseInt(this); }
    }
};

function isFalse(value) {
    return value === null || value === false || value === undefined;
}

function getInstanceMethod(obj, fnname) {
    return methods[typeof obj][fnname];
}

function ClassClass(cls) {
    var instanceMethods = {
        'new': function () {
            var newobj = new Object();
            newobj.$class = cls;
            return newobj;
        }
    };

    this.getInstanceMethod = function (name) {
        return instanceMethods[name];
    };
}

function ModuleClass(cls) {
    var instanceMethods = { };

    this.getInstanceMethod = function (name) {
        return instanceMethods[name];
    };
}

function Class(name, superclass) {
    var instanceMethods = { };

    this.$class = new ClassClass(this);
    this.$superclass = superclass;
    this.$constants = contexts.createContext();

    this.getName = function () { return name; };

    this.getInstanceMethod = function (name) {
        var method = instanceMethods[name];

        if (!method && superclass)
            return superclass.getInstanceMethod(name);

        return method;
    };

    this.setInstanceMethod = function (name, method) {
        instanceMethods[name] = method;
    }
}

function Module(name) {
    var instanceMethods = { };

    this.$class = new ModuleClass(this);
    this.$constants = contexts.createContext();

    this.getName = function () { return name; };

    this.getInstanceMethod = function (name) {
        return instanceMethods[name];
    };

    this.setInstanceMethod = function (name, method) {
        instanceMethods[name] = method;
    }
}

function ClassExpression(name, supername, expr) {
    if (!expr) {
        expr = supername;
        supername = null;
    }

    this.getName = function () { return name; }

    this.getSuperName = function () { return supername; }

    this.evaluate = function (context) {
        var supercls = null;

        if (supername)
            supercls = context.getValue(supername);

        var cls = new Class(name, supercls);
        var newcontext = contexts.createContext(context);
        newcontext.$module = cls;
        expr.evaluate(newcontext);
        context.setLocalValue(name, cls);
        return cls;
    }
}

function ModuleExpression(name, expr) {
    this.getName = function () { return name; }

    this.evaluate = function (context) {
        var mod = new Module(name);
        var newcontext = contexts.createContext(context);
        newcontext.$module = mod;
        expr.evaluate(newcontext);
        context.setLocalValue(name, mod);
        return mod;
    }
}

function JavaScriptNamespaceExpression() {
    var value;

    if (typeof global != 'undefined')
        value = global;
    else if (typeof window != 'undefined')
        value = window;

    this.evaluate = function (context) {
        return value;
    }
}

function JavaScriptQualifiedNameExpression(expr, name) {
    this.evaluate = function (context) {
        return expr.evaluate(context)[name];
    }

    this.getExpression = function () { return expr; }

    this.getName = function () { return name; }
}

function JavaScriptCallExpression(expr, exprs) {
    this.evaluate = function (context) {
        var obj = expr.getExpression().evaluate(context);
        var name = expr.getName();
        var args = [];

        exprs.forEach(function (expr) {
            args.push(expr.evaluate(context));
        });

        return obj[name].apply(obj, args);
    }
}

function DefExpression(name, parnames, expr) {
    this.evaluate = function (context) {
        var fun = function() {
            var newcontext = contexts.createContext(context);
            newcontext.$self = this;
            for (n in parnames)
                newcontext.setLocalValue(parnames[n], arguments[n]);
            return expr.evaluate(newcontext);
        };
        if (context.$module)
            context.$module.setInstanceMethod(name, fun);
        else
            context.setLocalValue(name, fun);
        return fun;
    }
}

function CallExpression(name, exprs) {
    this.evaluate = function (context) {
        var fun = context.getValue(name);
        var args = [];

        exprs.forEach(function (expr) {
            args.push(expr.evaluate(context));
        });

        return fun.apply(null, args);
    }
}

function ArrayExpression(exprs) {
    this.evaluate = function (context) {
        var array = [];

        exprs.forEach(function (expr) {
            array.push(expr.evaluate(context));
        });

        return array;
    }
}

function IndexedExpression(expr, exprs) {
    this.evaluate = function (context) {
        var value = expr.evaluate(context);

        exprs.forEach(function (expr) {
            value = value[expr.evaluate(context)];
        });

        return value;
    }
}

function MakeQualifiedCallExpression(expr, exprs) {
    if (exprs == null && (expr instanceof JavaScriptQualifiedNameExpression || expr instanceof JavaScriptNamespaceExpression))
        return expr;

    if (exprs == null)
        exprs = [];

    if (expr instanceof JavaScriptQualifiedNameExpression || expr instanceof JavaScriptNamespaceExpression)
        return new JavaScriptCallExpression(expr, exprs);

    return new QualifiedCallExpression(expr, exprs);
}

function QualifiedCallExpression(expr, exprs) {
    this.evaluate = function (context) {
        var obj = expr.getTarget().evaluate(context);
        var fun;
        var fnname = expr.getName();

        if (obj.$class)
            fun = obj.$class.getInstanceMethod(fnname);
        else
            fun = getInstanceMethod(obj, fnname);

        var args = [];

        exprs.forEach(function (expr) {
            args.push(expr.evaluate(context));
        });

        return fun.apply(obj, args);
    }
}

function IfExpression(condition, thenexpr, elseexpr) {
    this.evaluate = function (context) {
        var value = condition.evaluate(context);

        if (isFalse(value))
            if (elseexpr)
                return elseexpr.evaluate(context);
            else
                return null;

        return thenexpr.evaluate(context);
    };
}

function UnlessExpression(condition, thenexpr, elseexpr) {
    this.evaluate = function (context) {
        var value = condition.evaluate(context);

        if (!isFalse(value))
            if (elseexpr)
                return elseexpr.evaluate(context);
            else
                return null;

        return thenexpr.evaluate(context);
    };
}

function WhileExpression(condition, expr) {
    this.evaluate = function (context) {
        while (true) {
            var value = condition.evaluate(context);

            if (isFalse(value))
                return null;

            expr.evaluate(context);
        }
    };
}

function UntilExpression(condition, expr) {
    this.evaluate = function (context) {
        while (true) {
            var value = condition.evaluate(context);

            if (!isFalse(value))
                return null;

            expr.evaluate(context);
        }
    };
}

function CompositeExpression(exprs) {
    this.evaluate = function (context) {
        var result = null;

        exprs.forEach(function (expr) {
            result = expr.evaluate(context);
        });

        return result;
    };
}

function AssignmentExpression(leftvalue, expr) {
    this.evaluate = function (context) {
        var value = expr.evaluate(context);
        leftvalue.setValue(context, value);
        return value;
    };

    this.getName = function () { return name; };
}

function MakeQualifiedNameExpression(target, name) {
    if (target instanceof JavaScriptNamespaceExpression ||
        target instanceof JavaScriptQualifiedNameExpression)
        return new JavaScriptQualifiedNameExpression(target, name);

    return new QualifiedNameExpression(target, name);
}

function QualifiedNameExpression(target, name) {
    this.evaluate = function (context) {
        var obj = target.evaluate(context);

        if (obj.$class)
            return obj.$class.getInstanceMethod(name);

        return obj[name];
    };

    this.getName = function () { return name; };

    this.getTarget = function () { return target; };
}

function MakeNameExpression(name) {
    if (name == 'js')
        return new JavaScriptNamespaceExpression();
    return new NameExpression(name);
}

function InstanceVariableExpression(name) {
    this.evaluate = function (context) {
        if (!context.$self.$vars)
            return null;

        return context.$self.$vars[name];
    };

    this.getName = function () { return name; };

    this.setValue = function (context, value) {
        if (!context.$self.$vars)
            context.$self.$vars = { };

        context.$self.$vars[name] = value;
    }
}

function ClassVariableExpression(name) {
    this.evaluate = function (context) {
        if (!context.$self.$class.$vars)
            return null;

        return context.$self.$class.$vars[name];
    };

    this.getName = function () { return name; };

    this.setValue = function (context, value) {
        if (!context.$self.$class.$vars)
            context.$self.$class.$vars = { };

        context.$self.$class.$vars[name] = value;
    }
}

function NameExpression(name) {
    this.evaluate = function (context) {
        var value = context.getValue(name);

        if (typeof value == 'function')
            return value();

        return value;
    };

    this.getName = function () { return name; };

    this.setValue = function (context, value) {
        context.setLocalValue(name, value);
    }
}

function ConstantExpression(value) {
    this.evaluate = function () {
        return value;
    };
}

function IntegerExpression(text) {
    var value = parseInt(text);

    this.evaluate = function () {
        return value;
    };
}

function EqualExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) == right.evaluate(context);
    };
}

function NotEqualExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) != right.evaluate(context);
    };
}

function LessExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) < right.evaluate(context);
    };
}

function GreaterExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) > right.evaluate(context);
    };
}

function LessEqualExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) <= right.evaluate(context);
    };
}

function GreaterEqualExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) >= right.evaluate(context);
    };
}

function AddExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) + right.evaluate(context);
    };
}

function SubtractExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) - right.evaluate(context);
    };
}

function MultiplyExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) * right.evaluate(context);
    };
}

function DivideExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) / right.evaluate(context);
    };
}

module.exports = {
    ClassExpression: ClassExpression,
    ModuleExpression: ModuleExpression,
    JavaScriptNamespaceExpression: JavaScriptNamespaceExpression,
    JavaScriptQualifiedNameExpression: JavaScriptQualifiedNameExpression,
    DefExpression: DefExpression,
    CallExpression: CallExpression,
    ArrayExpression: ArrayExpression,
    IndexedExpression: IndexedExpression,
    MakeQualifiedCallExpression: MakeQualifiedCallExpression,
    QualifiedCallExpression: QualifiedCallExpression,
    IfExpression: IfExpression,
    UnlessExpression: UnlessExpression,
    WhileExpression: WhileExpression,
    UntilExpression: UntilExpression,
    CompositeExpression: CompositeExpression,
    AssignmentExpression: AssignmentExpression,
    MakeQualifiedNameExpression: MakeQualifiedNameExpression,
    QualifiedNameExpression: QualifiedNameExpression,
    MakeNameExpression: MakeNameExpression,
    InstanceVariableExpression: InstanceVariableExpression,
    ClassVariableExpression: ClassVariableExpression,
    NameExpression: NameExpression,
    ConstantExpression: ConstantExpression,
    IntegerExpression: IntegerExpression,
    EqualExpression: EqualExpression,
    NotEqualExpression: NotEqualExpression,
    LessExpression: LessExpression,
    GreaterExpression: GreaterExpression,
    LessEqualExpression: LessEqualExpression,
    GreaterEqualExpression: GreaterEqualExpression,
    AddExpression: AddExpression,
    SubtractExpression: SubtractExpression,
    MultiplyExpression: MultiplyExpression,
    DivideExpression: DivideExpression
};<commit_msg>Refactor get instance method using inheritance<commit_after>
var contexts = require('./contexts');

var methods = {
    number: {
        to_s: function () { return this.toString(); }
    },
    string: {
        to_i: function () { return parseInt(this); }
    }
};

function isFalse(value) {
    return value === null || value === false || value === undefined;
}

function getInstanceMethod(obj, fnname) {
    return methods[typeof obj][fnname];
}

function ClassClass(cls) {
    var instanceMethods = {
        'new': function () {
            var newobj = new Object();
            newobj.$class = cls;
            return newobj;
        }
    };

    this.getInstanceMethod = function (name) {
        return instanceMethods[name];
    };
}

function ModuleClass(cls) {
    var instanceMethods = { };

    this.getInstanceMethod = function (name) {
        return instanceMethods[name];
    };
}

function Class(name, superclass) {
    var instanceMethods = { };

    this.$class = new ClassClass(this);
    this.$superclass = superclass;
    this.$constants = contexts.createContext();

    this.getName = function () { return name; };

    this.getInstanceMethod = function (name) {
        var method = instanceMethods[name];

        if (!method && this.$superclass)
            return this.$superclass.getInstanceMethod(name);

        return method;
    };

    this.setInstanceMethod = function (name, method) {
        instanceMethods[name] = method;
    }
}

function Module(name) {
    var instanceMethods = { };

    this.$class = new ModuleClass(this);
    this.$constants = contexts.createContext();

    this.getName = function () { return name; };

    this.getInstanceMethod = function (name) {
        return instanceMethods[name];
    };

    this.setInstanceMethod = function (name, method) {
        instanceMethods[name] = method;
    }
}

function ClassExpression(name, supername, expr) {
    if (!expr) {
        expr = supername;
        supername = null;
    }

    this.getName = function () { return name; }

    this.getSuperName = function () { return supername; }

    this.evaluate = function (context) {
        var supercls = null;

        if (supername)
            supercls = context.getValue(supername);

        var cls = new Class(name, supercls);
        var newcontext = contexts.createContext(context);
        newcontext.$module = cls;
        expr.evaluate(newcontext);
        context.setLocalValue(name, cls);
        return cls;
    }
}

function ModuleExpression(name, expr) {
    this.getName = function () { return name; }

    this.evaluate = function (context) {
        var mod = new Module(name);
        var newcontext = contexts.createContext(context);
        newcontext.$module = mod;
        expr.evaluate(newcontext);
        context.setLocalValue(name, mod);
        return mod;
    }
}

function JavaScriptNamespaceExpression() {
    var value;

    if (typeof global != 'undefined')
        value = global;
    else if (typeof window != 'undefined')
        value = window;

    this.evaluate = function (context) {
        return value;
    }
}

function JavaScriptQualifiedNameExpression(expr, name) {
    this.evaluate = function (context) {
        return expr.evaluate(context)[name];
    }

    this.getExpression = function () { return expr; }

    this.getName = function () { return name; }
}

function JavaScriptCallExpression(expr, exprs) {
    this.evaluate = function (context) {
        var obj = expr.getExpression().evaluate(context);
        var name = expr.getName();
        var args = [];

        exprs.forEach(function (expr) {
            args.push(expr.evaluate(context));
        });

        return obj[name].apply(obj, args);
    }
}

function DefExpression(name, parnames, expr) {
    this.evaluate = function (context) {
        var fun = function() {
            var newcontext = contexts.createContext(context);
            newcontext.$self = this;
            for (n in parnames)
                newcontext.setLocalValue(parnames[n], arguments[n]);
            return expr.evaluate(newcontext);
        };
        if (context.$module)
            context.$module.setInstanceMethod(name, fun);
        else
            context.setLocalValue(name, fun);
        return fun;
    }
}

function CallExpression(name, exprs) {
    this.evaluate = function (context) {
        var fun = context.getValue(name);
        var args = [];

        exprs.forEach(function (expr) {
            args.push(expr.evaluate(context));
        });

        return fun.apply(null, args);
    }
}

function ArrayExpression(exprs) {
    this.evaluate = function (context) {
        var array = [];

        exprs.forEach(function (expr) {
            array.push(expr.evaluate(context));
        });

        return array;
    }
}

function IndexedExpression(expr, exprs) {
    this.evaluate = function (context) {
        var value = expr.evaluate(context);

        exprs.forEach(function (expr) {
            value = value[expr.evaluate(context)];
        });

        return value;
    }
}

function MakeQualifiedCallExpression(expr, exprs) {
    if (exprs == null && (expr instanceof JavaScriptQualifiedNameExpression || expr instanceof JavaScriptNamespaceExpression))
        return expr;

    if (exprs == null)
        exprs = [];

    if (expr instanceof JavaScriptQualifiedNameExpression || expr instanceof JavaScriptNamespaceExpression)
        return new JavaScriptCallExpression(expr, exprs);

    return new QualifiedCallExpression(expr, exprs);
}

function QualifiedCallExpression(expr, exprs) {
    this.evaluate = function (context) {
        var obj = expr.getTarget().evaluate(context);
        var fun;
        var fnname = expr.getName();

        if (obj.$class)
            fun = obj.$class.getInstanceMethod(fnname);
        else
            fun = getInstanceMethod(obj, fnname);

        var args = [];

        exprs.forEach(function (expr) {
            args.push(expr.evaluate(context));
        });

        return fun.apply(obj, args);
    }
}

function IfExpression(condition, thenexpr, elseexpr) {
    this.evaluate = function (context) {
        var value = condition.evaluate(context);

        if (isFalse(value))
            if (elseexpr)
                return elseexpr.evaluate(context);
            else
                return null;

        return thenexpr.evaluate(context);
    };
}

function UnlessExpression(condition, thenexpr, elseexpr) {
    this.evaluate = function (context) {
        var value = condition.evaluate(context);

        if (!isFalse(value))
            if (elseexpr)
                return elseexpr.evaluate(context);
            else
                return null;

        return thenexpr.evaluate(context);
    };
}

function WhileExpression(condition, expr) {
    this.evaluate = function (context) {
        while (true) {
            var value = condition.evaluate(context);

            if (isFalse(value))
                return null;

            expr.evaluate(context);
        }
    };
}

function UntilExpression(condition, expr) {
    this.evaluate = function (context) {
        while (true) {
            var value = condition.evaluate(context);

            if (!isFalse(value))
                return null;

            expr.evaluate(context);
        }
    };
}

function CompositeExpression(exprs) {
    this.evaluate = function (context) {
        var result = null;

        exprs.forEach(function (expr) {
            result = expr.evaluate(context);
        });

        return result;
    };
}

function AssignmentExpression(leftvalue, expr) {
    this.evaluate = function (context) {
        var value = expr.evaluate(context);
        leftvalue.setValue(context, value);
        return value;
    };

    this.getName = function () { return name; };
}

function MakeQualifiedNameExpression(target, name) {
    if (target instanceof JavaScriptNamespaceExpression ||
        target instanceof JavaScriptQualifiedNameExpression)
        return new JavaScriptQualifiedNameExpression(target, name);

    return new QualifiedNameExpression(target, name);
}

function QualifiedNameExpression(target, name) {
    this.evaluate = function (context) {
        var obj = target.evaluate(context);

        if (obj.$class)
            return obj.$class.getInstanceMethod(name);

        return obj[name];
    };

    this.getName = function () { return name; };

    this.getTarget = function () { return target; };
}

function MakeNameExpression(name) {
    if (name == 'js')
        return new JavaScriptNamespaceExpression();
    return new NameExpression(name);
}

function InstanceVariableExpression(name) {
    this.evaluate = function (context) {
        if (!context.$self.$vars)
            return null;

        return context.$self.$vars[name];
    };

    this.getName = function () { return name; };

    this.setValue = function (context, value) {
        if (!context.$self.$vars)
            context.$self.$vars = { };

        context.$self.$vars[name] = value;
    }
}

function ClassVariableExpression(name) {
    this.evaluate = function (context) {
        if (!context.$self.$class.$vars)
            return null;

        return context.$self.$class.$vars[name];
    };

    this.getName = function () { return name; };

    this.setValue = function (context, value) {
        if (!context.$self.$class.$vars)
            context.$self.$class.$vars = { };

        context.$self.$class.$vars[name] = value;
    }
}

function NameExpression(name) {
    this.evaluate = function (context) {
        var value = context.getValue(name);

        if (typeof value == 'function')
            return value();

        return value;
    };

    this.getName = function () { return name; };

    this.setValue = function (context, value) {
        context.setLocalValue(name, value);
    }
}

function ConstantExpression(value) {
    this.evaluate = function () {
        return value;
    };
}

function IntegerExpression(text) {
    var value = parseInt(text);

    this.evaluate = function () {
        return value;
    };
}

function EqualExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) == right.evaluate(context);
    };
}

function NotEqualExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) != right.evaluate(context);
    };
}

function LessExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) < right.evaluate(context);
    };
}

function GreaterExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) > right.evaluate(context);
    };
}

function LessEqualExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) <= right.evaluate(context);
    };
}

function GreaterEqualExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) >= right.evaluate(context);
    };
}

function AddExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) + right.evaluate(context);
    };
}

function SubtractExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) - right.evaluate(context);
    };
}

function MultiplyExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) * right.evaluate(context);
    };
}

function DivideExpression(left, right) {
    this.evaluate = function (context) {
        return left.evaluate(context) / right.evaluate(context);
    };
}

module.exports = {
    ClassExpression: ClassExpression,
    ModuleExpression: ModuleExpression,
    JavaScriptNamespaceExpression: JavaScriptNamespaceExpression,
    JavaScriptQualifiedNameExpression: JavaScriptQualifiedNameExpression,
    DefExpression: DefExpression,
    CallExpression: CallExpression,
    ArrayExpression: ArrayExpression,
    IndexedExpression: IndexedExpression,
    MakeQualifiedCallExpression: MakeQualifiedCallExpression,
    QualifiedCallExpression: QualifiedCallExpression,
    IfExpression: IfExpression,
    UnlessExpression: UnlessExpression,
    WhileExpression: WhileExpression,
    UntilExpression: UntilExpression,
    CompositeExpression: CompositeExpression,
    AssignmentExpression: AssignmentExpression,
    MakeQualifiedNameExpression: MakeQualifiedNameExpression,
    QualifiedNameExpression: QualifiedNameExpression,
    MakeNameExpression: MakeNameExpression,
    InstanceVariableExpression: InstanceVariableExpression,
    ClassVariableExpression: ClassVariableExpression,
    NameExpression: NameExpression,
    ConstantExpression: ConstantExpression,
    IntegerExpression: IntegerExpression,
    EqualExpression: EqualExpression,
    NotEqualExpression: NotEqualExpression,
    LessExpression: LessExpression,
    GreaterExpression: GreaterExpression,
    LessEqualExpression: LessEqualExpression,
    GreaterEqualExpression: GreaterEqualExpression,
    AddExpression: AddExpression,
    SubtractExpression: SubtractExpression,
    MultiplyExpression: MultiplyExpression,
    DivideExpression: DivideExpression
};<|endoftext|>


<commit_before>const { existsSync } = require('fs');
const { Mixin } = require('hops-mixin');
const strip = require('strip-indent');

class GraphQLMixin extends Mixin {
  registerCommands(yargs) {
    yargs.command('graphql', 'Execute GraphQL specific tasks', yargs =>
      yargs
        .usage('Usage: hops graphql <command>')
        .command({
          command: 'introspect',
          describe: 'Fetches GraphQL schema information for introspection',
          builder: {
            header: {
              alias: 'H',
              type: 'array',
              default: [],
              describe: strip(`
                Additional HTTP headers to be used when executing the schema
                introspection on the remote server. Specify this multiple
                times to add more headers.\nFormat: "Header: Value"
              `),
            },
          },
          handler: argv => {
            require('./lib/fragments')({
              graphqlUri: this.config.graphqlUri,
              schemaFile: this.config.graphqlSchemaFile,
              fragmentsFile: this.config.fragmentsFile,
              headers: argv.header,
            })
              .then(() => {
                if (typeof this.getLogger === 'function') {
                  this.getLogger().info('Fetched and saved GraphQL fragments');
                }
              })
              .catch(err => {
                if (typeof this.getLogger === 'function') {
                  this.getLogger().error('Could not fetch GraphQL fragments:');
                  this.getLogger().error(err);
                }
              });
          },
        })
        .help('help')
        .alias('h', 'help')
        .demandCommand()
    );
  }

  handleArguments(argv) {
    this.options = { ...this.options, ...argv };
  }

  diagnose({ detectDuplicatePackages }) {
    detectDuplicatePackages('graphql');
    if (!existsSync(this.config.fragmentsFile)) {
      return [
        `Could not find a graphql introspection query result at "${this.config.fragmentsFile}".`,
        'You might need to execute "hops graphql introspect"',
      ];
    }
  }
}

module.exports = GraphQLMixin;
<commit_msg>refactor(react-apollo): add graphql-tag loader<commit_after>const { existsSync } = require('fs');
const { Mixin } = require('hops-mixin');
const strip = require('strip-indent');

class GraphQLMixin extends Mixin {
  configureBuild(webpackConfig, loaderConfigs) {
    const { allLoaderConfigs } = loaderConfigs;

    allLoaderConfigs.splice(allLoaderConfigs.length - 1, 0, {
      test: /\.(graphql|gql)$/,
      loader: 'graphql-tag/loader',
    });
  }

  registerCommands(yargs) {
    yargs.command('graphql', 'Execute GraphQL specific tasks', yargs =>
      yargs
        .usage('Usage: hops graphql <command>')
        .command({
          command: 'introspect',
          describe: 'Fetches GraphQL schema information for introspection',
          builder: {
            header: {
              alias: 'H',
              type: 'array',
              default: [],
              describe: strip(`
                Additional HTTP headers to be used when executing the schema
                introspection on the remote server. Specify this multiple
                times to add more headers.\nFormat: "Header: Value"
              `),
            },
          },
          handler: argv => {
            require('./lib/fragments')({
              graphqlUri: this.config.graphqlUri,
              schemaFile: this.config.graphqlSchemaFile,
              fragmentsFile: this.config.fragmentsFile,
              headers: argv.header,
            })
              .then(() => {
                if (typeof this.getLogger === 'function') {
                  this.getLogger().info('Fetched and saved GraphQL fragments');
                }
              })
              .catch(err => {
                if (typeof this.getLogger === 'function') {
                  this.getLogger().error('Could not fetch GraphQL fragments:');
                  this.getLogger().error(err);
                }
              });
          },
        })
        .help('help')
        .alias('h', 'help')
        .demandCommand()
    );
  }

  handleArguments(argv) {
    this.options = { ...this.options, ...argv };
  }

  diagnose({ detectDuplicatePackages }) {
    detectDuplicatePackages('graphql');
    if (!existsSync(this.config.fragmentsFile)) {
      return [
        `Could not find a graphql introspection query result at "${this.config.fragmentsFile}".`,
        'You might need to execute "hops graphql introspect"',
      ];
    }
  }
}

module.exports = GraphQLMixin;
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the MIT license
 * If a copy of the MIT license was not distributed with this file, you can
 * obtain one at https://raw.github.com/mozilla/butter/master/LICENSE */

"use strict";

define( [ "util/uri" ],
  function( URI ) {

  var REGEX_MAP = {
        youtube: /(?:https?:\/\/www\.|https?:\/\/|www\.|\.|^)youtu/,
        vimeo: /https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/,
        soundcloud: /(?:https?:\/\/www\.|https?:\/\/|www\.|\.|^)(soundcloud)/,
        // supports #t=<start>,<duration>
        // where start or duration can be: X, X.X or XX:XX
        "null": /^\s*#t=(?:\d*(?:(?:\.|\:)?\d+)?),?(\d+(?:(?:\.|\:)\d+)?)\s*$/
      },
      YOUTUBE_EMBED_DISABLED = "Embedding of this YouTube video is disabled",
      SOUNDCLOUD_EMBED_DISABLED = "Embedding of this SoundCloud video is disabled";

  return {
    checkUrl: function( url ) {
      for ( var type in REGEX_MAP ) {
        if ( REGEX_MAP.hasOwnProperty( type ) ) {
          if ( REGEX_MAP[ type ].test( url ) ) {
            return type;
          }
        }
      }
      return "html5";
    },
    getMetaData: function( baseUrl, successCallback, errorCallback ) {
      var id,
          parsedUri,
          splitUriDirectory,
          xhrURL,
          type = this.checkUrl( baseUrl ),
          videoElem;

      successCallback = successCallback || function(){};
      errorCallback = errorCallback || function(){};

      if ( type === "youtube" ) {
        parsedUri = URI.parse( baseUrl );
        // youtube id can either be a query under v, example:
        // http://www.youtube.com/watch?v=p_7Qi3mprKQ
        // Or at the end of the url like this:
        // http://youtu.be/p_7Qi3mprKQ
        id = parsedUri.queryKey.v || parsedUri.directory.replace( "/", "" );
        if ( !id ) {
          return;
        }

        xhrURL = "https://gdata.youtube.com/feeds/api/videos/" + id + "?v=2&alt=jsonc&callback=?";
        Popcorn.getJSONP( xhrURL, function( resp ) {
          var respData = resp.data,
              from = parsedUri.queryKey.t,
              popcorn,
              div = document.createElement( "div" ),
              source;

          div.style.height = "400px";
          div.style.width = "400px";
          div.style.left = "-400px";
          div.style.position = "absolute";

          document.body.appendChild( div );

          if ( !respData ) {
            return;
          }

          if ( respData.accessControl.embed === "denied" ) {
            errorCallback( YOUTUBE_EMBED_DISABLED );
            return;
          }

          function readyEvent() {
            popcorn.off( "loadedmetadata", readyEvent );
            document.body.removeChild( div );
            popcorn.destroy();

            successCallback({
              source: source,
              title: respData.title,
              type: type,
              thumbnail: respData.thumbnail.hqDefault,
              author: respData.uploader,
              duration: popcorn.duration(),
              from: from
            });
          }

          if ( from ) {
            from = from.replace( /(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?/, function( all, hours, minutes, seconds ) {
              // Make sure we have real zeros
              hours = hours | 0; // bit-wise OR
              minutes = minutes | 0; // bit-wise OR
              seconds = seconds | 0; // bit-wise OR
              return ( +seconds + ( ( ( hours * 60 ) + minutes ) * 60 ) );
            });
          }

          source = "http://www.youtube.com/watch?v=" + id;
          popcorn = Popcorn.smart( div, source );
          if ( popcorn.media.readyState >= 1 ) {
            readyEvent();
          } else {
            popcorn.on( "loadedmetadata", readyEvent );
          }
        });
      } else if ( type === "soundcloud" ) {
        parsedUri = URI.parse( baseUrl );
        splitUriDirectory = parsedUri.directory.split( "/" );
        id = splitUriDirectory[ splitUriDirectory.length - 1 ];
        xhrURL = "https://api.soundcloud.com/tracks/" + id + ".json?callback=?&client_id=PRaNFlda6Bhf5utPjUsptg";
        Popcorn.getJSONP( xhrURL, function( respData ) {
          if ( !respData ) {
            return;
          }

          if ( respData.sharing === "private" || respData.embeddable_by === "none" ) {
            errorCallback( SOUNDCLOUD_EMBED_DISABLED );
            return;
          }
          successCallback({
            source: baseUrl,
            type: type,
            thumbnail: respData.artwork_url || "../../resources/icons/soundcloud-small.png",
            duration: respData.duration / 1000,
            title: respData.title,
            hidden: true
          });
        });
      } else if ( type === "vimeo" ) {
        parsedUri = URI.parse( baseUrl );
        splitUriDirectory = parsedUri.directory.split( "/" );
        id = splitUriDirectory[ splitUriDirectory.length - 1 ];
        xhrURL = "https://vimeo.com/api/v2/video/" + id + ".json?callback=?";
        Popcorn.getJSONP( xhrURL, function( respData ) {
          respData = respData && respData[ 0 ];
          if ( !respData ) {
            return;
          }
          successCallback({
            source: baseUrl,
            type: type,
            thumbnail: respData.thumbnail_small,
            duration: respData.duration,
            title: respData.title
          });
        });
      } else if ( type === "null" ) {
        successCallback({
          source: baseUrl,
          type: type,
          title: baseUrl,
          duration: REGEX_MAP[ "null" ].exec( baseUrl )[ 1 ]
        });
      } else if ( type === "html5" ) {
        videoElem = document.createElement( "video" );
        videoElem.addEventListener( "loadedmetadata", function() {
          successCallback ({
            source: baseUrl,
            type: type,
            title: baseUrl.substring( baseUrl.lastIndexOf( "/" ) + 1 ),
            thumbnail: videoElem,
            duration: videoElem.duration
          });
        }, false );
        videoElem.src = URI.makeUnique( baseUrl ).toString();
      }
    }
  };
});
<commit_msg>[3454] Non-embeddable SoundCloud sources say Embedding of this SoundCloud video<commit_after>/* This Source Code Form is subject to the terms of the MIT license
 * If a copy of the MIT license was not distributed with this file, you can
 * obtain one at https://raw.github.com/mozilla/butter/master/LICENSE */

"use strict";

define( [ "util/uri" ],
  function( URI ) {

  var REGEX_MAP = {
        youtube: /(?:https?:\/\/www\.|https?:\/\/|www\.|\.|^)youtu/,
        vimeo: /https?:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/,
        soundcloud: /(?:https?:\/\/www\.|https?:\/\/|www\.|\.|^)(soundcloud)/,
        // supports #t=<start>,<duration>
        // where start or duration can be: X, X.X or XX:XX
        "null": /^\s*#t=(?:\d*(?:(?:\.|\:)?\d+)?),?(\d+(?:(?:\.|\:)\d+)?)\s*$/
      },
      YOUTUBE_EMBED_DISABLED = "Embedding of this YouTube video is disabled",
      SOUNDCLOUD_EMBED_DISABLED = "Embedding of this SoundCloud audio source is disabled";

  return {
    checkUrl: function( url ) {
      for ( var type in REGEX_MAP ) {
        if ( REGEX_MAP.hasOwnProperty( type ) ) {
          if ( REGEX_MAP[ type ].test( url ) ) {
            return type;
          }
        }
      }
      return "html5";
    },
    getMetaData: function( baseUrl, successCallback, errorCallback ) {
      var id,
          parsedUri,
          splitUriDirectory,
          xhrURL,
          type = this.checkUrl( baseUrl ),
          videoElem;

      successCallback = successCallback || function(){};
      errorCallback = errorCallback || function(){};

      if ( type === "youtube" ) {
        parsedUri = URI.parse( baseUrl );
        // youtube id can either be a query under v, example:
        // http://www.youtube.com/watch?v=p_7Qi3mprKQ
        // Or at the end of the url like this:
        // http://youtu.be/p_7Qi3mprKQ
        id = parsedUri.queryKey.v || parsedUri.directory.replace( "/", "" );
        if ( !id ) {
          return;
        }

        xhrURL = "https://gdata.youtube.com/feeds/api/videos/" + id + "?v=2&alt=jsonc&callback=?";
        Popcorn.getJSONP( xhrURL, function( resp ) {
          var respData = resp.data,
              from = parsedUri.queryKey.t,
              popcorn,
              div = document.createElement( "div" ),
              source;

          div.style.height = "400px";
          div.style.width = "400px";
          div.style.left = "-400px";
          div.style.position = "absolute";

          document.body.appendChild( div );

          if ( !respData ) {
            return;
          }

          if ( respData.accessControl.embed === "denied" ) {
            errorCallback( YOUTUBE_EMBED_DISABLED );
            return;
          }

          function readyEvent() {
            popcorn.off( "loadedmetadata", readyEvent );
            document.body.removeChild( div );
            popcorn.destroy();

            successCallback({
              source: source,
              title: respData.title,
              type: type,
              thumbnail: respData.thumbnail.hqDefault,
              author: respData.uploader,
              duration: popcorn.duration(),
              from: from
            });
          }

          if ( from ) {
            from = from.replace( /(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?/, function( all, hours, minutes, seconds ) {
              // Make sure we have real zeros
              hours = hours | 0; // bit-wise OR
              minutes = minutes | 0; // bit-wise OR
              seconds = seconds | 0; // bit-wise OR
              return ( +seconds + ( ( ( hours * 60 ) + minutes ) * 60 ) );
            });
          }

          source = "http://www.youtube.com/watch?v=" + id;
          popcorn = Popcorn.smart( div, source );
          if ( popcorn.media.readyState >= 1 ) {
            readyEvent();
          } else {
            popcorn.on( "loadedmetadata", readyEvent );
          }
        });
      } else if ( type === "soundcloud" ) {
        parsedUri = URI.parse( baseUrl );
        splitUriDirectory = parsedUri.directory.split( "/" );
        id = splitUriDirectory[ splitUriDirectory.length - 1 ];
        xhrURL = "https://api.soundcloud.com/tracks/" + id + ".json?callback=?&client_id=PRaNFlda6Bhf5utPjUsptg";
        Popcorn.getJSONP( xhrURL, function( respData ) {
          if ( !respData ) {
            return;
          }

          if ( respData.sharing === "private" || respData.embeddable_by === "none" ) {
            errorCallback( SOUNDCLOUD_EMBED_DISABLED );
            return;
          }
          successCallback({
            source: baseUrl,
            type: type,
            thumbnail: respData.artwork_url || "../../resources/icons/soundcloud-small.png",
            duration: respData.duration / 1000,
            title: respData.title,
            hidden: true
          });
        });
      } else if ( type === "vimeo" ) {
        parsedUri = URI.parse( baseUrl );
        splitUriDirectory = parsedUri.directory.split( "/" );
        id = splitUriDirectory[ splitUriDirectory.length - 1 ];
        xhrURL = "https://vimeo.com/api/v2/video/" + id + ".json?callback=?";
        Popcorn.getJSONP( xhrURL, function( respData ) {
          respData = respData && respData[ 0 ];
          if ( !respData ) {
            return;
          }
          successCallback({
            source: baseUrl,
            type: type,
            thumbnail: respData.thumbnail_small,
            duration: respData.duration,
            title: respData.title
          });
        });
      } else if ( type === "null" ) {
        successCallback({
          source: baseUrl,
          type: type,
          title: baseUrl,
          duration: REGEX_MAP[ "null" ].exec( baseUrl )[ 1 ]
        });
      } else if ( type === "html5" ) {
        videoElem = document.createElement( "video" );
        videoElem.addEventListener( "loadedmetadata", function() {
          successCallback ({
            source: baseUrl,
            type: type,
            title: baseUrl.substring( baseUrl.lastIndexOf( "/" ) + 1 ),
            thumbnail: videoElem,
            duration: videoElem.duration
          });
        }, false );
        videoElem.src = URI.makeUnique( baseUrl ).toString();
      }
    }
  };
});
<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const nconf = require.main.require('nconf');
const winston = require.main.require('winston');
const settings = require('./settings');
const async = require.main.require('async');
const logTag = require('./logtag');

/**
 * @class - Handles file-system operations.
 * - Instances can also schedule deletion of expired files
 */
class FileHandler {
  constructor() {
    this._timeout = settings().expireAfter;
    this.intervalReference = null;
  }
  /**
   * Sets interval for expired file deletion
   */
  startFileDelete() {
    const self = this;
    this.intervalReference = setInterval(() => self.doSome(), 3000);
    winston.info(logTag` Scheduled deleting expired files every ${settings().expireAfter / 1000} seconds`);
  }
  /**
   * Clears interval for expired file deletion
   */
  stopFileDelete() {
    clearInterval(this.intervalReference);
    this.intervalReference = null;
  }
  /**
   * Resets interval for expired file deletion
   */
  resetFileDelete() {
    if (this.intervalReference) this.stopFileDelete();
    this.startFileDelete();
  }
  doSome() {
    console.log('doing some');
  }

  /**
   * Creates storage folder on disk if not already present
   * @param  {Function} next
   */
  static createStorage(next) {
    var absPath = nconf.get('base_dir') + settings().storage;
    // create 'storage' directory
    fs.mkdir(absPath, function(err) {
      if (err) {
        if (err.code === 'EEXIST') {
          // if folder exists, we're good.
          return next();
        } else {
          // unexpected error; scream panic back into the log ;)
          winston.error(logTag` Unexpected error while creating ${absPath}`);
          return next(err);
        }
      }
      winston.warn(logTag` Storage folder '${absPath}' not found. Created it.`);
      next();
    });
  }

  /**
   * Moves uploaded file from its temp path to the storage folder
   * @param  {ExpiringFile} expFile - Meta data of file to move
   * @param  {string}       tmpPath - Temporary upload path
   * @param  {function}     cb
   */
  static saveUpload(expFile, tmpPath, cb) {
    var is = fs.createReadStream(tmpPath);
    var os = fs.createWriteStream(expFile.absolutePath);

    is.on('end', cb);
    os.on('error', cb);
    is.pipe(os);
  }

  /**
   * Deletes files described by given ExpiringFile intances
   * @param  {Array.<ExpiringFile>} files
   * @param  {FileHandler~cbDeleteFiles} next
   */
  static deleteFiles(files, next) {
    async.each(files, (file, eachNext) => {
      fs.unlink(file.absolutePath, function(err) {
        if (err) {
          if (err.code === 'ENOENT') {
            // no reason to panic, if file is not found
            winston.warn(logTag` Couldn't delete ${file.absolutePath} [Not found]`);
          } else {
            // everything else could be a serious problem; abort
            return eachNext(err);
          }
        } else {
          winston.verbose(logTag` Deleted ${file.absolutePath}`);
          eachNext();
        }
      });
    }, (err) => err ? next(err) : next(null, files));
  }

  /**
   * Makes sure {@link Settings.storage} isn't part of /public/
   * @param  {Function} next
   */
  static checkPublicStorage(next) {
    winston.info(logTag` Settings loaded.`);
    // everything in /public is out of the question, since it is
    // automatically exposed to the public (hence the name - maybe? ^_^)
    var pubTestPath = nconf.get('base_dir') + '/public';
    if (settings().storage.indexOf(pubTestPath) > -1) {
      winston.error(logTag` Upload directory is publicly accessible. Refusing to activate plugin!`);
      return next(new Error(`Public directory '${pubTestPath}' not allowed as storage.`));
    }
    next();
  }

  /**
   * @callback FileHandler~cbDeleteFiles
   * @param {?Error} err
   * @param {Array.<ExpiringFile>} files - Passed down input
   */
}

module.exports = FileHandler;
<commit_msg>Move/Rename deleteExpiredFiles to FileHandler.deleteExpired<commit_after>'use strict';

const fs = require('fs');
const nconf = require.main.require('nconf');
const winston = require.main.require('winston');
const settings = require('./settings');
const async = require.main.require('async');
const logTag = require('./logtag');
const DB = require('./dbwrap');

/**
 * @class - Handles file-system operations.
 * - Instances can also schedule deletion of expired files
 */
class FileHandler {
  constructor() {
    this._timeout = settings().expireAfter;
    this._intervalReference = null;
  }
  /**
   * Sets interval for expired file deletion
   */
  startFileDelete() {
    this._intervalReference = setInterval(() => FileHandler.deleteExpired(), settings().deleteFilesInterval);
    winston.info(logTag` Scheduled deleting expired files every ${settings().expireAfter / 1000} seconds`);
  }
  /**
   * Clears interval for expired file deletion
   */
  stopFileDelete() {
    clearInterval(this._intervalReference);
    this._intervalReference = null;
  }
  /**
   * Resets interval for expired file deletion
   */
  resetFileDelete() {
    if (this._intervalReference) this.stopFileDelete();
    this.startFileDelete();
  }

  /**
   * Moves uploaded file from its temp path to the storage folder
   * @param  {ExpiringFile} expFile - Meta data of file to move
   * @param  {string}       tmpPath - Temporary upload path
   * @param  {function}     cb
   */
  static saveUpload(expFile, tmpPath, cb) {
    var is = fs.createReadStream(tmpPath);
    var os = fs.createWriteStream(expFile.absolutePath);

    is.on('end', cb);
    os.on('error', cb);
    is.pipe(os);
  }

  /**
   * Regular cleanup routine
   */
  static deleteExpired() {
    async.waterfall([
      DB.getExpiredIds,
      DB.getExpiringFiles,
      FileHandler.deleteFiles,
      DB.setFilesDeleted
    ], function(err, keys) {
      if (err) {
        if (err.code === 'ENOEXP') {
          return winston.info(logTag`${err.message}`);
        }
        winston.error(logTag`Error while deleting expired files`);
        winston.error(err);
      }
    });
  };

  /**
   * Deletes files described by given ExpiringFile intances
   * @param  {Array.<ExpiringFile>} files
   * @param  {FileHandler~cbDeleteFiles} next
   */
  static deleteFiles(files, next) {
    async.each(files, (file, eachNext) => {
      fs.unlink(file.absolutePath, function(err) {
        if (err) {
          if (err.code === 'ENOENT') {
            // no reason to panic, if file is not found
            winston.warn(logTag` Couldn't delete ${file.absolutePath} [Not found]`);
          } else {
            // everything else could be a serious problem; abort
            return eachNext(err);
          }
        } else {
          winston.verbose(logTag` Deleted ${file.absolutePath}`);
          eachNext();
        }
      });
    }, (err) => err ? next(err) : next(null, files));
  }

  /**
   * Creates storage folder on disk if not already present
   * @param  {Function} next
   */
  static createStorage(next) {
    var absPath = nconf.get('base_dir') + settings().storage;
    // create 'storage' directory
    fs.mkdir(absPath, function(err) {
      if (err) {
        if (err.code === 'EEXIST') {
          // if folder exists, we're good.
          return next();
        } else {
          // unexpected error; scream panic back into the log ;)
          winston.error(logTag` Unexpected error while creating ${absPath}`);
          return next(err);
        }
      }
      winston.warn(logTag` Storage folder '${absPath}' not found. Created it.`);
      next();
    });
  }

  /**
   * Makes sure {@link Settings.storage} isn't part of /public/
   * @param  {Function} next
   */
  static checkPublicStorage(next) {
    winston.info(logTag` Settings loaded.`);
    // everything in /public is out of the question, since it is
    // automatically exposed to the public (hence the name - maybe? ^_^)
    var pubTestPath = nconf.get('base_dir') + '/public';
    if (settings().storage.indexOf(pubTestPath) > -1) {
      winston.error(logTag` Upload directory is publicly accessible. Refusing to activate plugin!`);
      return next(new Error(`Public directory '${pubTestPath}' not allowed as storage.`));
    }
    next();
  }

  /**
   * @callback FileHandler~cbDeleteFiles
   * @param {?Error} err
   * @param {Array.<ExpiringFile>} files - Passed down input
   */
}

module.exports = FileHandler;
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var config = require('./helpers/config');

/**
 * App and Firestarter create a circular require. Set the exports early, before requiring App, so that it's available in App already.
 */
exports = module.exports = new Firestarter();

var App = require('./app');

/**
 * The singleton-ish module orchastrating the modules and apps. Do not construct an instance of this manually. When `require`ing fire, an instance of `Firestarter` is exported.
 *
 * @constructor
 */
function Firestarter() {
	this.appsMap = {};
	this.disabled = false;

	config.basePath = path.resolve('./');
}

/**
 * Creates a new or returns an existing `App`.
 *
 * It is possible to create multiple apps with different names. Fire will store them in a map internally.
 *
 * If a `options` is specified, a new app will be created. If an app with the same name already exists, an exception is thrown.
 *
 * If `options` is not specified, an existing app will be retrieved. If no app with `name` exists, an exception is thrown.
 *
 * For example, to create a new app:
 * ```
 * var fire = require('fire');
 * var app = fire.app('test', {});
 *
 * //
 * ```
 *
 * @param  {String} name The name of the app passed to the App constructor.
 * @param  {Dictionary} opts Passed directly to the app constructor. See {@link App} for more information.
 * @return {App}      The newly created or existing app.
 */
Firestarter.prototype.app = function(name, options) {
	if(!name) {
		throw new Error('You must specify an app name in fire.app()');
	}

	var app = null;
	if(!this.appsMap[name]) {
		if(!options) {
			throw new Error('Cannot create an app without options.');
		}

		if(this.disabled) {
			options.disabled = true;
		}

		app = new App(name, options);
		this.appsMap[name] = app;
	}
	else {
		if(options) {
			throw new Error('Cannot create app `' + name + '`. It already exists.');
		}
		else {
			app = this.appsMap[name];
		}
	}

	// Please note: when calling fire.app(...) for a second time, it simply returns the cached app (if it's not been removed)
	// regardless of the name. It will also _not_ set any of the options.

	return app;
};

/**
 * Removes an app from the internal map. Useful when cleaning up during tests.
 *
 * @access private
 *
 * @param {App} app The app to be removed.
 */
Firestarter.prototype.removeApp = function(app) {
	if(this.appsMap[app.name]) {
		delete this.appsMap[app.name];
	}
};
<commit_msg>improves error message when retrieving unknown app<commit_after>'use strict';

var path = require('path');
var config = require('./helpers/config');

/**
 * App and Firestarter create a circular require. Set the exports early, before requiring App, so that it's available in App already.
 */
exports = module.exports = new Firestarter();

var App = require('./app');

/**
 * The singleton-ish module orchastrating the modules and apps. Do not construct an instance of this manually. When `require`ing fire, an instance of `Firestarter` is exported.
 *
 * @constructor
 */
function Firestarter() {
	this.appsMap = {};
	this.disabled = false;

	config.basePath = path.resolve('./');
}

/**
 * Creates a new or returns an existing `App`.
 *
 * It is possible to create multiple apps with different names. Fire will store them in a map internally.
 *
 * If a `options` is specified, a new app will be created. If an app with the same name already exists, an exception is thrown.
 *
 * If `options` is not specified, an existing app will be retrieved. If no app with `name` exists, an exception is thrown.
 *
 * For example, to create a new app:
 * ```
 * var fire = require('fire');
 * var app = fire.app('test', {});
 *
 * //
 * ```
 *
 * @param  {String} name The name of the app passed to the App constructor.
 * @param  {Dictionary} opts Passed directly to the app constructor. See {@link App} for more information.
 * @return {App}      The newly created or existing app.
 */
Firestarter.prototype.app = function(name, options) {
	if(!name) {
		throw new Error('You must specify an app name in fire.app()');
	}

	var app = null;
	if(!this.appsMap[name]) {
		if(!options) {
			throw new Error('Cannot create app `' + name + '` without options.');
		}

		if(this.disabled) {
			options.disabled = true;
		}

		app = new App(name, options);
		this.appsMap[name] = app;
	}
	else {
		if(options) {
			throw new Error('Cannot create app `' + name + '`. It already exists.');
		}
		else {
			app = this.appsMap[name];
		}
	}

	// Please note: when calling fire.app(...) for a second time, it simply returns the cached app (if it's not been removed)
	// regardless of the name. It will also _not_ set any of the options.

	return app;
};

/**
 * Removes an app from the internal map. Useful when cleaning up during tests.
 *
 * @access private
 *
 * @param {App} app The app to be removed.
 */
Firestarter.prototype.removeApp = function(app) {
	if(this.appsMap[app.name]) {
		delete this.appsMap[app.name];
	}
};
<|endoftext|>


<commit_before>"use strict";

module.exports = function flattenDeep(array) {
    var result = [];
    var nodes = array.slice();
    var node;

    if (!array.length) {
        return result;
    }

    node = nodes.pop();

    do {
        if (node instanceof Array) {
            nodes.push.apply(nodes, node);
        } else {
            result.push(node);
        }
    } while (nodes.length && (node = nodes.pop()) !== undefined);

    result.reverse();
    return result;
};<commit_msg>Fix remove built version<commit_after><|endoftext|>


<commit_before>var Stream = require('stream');

// writable
exports.Event = function (options) {

    options = options || {};
    if (typeof options.objectMode === 'undefined') {
        options.objectMode = true;
    }

    var sequence = Stream.Duplex({
        readableObjectMode: options.objectMode ? true : false,
        writableObjectMode: options.objectMode ? true : false
    });

    // writable
    sequence._write = function (chunk, enc, next) {

        if (!sequence.seq) {
            return sequence.emit('error', new Error('Stream._write: Sequence not set.'));
        }

        sequence._next = next;
        sequence._pos = -1;
        sequence.next(null, chunk);
    };

    // readable
    sequence._read = function () {
        if (sequence.seq) {
            sequence.uncork();
        }
    };

    // next handler
    sequence.next = function (err, data) {

        // handle steam end (null) | (false, null)
        if (err === null && (data === null || data === undefined)) {
            sequence.end();
            return;
        }

        // set error flag and reset position (err)
        if (!sequence._err && err) {
            sequence._err = true;
            sequence._pos = 0;
            data = err;
        }

        // get handler
        // TODO handle no handler (reset position if no handler is found?)
        var handler = sequence.seq[sequence._err ? 'error' : 'data'][++sequence._pos];
        if (!handler) {

            // emit error to reader
            if (sequence._err) {
                sequence._next(data || new Error('Error stream: no data.'));
                return;
            }

            // auto convert to non-object streams
            if (!options.objectMode &&
                typeof data !== 'string' &&
                data.constructor !== Buffer
            ) {
                try {
                    data = JSON.stringify(data);
                } catch (err)  {
                    sequence._next(err);
                    return;
                }
            }

            // write to linked stream
            if (sequence.linked) {

                // push also to response
                if (sequence.seq.type === '|') {
                    sequence.push(data);
                }

                // handle back pressure
                if (!sequence.linked.write(data)) {
                    sequence.linked.once('drain', sequence._next);
                    return;
                }

            // push data to readable
            } else if ((!sequence.push(data))) {

                // buffer all writes
                sequence.cork()
            }

            // request the next data chunk
            sequence._next();
            return;
        }

        // call next data handler
        handler[1].call(handler[0], sequence.next.bind(sequence), handler[2], data);
    };

    return sequence;
};
<commit_msg>working on data handler calls<commit_after>var Stream = require('stream');

// writable
exports.Event = function (options) {

    options = options || {};
    if (typeof options.objectMode === 'undefined') {
        options.objectMode = true;
    }

    var sequence = Stream.Duplex({
        readableObjectMode: options.objectMode ? true : false,
        writableObjectMode: options.objectMode ? true : false
    });

    // writable
    sequence._write = function (chunk, enc, next) {

        if (!sequence.seq) {
            return sequence.emit('error', new Error('Stream._write: Sequence not set.'));
        }

        sequence._next = next;
        sequence._pos = -1;
        sequence.next(null, chunk);
    };

    // readable
    sequence._read = function () {
        if (sequence.seq) {
            sequence.uncork();
        }
    };

    // next haninstancedler
    sequence.next = function (err, data) {

        // handle steam end (null) | (false, null)
        if (err === null && (data === null || data === undefined)) {
            sequence.end();
            return;
        }

        // set error flag and reset position (err)
        if (!sequence._err && err) {
            sequence._err = true;
            sequence._pos = 0;
            data = err;
        }

        // get handler
        // TODO handle no handler (reset position if no handler is found?)
        var handler = sequence.seq[0][++sequence._pos];
        if (!handler) {

            // emit error to reader
            if (sequence._err) {
                sequence._next(data || new Error('Error stream: no data.'));
                return;
            }

            // auto convert to non-object streams
            if (!options.objectMode &&
                typeof data !== 'string' &&
                data.constructor !== Buffer
            ) {
                try {
                    data = JSON.stringify(data);
                } catch (err)  {
                    sequence._next(err);
                    return;
                }
            }

            // write to linked stream
            if (sequence.linked) {

                // push also to response
                if (sequence.seq[1][0] === '|') {
                    sequence.push(data);
                }

                // handle back pressure
                if (!sequence.linked.write(data)) {
                    sequence.linked.once('drain', sequence._next);
                    return;
                }

            // push data to readable
            } else if ((!sequence.push(data))) {

                // buffer all writes
                sequence.cork()
            }

            // request the next data chunk
            sequence._next();
            return;
        }

        // call next data handler
        handler[0].call(handler[2], sequence.next.bind(sequence), handler[1], data);
    };

    return sequence;
};
<|endoftext|>