<commit_before>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/* global _playground */

define(function (require, exports, module) {
    "use strict";

    var EventEmitter = require("eventEmitter"),
        util = require("../util"),
        Promise = require("bluebird");

    /**
     * The Descriptor object provides helper methods for dealing with the
     * low-level native binding to Photoshop. This object will typically
     * not be used by user-level code.
     *
     * Emits low-level Photoshop events such as "select" with
     * the following parameters:
     *    1. @param {?} info about the event, dependent on event type (Note:
     *           this should become more specific as the native interface is
     *           further defined.)
     *
     * @extends EventEmitter
     * @constructor
     * @private
     */
    var Descriptor = function () {
        EventEmitter.call(this);

        this._psEventHandler = this._psEventHandler.bind(this);
    };
    util.inherits(Descriptor, EventEmitter);

    /**
     * Event handler for events from the native bridge.
     *
     * @private
     * @param {*=} err Error information
     * @param {String} eventID typeID for event type
     * @param {Object} payload serialized ActionDescriptor for the event, dependent on event type
     */
    Descriptor.prototype._psEventHandler = function (err, eventID, payload) {
        if (err) {
            this.emit("error", "Failed to handle Photoshop event: " + err);
            return;
        }

        this.emit("all", eventID, payload);
        this.emit(eventID, payload);
    };

    /**
     * Emit the named event with the given arguments as parameters. Throws if the
     * event is "error" and there are no listeners.
     *
     * @override EventEmitter.prototype.emitEvent
     * @param {string|RegExp} event Name of the event to emit and execute listeners for
     * @param {Array=} args Optional array of arguments to be passed to each listener
     * @return {object} Current instance for chaining
     */
    Descriptor.prototype.emitEvent = function (event, args) {
        if (event === "error") {
            var listeners = this.getListeners(event);

            if (listeners.length === 0) {
                var message,
                    error;

                if (args.length > 0 && typeof args[0] === "string") {
                    message = args.shift();
                } else {
                    message = "Unhandled error event";
                }

                error = new Error(message);
                error.args = args;
                throw error;
            }
        }

        Descriptor.super_.prototype.emitEvent.call(this, event, args);
    };

    /**
     * Wraps certain type of parameters making it easier to call Descriptor.prototype.get
     * For arrays, returns the reference to array recursively mapping everything inside
     * For string values, references to the currently active one
     * For objects, leaves them as is.
     *
     * @private
     * @param {(string|Array.<object>|object)} toWrap object to reference to
     * @return {object} Reference to the toWrap object in a form .get will accept
     */
    var _wrap = function (toWrap) {
        var reference;

        if (Array.isArray(toWrap)) {
            reference = {
                ref: toWrap.map(_wrap).reverse()
            };
        } else if (typeof toWrap === "string") {
            reference = {
                ref: toWrap,
                enum: "ordinal",
                value: "targetEnum"
            };
        } else {
            reference = toWrap;

            // Special case for play objects
            if (reference.hasOwnProperty("null")) {
                reference["null"] = _wrap(reference["null"]);
            }

        }

        return reference;
    };

    /**
     * Executes a low-level "get" call using an ActionReference.
     *
     * @param {(string|Array.<(string|Object)>|Object)} reference The reference to retrieve. Can be:
     *     - string of a class name
     *     - Object representation of ActionReference key/value pairs
     *     - An array of a combination of the above, which will get turned into the appropriate ActionReference
     * @return {Promise.<?>} The value of the reference, dependent on reference type
     */
    Descriptor.prototype.get = function (reference) {
        var wrappedReference = _wrap(reference),
            getAsync = Promise.promisify(_playground.ps.descriptor.get,
                _playground.ps.descriptor);

        return getAsync(wrappedReference);
    };

    /**
     * Retrieves a property of a reference
     *
     * @param {String} reference The name of the reference
     * @param {String} property The name of the property
     * @return {Promise.<?>} The value of the property, dependent on reference type
     */
    Descriptor.prototype.getProperty = function (reference, property) {
        var propertyDescriptor = {
                ref: "property",
                property: property
            },
            propertyReference = Array.isArray(reference) ?
                reference.concat(propertyDescriptor) :
                [reference, propertyDescriptor];

        return this.get(propertyReference)
            .then(function (obj) {
                if (!obj.hasOwnProperty(property)) {
                    throw new Error("No such property: " + property);
                }

                return obj[property];
            });
    };

    /**
     * Defines an enumeration of three constants that control dialog display
     * while executing action descriptors: DONT_DISPLAY, DISPLAY and SILENT.
     *
     * @const
     * @type {Object.<string: number>}
     */
    Descriptor.prototype.interactionMode = _playground.ps.descriptor.interactionMode;

    /**
     * Executes a low-level "play" call on the specified ActionDescriptor.
     *
     * @param {string} name Name of the ActionDescriptor command
     * @param {Object=} descriptor JS Object representation of ActionDescriptor key/value pairs, defaults to {}
     * @param {Object=} options options, defaults to "silent"
     * @return {Promise.<object>} Resolves when the call is complete (Note: eventually, this will
     *     return the value resulting from the execution of the ActionDescriptor, if any).
     */
    Descriptor.prototype.play = function (name, descriptor, options) {
        descriptor = descriptor || {};
        options = options || {
            interactionMode: this.interactionMode.SILENT
        };

        var playAsync = Promise.promisify(_playground.ps.descriptor.play,
            _playground.ps.descriptor);

        return playAsync(name, descriptor, options);
    };

    /**
     * Executes a low-level "play" call on the PlayObject by unwrapping it
     *
     * @param {PlayObject} playObject Contains command, descriptor and options information
     *
     * @returns {Promise} Resolves to the result of the call
     */
    Descriptor.prototype.playObject = function (playObject) {
        var command = playObject.command,
            descriptor = _wrap(playObject.descriptor),
            options = playObject.options;

        return this.play(command, descriptor, options);
    };

    /**
     * Executes a low-level "batchPlay" call on the specified ActionDescriptors.
     *
     * @param {Array.<{name: string, descriptor: object}>} commands Array of ActionDescriptors to play
     * @param {object=} options Options applied to the execution of each ActionDescriptor individually
     * @param {{continueOnError: boolean=}}=} batchOptions Options that control how the batch of
     *      ActionDescriptors is executed.
     * @return {Promise.<Array.object>} Resolves with the list of ActionDescriptor results.
     */
    Descriptor.prototype.batchPlay = function (commands, options, batchOptions) {
        batchOptions = batchOptions || {};
        options = options || {
            interactionMode: this.interactionMode.SILENT
        };

        var batchPlayAsync = Promise.promisify(_playground.ps.descriptor.batchPlay,
            _playground.ps.descriptor);

        return batchPlayAsync(commands, options, batchOptions);
    };

    /**
     * Executes a low-level "batchPlay" call on the specified PlayObjects.
     *
     * @param {Array.<PlayObject>} objects Array of PlayObjects to play
     * @param {object=} options Options applied to the execution of each PlayObject individually
     * @param {{continueOnError: boolean}=} batchOptions Options that control how the batch of
     *      ActionDescriptors is executed.
     * @return {Promise.<Array.object>} Resolves with the list of ActionDescriptor results.
     */
    Descriptor.prototype.batchPlayObjects = function (objects, options, batchOptions) {
        batchOptions = batchOptions || {};
        options = options || {
            interactionMode: this.interactionMode.SILENT
        };

        var commands = objects.map(function (object) {
            return {
                name: object.command,
                descriptor: object.descriptor
            };
        });

        return this.batchPlay(commands, options, batchOptions);
    };

    /**
     * @type {Descriptor} The Descriptor singleton
     */
    var descriptor = new Descriptor();

    // bind native Photoshop event handler to our handler function
    _playground.setNotifier(_playground.notifierGroup.PHOTOSHOP, {}, descriptor._psEventHandler);

    module.exports = descriptor;
});
<commit_msg>Don't throw a TypeError when getProperty returns null<commit_after>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

/* global _playground */

define(function (require, exports, module) {
    "use strict";

    var EventEmitter = require("eventEmitter"),
        util = require("../util"),
        Promise = require("bluebird");

    /**
     * The Descriptor object provides helper methods for dealing with the
     * low-level native binding to Photoshop. This object will typically
     * not be used by user-level code.
     *
     * Emits low-level Photoshop events such as "select" with
     * the following parameters:
     *    1. @param {?} info about the event, dependent on event type (Note:
     *           this should become more specific as the native interface is
     *           further defined.)
     *
     * @extends EventEmitter
     * @constructor
     * @private
     */
    var Descriptor = function () {
        EventEmitter.call(this);

        this._psEventHandler = this._psEventHandler.bind(this);
    };
    util.inherits(Descriptor, EventEmitter);

    /**
     * Event handler for events from the native bridge.
     *
     * @private
     * @param {*=} err Error information
     * @param {String} eventID typeID for event type
     * @param {Object} payload serialized ActionDescriptor for the event, dependent on event type
     */
    Descriptor.prototype._psEventHandler = function (err, eventID, payload) {
        if (err) {
            this.emit("error", "Failed to handle Photoshop event: " + err);
            return;
        }

        this.emit("all", eventID, payload);
        this.emit(eventID, payload);
    };

    /**
     * Emit the named event with the given arguments as parameters. Throws if the
     * event is "error" and there are no listeners.
     *
     * @override EventEmitter.prototype.emitEvent
     * @param {string|RegExp} event Name of the event to emit and execute listeners for
     * @param {Array=} args Optional array of arguments to be passed to each listener
     * @return {object} Current instance for chaining
     */
    Descriptor.prototype.emitEvent = function (event, args) {
        if (event === "error") {
            var listeners = this.getListeners(event);

            if (listeners.length === 0) {
                var message,
                    error;

                if (args.length > 0 && typeof args[0] === "string") {
                    message = args.shift();
                } else {
                    message = "Unhandled error event";
                }

                error = new Error(message);
                error.args = args;
                throw error;
            }
        }

        Descriptor.super_.prototype.emitEvent.call(this, event, args);
    };

    /**
     * Wraps certain type of parameters making it easier to call Descriptor.prototype.get
     * For arrays, returns the reference to array recursively mapping everything inside
     * For string values, references to the currently active one
     * For objects, leaves them as is.
     *
     * @private
     * @param {(string|Array.<object>|object)} toWrap object to reference to
     * @return {object} Reference to the toWrap object in a form .get will accept
     */
    var _wrap = function (toWrap) {
        var reference;

        if (Array.isArray(toWrap)) {
            reference = {
                ref: toWrap.map(_wrap).reverse()
            };
        } else if (typeof toWrap === "string") {
            reference = {
                ref: toWrap,
                enum: "ordinal",
                value: "targetEnum"
            };
        } else {
            reference = toWrap;

            // Special case for play objects
            if (reference.hasOwnProperty("null")) {
                reference["null"] = _wrap(reference["null"]);
            }

        }

        return reference;
    };

    /**
     * Executes a low-level "get" call using an ActionReference.
     *
     * @param {(string|Array.<(string|Object)>|Object)} reference The reference to retrieve. Can be:
     *     - string of a class name
     *     - Object representation of ActionReference key/value pairs
     *     - An array of a combination of the above, which will get turned into the appropriate ActionReference
     * @return {Promise.<?>} The value of the reference, dependent on reference type
     */
    Descriptor.prototype.get = function (reference) {
        var wrappedReference = _wrap(reference),
            getAsync = Promise.promisify(_playground.ps.descriptor.get,
                _playground.ps.descriptor);

        return getAsync(wrappedReference);
    };

    /**
     * Retrieves a property of a reference
     *
     * @param {String} reference The name of the reference
     * @param {String} property The name of the property
     * @return {Promise.<?>} The value of the property, dependent on reference type
     */
    Descriptor.prototype.getProperty = function (reference, property) {
        var propertyDescriptor = {
                ref: "property",
                property: property
            },
            propertyReference = Array.isArray(reference) ?
                reference.concat(propertyDescriptor) :
                [reference, propertyDescriptor];

        return this.get(propertyReference)
            .then(function (obj) {
                if (!obj || !obj.hasOwnProperty(property)) {
                    throw new Error("No such property: " + property);
                }

                return obj[property];
            });
    };

    /**
     * Defines an enumeration of three constants that control dialog display
     * while executing action descriptors: DONT_DISPLAY, DISPLAY and SILENT.
     *
     * @const
     * @type {Object.<string: number>}
     */
    Descriptor.prototype.interactionMode = _playground.ps.descriptor.interactionMode;

    /**
     * Executes a low-level "play" call on the specified ActionDescriptor.
     *
     * @param {string} name Name of the ActionDescriptor command
     * @param {Object=} descriptor JS Object representation of ActionDescriptor key/value pairs, defaults to {}
     * @param {Object=} options options, defaults to "silent"
     * @return {Promise.<object>} Resolves when the call is complete (Note: eventually, this will
     *     return the value resulting from the execution of the ActionDescriptor, if any).
     */
    Descriptor.prototype.play = function (name, descriptor, options) {
        descriptor = descriptor || {};
        options = options || {
            interactionMode: this.interactionMode.SILENT
        };

        var playAsync = Promise.promisify(_playground.ps.descriptor.play,
            _playground.ps.descriptor);

        return playAsync(name, descriptor, options);
    };

    /**
     * Executes a low-level "play" call on the PlayObject by unwrapping it
     *
     * @param {PlayObject} playObject Contains command, descriptor and options information
     *
     * @returns {Promise} Resolves to the result of the call
     */
    Descriptor.prototype.playObject = function (playObject) {
        var command = playObject.command,
            descriptor = _wrap(playObject.descriptor),
            options = playObject.options;

        return this.play(command, descriptor, options);
    };

    /**
     * Executes a low-level "batchPlay" call on the specified ActionDescriptors.
     *
     * @param {Array.<{name: string, descriptor: object}>} commands Array of ActionDescriptors to play
     * @param {object=} options Options applied to the execution of each ActionDescriptor individually
     * @param {{continueOnError: boolean=}}=} batchOptions Options that control how the batch of
     *      ActionDescriptors is executed.
     * @return {Promise.<Array.object>} Resolves with the list of ActionDescriptor results.
     */
    Descriptor.prototype.batchPlay = function (commands, options, batchOptions) {
        batchOptions = batchOptions || {};
        options = options || {
            interactionMode: this.interactionMode.SILENT
        };

        var batchPlayAsync = Promise.promisify(_playground.ps.descriptor.batchPlay,
            _playground.ps.descriptor);

        return batchPlayAsync(commands, options, batchOptions);
    };

    /**
     * Executes a low-level "batchPlay" call on the specified PlayObjects.
     *
     * @param {Array.<PlayObject>} objects Array of PlayObjects to play
     * @param {object=} options Options applied to the execution of each PlayObject individually
     * @param {{continueOnError: boolean}=} batchOptions Options that control how the batch of
     *      ActionDescriptors is executed.
     * @return {Promise.<Array.object>} Resolves with the list of ActionDescriptor results.
     */
    Descriptor.prototype.batchPlayObjects = function (objects, options, batchOptions) {
        batchOptions = batchOptions || {};
        options = options || {
            interactionMode: this.interactionMode.SILENT
        };

        var commands = objects.map(function (object) {
            return {
                name: object.command,
                descriptor: object.descriptor
            };
        });

        return this.batchPlay(commands, options, batchOptions);
    };

    /**
     * @type {Descriptor} The Descriptor singleton
     */
    var descriptor = new Descriptor();

    // bind native Photoshop event handler to our handler function
    _playground.setNotifier(_playground.notifierGroup.PHOTOSHOP, {}, descriptor._psEventHandler);

    module.exports = descriptor;
});
<|endoftext|>


<commit_before>export default class PubSub {
  constructor() {
    this._connections = {};
  }

  subscribe(name, connection, action) {
    this._connections[name] = this._connections[name] || new Set();

    if (action === true) {
      this._connections[name].add(connection);

      connection.once('close', () => {
        this.subscribe(name, connection, false);
      });
    } else if (action === false) {
      this._connection[name].delete(connection);
    }

    return this;
  }

  publish(name, connection, path, data) {
    this._connections[name] = this._connections[name] || new Set();

    if (!this._connections[name].has(connection)) {
      return this;
    }

    this._connections[name].forEach((target) => {
      target.request()
        .method('PUB')
        .path(path)
        .once('error', () => {})
        .end(data);
    });

    return this;
  }
}
<commit_msg>Fix reference error<commit_after>export default class PubSub {
  constructor() {
    this._connections = {};
  }

  subscribe(name, connection, action) {
    this._connections[name] = this._connections[name] || new Set();

    if (action === true) {
      this._connections[name].add(connection);

      connection.once('close', () => {
        this.subscribe(name, connection, false);
      });
    } else if (action === false) {
      this._connections[name].delete(connection);
    }

    return this;
  }

  publish(name, connection, path, data) {
    this._connections[name] = this._connections[name] || new Set();

    if (!this._connections[name].has(connection)) {
      return this;
    }

    this._connections[name].forEach((target) => {
      target.request()
        .method('PUB')
        .path(path)
        .once('error', () => {})
        .end(data);
    });

    return this;
  }
}
<|endoftext|>


<commit_before>var _ = require('lodash');

exports.flatten = function() {
	return _.flatten(arguments);
};

exports.numbers = function() {
	var possibleNumbers = exports.flatten(arguments);
	return possibleNumbers.filter(function(el) {
		return typeof el === 'number';
	});
};<commit_msg>add parseBool<commit_after>var _ = require('lodash');
var error = require('./error');

exports.flatten = function() {
  return _.flatten(arguments);
};

exports.numbers = function() {
  var possibleNumbers = exports.flatten(arguments);
  return possibleNumbers.filter(function(el) {
    return typeof el === 'number';
  });
};

exports.cleanFloat = function(number) {
  var power = Math.pow(10, 14);
  return Math.round(number * power) / power;
};

exports.parseBool = function(bool) {
  if (typeof bool === 'boolean') {
    return bool;
  }

  if (bool instanceof Error) {
    return bool;
  }

  if (typeof bool === 'number') {
    if (bool === 0) {
      return false;
    } else {
      return true;
    }
  }

  if (typeof bool === 'string') {
    var up = bool.toUpperCase();
    if (up === 'TRUE') {
      return true;
    }

    if (up === 'FALSE') {
      return false;
    }
  }

  if (bool instanceof Date && !isNaN(bool)) {
    return true;
  }

  return error.value;
};<|endoftext|>


<commit_before>var app = require('./app'),
    http = require('http'),
    xml2js = require('xml2js'),
    util = require('util'),
    path = require('path'),
    error = app.log.error;

var parserDefaults = {
    attrkey: "$",
    charkey: "_",
    explicitArray: true
  };

module.exports = {
    saveMDRecord: function(record, params, query, callback) {
      //parser options
      var parserConfig = getParserConfig();
      var parser = new xml2js.Parser({
          attrkey: parserConfig.attrkey,
          charkey: parserConfig.charkey,
          explicitArray : parserConfig.explicitArray
      });

      parser.parseString(record, function(err, result) {
					if (!err) {
            //app.log.info('result: ' + JSON.stringify(result));
						var mdrecord = app.schema.CreateMDRecord({
		            dkclarinID: params.id,
		            data: JSON.stringify(result),
		            'type.name': params.name,
                reversible: (parserConfig.attrkey === parserDefaults.attrkey && parserConfig.charkey === parserDefaults.charkey && parserConfig.explicitArray === parserDefaults.explicitArray)
		        });

            mdrecord.save();

            app.log.info('mdrecord: ' + mdrecord.id);

						var itemsToAdd = (query.search_ids.length > 0) ? {
		                result_collection: mdrecord.id,
		                search_ids: params.id
		            } :
		            {
		                result_collection: mdrecord.id
		            };

		        app.schema.models.Query.update({
		            _id: query.id
		        }, {
		            $addToSet: itemsToAdd
		        }, function(err) {
		            if (err) return app.log.error("Error on Query update: " + err);

		            app.log.info("Update +Query-" + query.id);
		            query.result_collection.push(mdrecord);

		            if (callback) callback();
		        });
					} else {
						error('Error: ' + err);
					}
				});
    },

    updateMDRecord: function(new_data, mdrecord) {
        app.log.debug("Updating MDRecord: " + mdrecord.id);
        var new_data_str = JSON.stringify(new_data);
        if (mdrecord.data != new_data_str) {
            mdrecord.data = new_data_str;
            mdrecord.set('update', true);
            this.saveDocument(mdrecord);
        }
    },

    updateQuery: function(query, callback) {
        app.log.debug("Updating Query: " + query.id);
        query.set('update', true);
        this.saveDocument(query, callback);
    },

    saveDocument: function(model, callback) {
        model.save(function(err) {
            if (err) error('Error:' + err);
            else app.log.debug('+' + model.constructor.modelName + "-" + model.id);
            if (callback && !err) callback(model);
        });
    },

    removeDocument: function(model, callback) {
        var modelDesc = model.constructor.modelName + "-" + model.id;
        model.remove(function(err, doc) {
            if (err) throw err;
            else app.log.debug('-' + modelDesc);

            if (callback)
                callback(doc);
        });
    },

    rest_options: function(params, isUpload) {
        var path = '/v0.9/items/' + params.id + '/metadata/' + params.name + '?escidocurl=' + params.target + '&d=' + Date.now(),
            updaterHost = (app.config.get('updaterHost') != null) ? app.config.get('updaterHost') : 'localhost',
            updaterPort = (app.config.get('updaterPort') != null) ? app.config.get('updaterPort') : '80';
        if (updaterPort == '80' || updaterPort == '8080') path = '/rest' + path; // expect deployed WAR
        return {
            host: updaterHost,
            port: updaterPort,
            path: path,
            headers: {
                'Cookie': 'escidocCookie=' + params.handle,
                'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
            },
            method: (!isUpload) ? 'GET' : 'PUT'
        };
    },

    srw_options: function(queryCQL, record_vals) {
        var search_path_limits = "&maximumRecords=" + record_vals.limit + "&startRecord=" + record_vals.start;
        var targetUrl = app.config.get('targetUrl');
        return {
            host: (targetUrl.indexOf('http://') != -1) ? targetUrl.replace('http://', '') : targetUrl,
            path: '/srw/search/escidoc_all?query=' + encodeURIComponent(queryCQL.replace(/\s/g, "%20")) + search_path_limits + '&d=' + Date.now()
        };
    },

    ir_options: function(params) {
        var targetUrl = app.config.get('targetUrl');
        return {
            host: (targetUrl.indexOf('http://') != -1) ? targetUrl.replace('http://', '') : targetUrl,
            path: '/ir/item/' + params.id + '/' + params.method,
            headers: (params.lastModificationDate != null) ? {
                'Content-Type': 'application/xml',
                'Cookie': 'escidocCookie=' + params.handle,
                'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
            } : null,
            method: (params.lastModificationDate != null) ? 'POST' : 'GET'
        };
    },

    getNamedNS: function(name) {
        switch (name) {
            case "olac":
                return {
                    ns: "http://www.language-archives.org/OLAC/1.1/",
                    nodeName: "olac"
                };
            case "escidoc":
                return {
                    ns: "http://www.openarchives.org/OAI/2.0/oai_dc/",
                    nodeName: "dc"
                };
            case "CMD":
                return {
                    nodeName: "CMD"
                };
            case "TEI":
                return {
                    nodeName: "teiHeader"
                };
            case "dkclarin":
                return {
                    ns: "http://purl.org/dc/elements/1.1/",
                    nodeName: "type"
                };
            default:
                return null;
        }
    },

    getSession: function(sessionModel, callback) {
        var handle = app.config.get('escidoc_handle');
        if (handle == null)
            return null;
        //TODO Config check, warning

        sessionModel.findByHandle(handle, function(err, res) {
            if (!err)
                if (res != null) callback(res);
                else callback(res, new Error("No valid Session exists for set handle: " + handle));
            else
                throw new Error("Error opening Session: " + err);
        });
    },
    getParserDefaults: function() {
      return parserDefaults;
    },
    getParserConfig: function() {
      var attrkey = (app.config.get('parserAttrkey')) ? app.config.get('parserAttrkey') : parserDefaults.attrkey;
      var charkey = (app.config.get('parserAttrkey')) ? app.config.get('parserCharkey') : parserDefaults.charkey;
      var explicitArray = (app.config.get('parserExplicitArray')) ? app.config.get('parserExplicitArray') : parserDefaults.explicitArray;
      return {
        attrkey: attrkey,
        charkey: charkey,
        explicitArray: explicitArray
      };
    },
    loadJSONFile: function(rel_filepath, callback) {
        var json = require(path.resolve(process.cwd(), rel_filepath));
        callback(json);
    },

    updateMDRecordREST: function(data, record, params, callback) {
        data = data.replace(/^\uFEFF/, ''); // Strip any potential UTF-8 BOM
        var req = http.request(this.rest_options(params, true), function(res) {
                var str = '';
                res.on('data', function(chunk) {
                    str += chunk;
                });
                res.on('end', function() {
                    // flag completed if successful 200 - comment: handled in callback fn
                    callback(res, str, data, record);
                });
            })
            .on('error', function(e) {
                app.log.error("Error: " + e.message);
                app.log.error("Error code: " + e.code);
            });

        req.end(data);
    },

    execItemREST: function(record, method, emitter, nextEvent, lastModificationDate, handle) {
      var restresp_parser = new xml2js.Parser({
          // options
          //explicitArray : false,
          //ignoreAttrs : false,
          mergeAttrs : true
      });
      var req = http.request(this.ir_options({
                id: record.dkclarinID,
                method: method,
                lastModificationDate: lastModificationDate,
                handle: handle
            }), function(res) {
                var str = '';
                res.on('data', function(chunk) {
                    str += chunk;
                });
                res.on('end', function() {
                    if (res.statusCode == 200 || res.statusCode == 409 || res.statusCode == 450) { //failSafe to release submitted items
                        restresp_parser.parseString(str, function(err, res_data) {
                            var newLastModificationDate = lastModificationDate;
                            if (res.statusCode == 450) {
                                // handle already submitted / released items
                                if (nextEvent == "release")
                                    app.log.warn("Item " + record.dkclarinID + " is already submitted, trying release..");
                                else if (nextEvent == "public") {
                                    app.log.warn("Item " + record.dkclarinID + " is already released, it likely that no new version was made.");
                                    app.log.warn("Marking Item " + record.dkclarinID + " as completed..");
                                    newLastModificationDate = null;
                                } else
                                    error("Unexpected 450 error: " + str);
                            } else if (res.statusCode == 409 && method == "submit") {
                                // handle invalid timestamp (fallback)
                                return emitter.emit("version", record, null);
                            } else {
                                if (method == "resources/version-history") {
                                    app.log.info('Using version timestamp from history');
                                    newLastModificationDate = res_data['escidocVersions:version-history']['escidocVersions:version'][0]['escidocVersions:timestamp']; // Obtain lastModificationDate for Item updated version
                                } else
                                    newLastModificationDate = res_data['result']['last-modification-date'];
                            }
                            emitter.emit(nextEvent, record, newLastModificationDate);
                        });
                    } else {
                        error("Error occurred processing " + method + ": " + res.statusCode + "\n" + str);
                        if (res.statusCode == 503) {
                            setTimeout(function(emitter, method, record, date) {
                                return emitter.emit(method, record, date);
                            }, 300000, emitter, method, record, lastModificationDate);
                            app.log.debug('attempting method call again after error, method: ' + method);
                        }
                    }

                });
            })
            .on('error', function(e) {
                error("Error: " + e.message);
                app.log.error("Error code: " + e.code);
            });

        if (lastModificationDate != "" && lastModificationDate) {
            var comment = "Test submission/release of item.";

            // Allow user to specify submit comment
            if (emitter.submitComment)
                comment = emitter.submitComment;

            app.log.debug("Submission comment: " + comment);
            var post = "<param last-modification-date=\"" + lastModificationDate + "\"><comment>" + comment + "</comment></param>";
            req.write(post);
        }
        req.end();
    },

    tableOutputBoolean: function(value) {
        return (value) ? 'yes'.green : 'no'.red;
    },
    exit: function(exitCode) {
        process.stdout.on('drain', function() {
            process.exit(exitCode);
        });
    },
    util: util

    // Read from Md-Record data file in local dir
    /* readFile: function(file_path) {
        if(!file_path) file_path = 'data/olac-243215.xml';
        fs.readFile(file_path, function(err, data) {
    	if(err) return console.log('Error: ' + err);
    	console.log("Data:" + data);
    	updateMDRecord(data, {})
        });
    };
    */
};
<commit_msg>Fix parser config<commit_after>var app = require('./app'),
    http = require('http'),
    xml2js = require('xml2js'),
    util = require('util'),
    path = require('path'),
    error = app.log.error;

var parserDefaults = {
    attrkey: "$",
    charkey: "_",
    explicitArray: true
  };

var attrkey = (app.config.get('parserAttrkey')) ? app.config.get('parserAttrkey') : parserDefaults.attrkey;
var charkey = (app.config.get('parserAttrkey')) ? app.config.get('parserCharkey') : parserDefaults.charkey;
var explicitArray = (app.config.get('parserExplicitArray')) ? app.config.get('parserExplicitArray') : parserDefaults.explicitArray;

module.exports = {
    saveMDRecord: function(record, params, query, callback) {
      //parser options
      var parser = new xml2js.Parser({
          attrkey: attrkey,
          charkey: charkey,
          explicitArray : explicitArray
      });

      parser.parseString(record, function(err, result) {
					if (!err) {
            //app.log.info('result: ' + JSON.stringify(result));
						var mdrecord = app.schema.CreateMDRecord({
		            dkclarinID: params.id,
		            data: JSON.stringify(result),
		            'type.name': params.name,
                reversible: (attrkey === parserDefaults.attrkey && charkey === parserDefaults.charkey && explicitArray === parserDefaults.explicitArray)
		        });

            mdrecord.save();

            app.log.info('mdrecord: ' + mdrecord.id);

						var itemsToAdd = (query.search_ids.length > 0) ? {
		                result_collection: mdrecord.id,
		                search_ids: params.id
		            } :
		            {
		                result_collection: mdrecord.id
		            };

		        app.schema.models.Query.update({
		            _id: query.id
		        }, {
		            $addToSet: itemsToAdd
		        }, function(err) {
		            if (err) return app.log.error("Error on Query update: " + err);

		            app.log.info("Update +Query-" + query.id);
		            query.result_collection.push(mdrecord);

		            if (callback) callback();
		        });
					} else {
						error('Error: ' + err);
					}
				});
    },

    updateMDRecord: function(new_data, mdrecord) {
        app.log.debug("Updating MDRecord: " + mdrecord.id);
        var new_data_str = JSON.stringify(new_data);
        if (mdrecord.data != new_data_str) {
            mdrecord.data = new_data_str;
            mdrecord.set('update', true);
            this.saveDocument(mdrecord);
        }
    },

    updateQuery: function(query, callback) {
        app.log.debug("Updating Query: " + query.id);
        query.set('update', true);
        this.saveDocument(query, callback);
    },

    saveDocument: function(model, callback) {
        model.save(function(err) {
            if (err) error('Error:' + err);
            else app.log.debug('+' + model.constructor.modelName + "-" + model.id);
            if (callback && !err) callback(model);
        });
    },

    removeDocument: function(model, callback) {
        var modelDesc = model.constructor.modelName + "-" + model.id;
        model.remove(function(err, doc) {
            if (err) throw err;
            else app.log.debug('-' + modelDesc);

            if (callback)
                callback(doc);
        });
    },

    rest_options: function(params, isUpload) {
        var path = '/v0.9/items/' + params.id + '/metadata/' + params.name + '?escidocurl=' + params.target + '&d=' + Date.now(),
            updaterHost = (app.config.get('updaterHost') != null) ? app.config.get('updaterHost') : 'localhost',
            updaterPort = (app.config.get('updaterPort') != null) ? app.config.get('updaterPort') : '80';
        if (updaterPort == '80' || updaterPort == '8080') path = '/rest' + path; // expect deployed WAR
        return {
            host: updaterHost,
            port: updaterPort,
            path: path,
            headers: {
                'Cookie': 'escidocCookie=' + params.handle,
                'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
            },
            method: (!isUpload) ? 'GET' : 'PUT'
        };
    },

    srw_options: function(queryCQL, record_vals) {
        var search_path_limits = "&maximumRecords=" + record_vals.limit + "&startRecord=" + record_vals.start;
        var targetUrl = app.config.get('targetUrl');
        return {
            host: (targetUrl.indexOf('http://') != -1) ? targetUrl.replace('http://', '') : targetUrl,
            path: '/srw/search/escidoc_all?query=' + encodeURIComponent(queryCQL.replace(/\s/g, "%20")) + search_path_limits + '&d=' + Date.now()
        };
    },

    ir_options: function(params) {
        var targetUrl = app.config.get('targetUrl');
        return {
            host: (targetUrl.indexOf('http://') != -1) ? targetUrl.replace('http://', '') : targetUrl,
            path: '/ir/item/' + params.id + '/' + params.method,
            headers: (params.lastModificationDate != null) ? {
                'Content-Type': 'application/xml',
                'Cookie': 'escidocCookie=' + params.handle,
                'Cache-Control': 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'
            } : null,
            method: (params.lastModificationDate != null) ? 'POST' : 'GET'
        };
    },

    getNamedNS: function(name) {
        switch (name) {
            case "olac":
                return {
                    ns: "http://www.language-archives.org/OLAC/1.1/",
                    nodeName: "olac"
                };
            case "escidoc":
                return {
                    ns: "http://www.openarchives.org/OAI/2.0/oai_dc/",
                    nodeName: "dc"
                };
            case "CMD":
                return {
                    nodeName: "CMD"
                };
            case "TEI":
                return {
                    nodeName: "teiHeader"
                };
            case "dkclarin":
                return {
                    ns: "http://purl.org/dc/elements/1.1/",
                    nodeName: "type"
                };
            default:
                return null;
        }
    },

    getSession: function(sessionModel, callback) {
        var handle = app.config.get('escidoc_handle');
        if (handle == null)
            return null;
        //TODO Config check, warning

        sessionModel.findByHandle(handle, function(err, res) {
            if (!err)
                if (res != null) callback(res);
                else callback(res, new Error("No valid Session exists for set handle: " + handle));
            else
                throw new Error("Error opening Session: " + err);
        });
    },
    getParserDefaults: function() {
      return parserDefaults;
    },
    getParserConfig: function() {
      return {
        attrkey: attrkey,
        charkey: charkey,
        explicitArray: explicitArray
      };
    },
    loadJSONFile: function(rel_filepath, callback) {
        var json = require(path.resolve(process.cwd(), rel_filepath));
        callback(json);
    },

    updateMDRecordREST: function(data, record, params, callback) {
        data = data.replace(/^\uFEFF/, ''); // Strip any potential UTF-8 BOM
        var req = http.request(this.rest_options(params, true), function(res) {
                var str = '';
                res.on('data', function(chunk) {
                    str += chunk;
                });
                res.on('end', function() {
                    // flag completed if successful 200 - comment: handled in callback fn
                    callback(res, str, data, record);
                });
            })
            .on('error', function(e) {
                app.log.error("Error: " + e.message);
                app.log.error("Error code: " + e.code);
            });

        req.end(data);
    },

    execItemREST: function(record, method, emitter, nextEvent, lastModificationDate, handle) {
      var restresp_parser = new xml2js.Parser({
          // options
          //explicitArray : false,
          //ignoreAttrs : false,
          mergeAttrs : true
      });
      var req = http.request(this.ir_options({
                id: record.dkclarinID,
                method: method,
                lastModificationDate: lastModificationDate,
                handle: handle
            }), function(res) {
                var str = '';
                res.on('data', function(chunk) {
                    str += chunk;
                });
                res.on('end', function() {
                    if (res.statusCode == 200 || res.statusCode == 409 || res.statusCode == 450) { //failSafe to release submitted items
                        restresp_parser.parseString(str, function(err, res_data) {
                            var newLastModificationDate = lastModificationDate;
                            if (res.statusCode == 450) {
                                // handle already submitted / released items
                                if (nextEvent == "release")
                                    app.log.warn("Item " + record.dkclarinID + " is already submitted, trying release..");
                                else if (nextEvent == "public") {
                                    app.log.warn("Item " + record.dkclarinID + " is already released, it likely that no new version was made.");
                                    app.log.warn("Marking Item " + record.dkclarinID + " as completed..");
                                    newLastModificationDate = null;
                                } else
                                    error("Unexpected 450 error: " + str);
                            } else if (res.statusCode == 409 && method == "submit") {
                                // handle invalid timestamp (fallback)
                                return emitter.emit("version", record, null);
                            } else {
                                if (method == "resources/version-history") {
                                    app.log.info('Using version timestamp from history');
                                    newLastModificationDate = res_data['escidocVersions:version-history']['escidocVersions:version'][0]['escidocVersions:timestamp']; // Obtain lastModificationDate for Item updated version
                                } else
                                    newLastModificationDate = res_data['result']['last-modification-date'];
                            }
                            emitter.emit(nextEvent, record, newLastModificationDate);
                        });
                    } else {
                        error("Error occurred processing " + method + ": " + res.statusCode + "\n" + str);
                        if (res.statusCode == 503) {
                            setTimeout(function(emitter, method, record, date) {
                                return emitter.emit(method, record, date);
                            }, 300000, emitter, method, record, lastModificationDate);
                            app.log.debug('attempting method call again after error, method: ' + method);
                        }
                    }

                });
            })
            .on('error', function(e) {
                error("Error: " + e.message);
                app.log.error("Error code: " + e.code);
            });

        if (lastModificationDate != "" && lastModificationDate) {
            var comment = "Test submission/release of item.";

            // Allow user to specify submit comment
            if (emitter.submitComment)
                comment = emitter.submitComment;

            app.log.debug("Submission comment: " + comment);
            var post = "<param last-modification-date=\"" + lastModificationDate + "\"><comment>" + comment + "</comment></param>";
            req.write(post);
        }
        req.end();
    },

    tableOutputBoolean: function(value) {
        return (value) ? 'yes'.green : 'no'.red;
    },
    exit: function(exitCode) {
        process.stdout.on('drain', function() {
            process.exit(exitCode);
        });
    },
    util: util

    // Read from Md-Record data file in local dir
    /* readFile: function(file_path) {
        if(!file_path) file_path = 'data/olac-243215.xml';
        fs.readFile(file_path, function(err, data) {
    	if(err) return console.log('Error: ' + err);
    	console.log("Data:" + data);
    	updateMDRecord(data, {})
        });
    };
    */
};
<|endoftext|>


<commit_before>/***********************************************************************

  A JavaScript tokenizer / parser / beautifier / compressor.
  https://github.com/mishoo/UglifyJS2

  -------------------------------- (C) ---------------------------------

                           Author: Mihai Bazon
                         <mihai.bazon@gmail.com>
                       http://mihai.bazon.net/blog

  Distributed under the BSD license:

    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

        * Redistributions of source code must retain the above
          copyright notice, this list of conditions and the following
          disclaimer.

        * Redistributions in binary form must reproduce the above
          copyright notice, this list of conditions and the following
          disclaimer in the documentation and/or other materials
          provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    SUCH DAMAGE.

 ***********************************************************************/

"use strict";

function array_to_hash(a) {
    var ret = Object.create(null);
    for (var i = 0; i < a.length; ++i)
        ret[a[i]] = true;
    return ret;
};

function slice(a, start) {
    return Array.prototype.slice.call(a, start || 0);
};

function characters(str) {
    return str.split("");
};

function member(name, array) {
    for (var i = array.length; --i >= 0;)
        if (array[i] == name)
            return true;
    return false;
};

function find_if(func, array) {
    for (var i = 0, n = array.length; i < n; ++i) {
        if (func(array[i]))
            return array[i];
    }
};

function repeat_string(str, i) {
    if (i <= 0) return "";
    if (i == 1) return str;
    var d = repeat_string(str, i >> 1);
    d += d;
    if (i & 1) d += str;
    return d;
};

function DefaultsError(msg, defs) {
    Error.call(this, msg);
    this.msg = msg;
    this.defs = defs;
};
DefaultsError.prototype = Object.create(Error.prototype);
DefaultsError.prototype.constructor = DefaultsError;

DefaultsError.croak = function(msg, defs) {
    throw new DefaultsError(msg, defs);
};

function defaults(args, defs, croak) {
    if (args === true)
        args = {};
    var ret = args || {};
    if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i))
        DefaultsError.croak("`" + i + "` is not a supported option", defs);
    for (var i in defs) if (defs.hasOwnProperty(i)) {
        ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i];
    }
    return ret;
};

function merge(obj, ext) {
    for (var i in ext) if (ext.hasOwnProperty(i)) {
        obj[i] = ext[i];
    }
    return obj;
};

function noop() {};

var MAP = (function(){
    function MAP(a, f, backwards) {
        var ret = [], top = [], i;
        function doit() {
            var val = f(a[i], i);
            var is_last = val instanceof Last;
            if (is_last) val = val.v;
            if (val instanceof AtTop) {
                val = val.v;
                if (val instanceof Splice) {
                    top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
                } else {
                    top.push(val);
                }
            }
            else if (val !== skip) {
                if (val instanceof Splice) {
                    ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
                } else {
                    ret.push(val);
                }
            }
            return is_last;
        };
        if (a instanceof Array) {
            if (backwards) {
                for (i = a.length; --i >= 0;) if (doit()) break;
                ret.reverse();
                top.reverse();
            } else {
                for (i = 0; i < a.length; ++i) if (doit()) break;
            }
        }
        else {
            for (i in a) if (a.hasOwnProperty(i)) if (doit()) break;
        }
        return top.concat(ret);
    };
    MAP.at_top = function(val) { return new AtTop(val) };
    MAP.splice = function(val) { return new Splice(val) };
    MAP.last = function(val) { return new Last(val) };
    var skip = MAP.skip = {};
    function AtTop(val) { this.v = val };
    function Splice(val) { this.v = val };
    function Last(val) { this.v = val };
    return MAP;
})();

function push_uniq(array, el) {
    if (array.indexOf(el) < 0)
        array.push(el);
};

function string_template(text, props) {
    return text.replace(/\{(.+?)\}/g, function(str, p){
        return props[p];
    });
};

function remove(array, el) {
    for (var i = array.length; --i >= 0;) {
        if (array[i] === el) array.splice(i, 1);
    }
};

function mergeSort(array, cmp) {
    if (array.length < 2) return array.slice();
    function merge(a, b) {
        var r = [], ai = 0, bi = 0, i = 0;
        while (ai < a.length && bi < b.length) {
            cmp(a[ai], b[bi]) <= 0
                ? r[i++] = a[ai++]
                : r[i++] = b[bi++];
        }
        if (ai < a.length) r.push.apply(r, a.slice(ai));
        if (bi < b.length) r.push.apply(r, b.slice(bi));
        return r;
    };
    function _ms(a) {
        if (a.length <= 1)
            return a;
        var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
        left = _ms(left);
        right = _ms(right);
        return merge(left, right);
    };
    return _ms(array);
};

function set_difference(a, b) {
    return a.filter(function(el){
        return b.indexOf(el) < 0;
    });
};

function set_intersection(a, b) {
    return a.filter(function(el){
        return b.indexOf(el) >= 0;
    });
};

// this function is taken from Acorn [1], written by Marijn Haverbeke
// [1] https://github.com/marijnh/acorn
function makePredicate(words) {
    if (!(words instanceof Array)) words = words.split(" ");
    var f = "", cats = [];
    out: for (var i = 0; i < words.length; ++i) {
        for (var j = 0; j < cats.length; ++j)
            if (cats[j][0].length == words[i].length) {
                cats[j].push(words[i]);
                continue out;
            }
        cats.push([words[i]]);
    }
    function compareTo(arr) {
        if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
        f += "switch(str){";
        for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
        f += "return true}return false;";
    }
    // When there are more than three length categories, an outer
    // switch first dispatches on the lengths, to save on comparisons.
    if (cats.length > 3) {
        cats.sort(function(a, b) {return b.length - a.length;});
        f += "switch(str.length){";
        for (var i = 0; i < cats.length; ++i) {
            var cat = cats[i];
            f += "case " + cat[0].length + ":";
            compareTo(cat);
        }
        f += "}";
        // Otherwise, simply generate a flat `switch` statement.
    } else {
        compareTo(words);
    }
    return new Function("str", f);
};

function all(array, predicate) {
    for (var i = array.length; --i >= 0;)
        if (!predicate(array[i]))
            return false;
    return true;
};

function Dictionary() {
    this._values = Object.create(null);
    this._size = 0;
};
Dictionary.prototype = {
    set: function(key, val) {
        if (!this.has(key)) ++this._size;
        this._values["$" + key] = val;
        return this;
    },
    add: function(key, val) {
        if (this.has(key)) {
            this.get(key).push(val);
        } else {
            this.set(key, [ val ]);
        }
        return this;
    },
    get: function(key) { return this._values["$" + key] },
    del: function(key) {
        if (this.has(key)) {
            --this._size;
            delete this._values["$" + key];
        }
        return this;
    },
    has: function(key) { return ("$" + key) in this._values },
    each: function(f) {
        for (var i in this._values)
            f(this._values[i], i.substr(1));
    },
    size: function() {
        return this._size;
    },
    map: function(f) {
        var ret = [];
        for (var i in this._values)
            ret.push(f(this._values[i], i.substr(1)));
        return ret;
    }
};

function CopyObject(obj){
    var newObj = {};
    for(var i in obj) if(obj.hasOwnProperty(i)) newObj[i] = obj[i];
    newObj.__proto__ = obj.__proto__;
    return newObj
}

function ReplaceObject(obj, newObj){
    for(var i in obj) if(obj.hasOwnProperty(i)) delete obj[i];
    for(var i in newObj) if(newObj.hasOwnProperty(i)) obj[i] = newObj[i];
    obj.__proto__ = newObj.__proto__;
    return obj;
}<commit_msg>use transform insted treewalker<commit_after>/***********************************************************************

  A JavaScript tokenizer / parser / beautifier / compressor.
  https://github.com/mishoo/UglifyJS2

  -------------------------------- (C) ---------------------------------

                           Author: Mihai Bazon
                         <mihai.bazon@gmail.com>
                       http://mihai.bazon.net/blog

  Distributed under the BSD license:

    Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

        * Redistributions of source code must retain the above
          copyright notice, this list of conditions and the following
          disclaimer.

        * Redistributions in binary form must reproduce the above
          copyright notice, this list of conditions and the following
          disclaimer in the documentation and/or other materials
          provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    SUCH DAMAGE.

 ***********************************************************************/

"use strict";

function array_to_hash(a) {
    var ret = Object.create(null);
    for (var i = 0; i < a.length; ++i)
        ret[a[i]] = true;
    return ret;
};

function slice(a, start) {
    return Array.prototype.slice.call(a, start || 0);
};

function characters(str) {
    return str.split("");
};

function member(name, array) {
    for (var i = array.length; --i >= 0;)
        if (array[i] == name)
            return true;
    return false;
};

function find_if(func, array) {
    for (var i = 0, n = array.length; i < n; ++i) {
        if (func(array[i]))
            return array[i];
    }
};

function repeat_string(str, i) {
    if (i <= 0) return "";
    if (i == 1) return str;
    var d = repeat_string(str, i >> 1);
    d += d;
    if (i & 1) d += str;
    return d;
};

function DefaultsError(msg, defs) {
    Error.call(this, msg);
    this.msg = msg;
    this.defs = defs;
};
DefaultsError.prototype = Object.create(Error.prototype);
DefaultsError.prototype.constructor = DefaultsError;

DefaultsError.croak = function(msg, defs) {
    throw new DefaultsError(msg, defs);
};

function defaults(args, defs, croak) {
    if (args === true)
        args = {};
    var ret = args || {};
    if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i))
        DefaultsError.croak("`" + i + "` is not a supported option", defs);
    for (var i in defs) if (defs.hasOwnProperty(i)) {
        ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i];
    }
    return ret;
};

function merge(obj, ext) {
    for (var i in ext) if (ext.hasOwnProperty(i)) {
        obj[i] = ext[i];
    }
    return obj;
};

function noop() {};

var MAP = (function(){
    function MAP(a, f, backwards) {
        var ret = [], top = [], i;
        function doit() {
            var val = f(a[i], i);
            var is_last = val instanceof Last;
            if (is_last) val = val.v;
            if (val instanceof AtTop) {
                val = val.v;
                if (val instanceof Splice) {
                    top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
                } else {
                    top.push(val);
                }
            }
            else if (val !== skip) {
                if (val instanceof Splice) {
                    ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
                } else {
                    ret.push(val);
                }
            }
            return is_last;
        };
        if (a instanceof Array) {
            if (backwards) {
                for (i = a.length; --i >= 0;) if (doit()) break;
                ret.reverse();
                top.reverse();
            } else {
                for (i = 0; i < a.length; ++i) if (doit()) break;
            }
        }
        else {
            for (i in a) if (a.hasOwnProperty(i)) if (doit()) break;
        }
        return top.concat(ret);
    };
    MAP.at_top = function(val) { return new AtTop(val) };
    MAP.splice = function(val) { return new Splice(val) };
    MAP.last = function(val) { return new Last(val) };
    var skip = MAP.skip = {};
    function AtTop(val) { this.v = val };
    function Splice(val) { this.v = val };
    function Last(val) { this.v = val };
    return MAP;
})();

function push_uniq(array, el) {
    if (array.indexOf(el) < 0)
        array.push(el);
};

function string_template(text, props) {
    return text.replace(/\{(.+?)\}/g, function(str, p){
        return props[p];
    });
};

function remove(array, el) {
    for (var i = array.length; --i >= 0;) {
        if (array[i] === el) array.splice(i, 1);
    }
};

function mergeSort(array, cmp) {
    if (array.length < 2) return array.slice();
    function merge(a, b) {
        var r = [], ai = 0, bi = 0, i = 0;
        while (ai < a.length && bi < b.length) {
            cmp(a[ai], b[bi]) <= 0
                ? r[i++] = a[ai++]
                : r[i++] = b[bi++];
        }
        if (ai < a.length) r.push.apply(r, a.slice(ai));
        if (bi < b.length) r.push.apply(r, b.slice(bi));
        return r;
    };
    function _ms(a) {
        if (a.length <= 1)
            return a;
        var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
        left = _ms(left);
        right = _ms(right);
        return merge(left, right);
    };
    return _ms(array);
};

function set_difference(a, b) {
    return a.filter(function(el){
        return b.indexOf(el) < 0;
    });
};

function set_intersection(a, b) {
    return a.filter(function(el){
        return b.indexOf(el) >= 0;
    });
};

// this function is taken from Acorn [1], written by Marijn Haverbeke
// [1] https://github.com/marijnh/acorn
function makePredicate(words) {
    if (!(words instanceof Array)) words = words.split(" ");
    var f = "", cats = [];
    out: for (var i = 0; i < words.length; ++i) {
        for (var j = 0; j < cats.length; ++j)
            if (cats[j][0].length == words[i].length) {
                cats[j].push(words[i]);
                continue out;
            }
        cats.push([words[i]]);
    }
    function compareTo(arr) {
        if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
        f += "switch(str){";
        for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
        f += "return true}return false;";
    }
    // When there are more than three length categories, an outer
    // switch first dispatches on the lengths, to save on comparisons.
    if (cats.length > 3) {
        cats.sort(function(a, b) {return b.length - a.length;});
        f += "switch(str.length){";
        for (var i = 0; i < cats.length; ++i) {
            var cat = cats[i];
            f += "case " + cat[0].length + ":";
            compareTo(cat);
        }
        f += "}";
        // Otherwise, simply generate a flat `switch` statement.
    } else {
        compareTo(words);
    }
    return new Function("str", f);
};

function all(array, predicate) {
    for (var i = array.length; --i >= 0;)
        if (!predicate(array[i]))
            return false;
    return true;
};

function Dictionary() {
    this._values = Object.create(null);
    this._size = 0;
};
Dictionary.prototype = {
    set: function(key, val) {
        if (!this.has(key)) ++this._size;
        this._values["$" + key] = val;
        return this;
    },
    add: function(key, val) {
        if (this.has(key)) {
            this.get(key).push(val);
        } else {
            this.set(key, [ val ]);
        }
        return this;
    },
    get: function(key) { return this._values["$" + key] },
    del: function(key) {
        if (this.has(key)) {
            --this._size;
            delete this._values["$" + key];
        }
        return this;
    },
    has: function(key) { return ("$" + key) in this._values },
    each: function(f) {
        for (var i in this._values)
            f(this._values[i], i.substr(1));
    },
    size: function() {
        return this._size;
    },
    map: function(f) {
        var ret = [];
        for (var i in this._values)
            ret.push(f(this._values[i], i.substr(1)));
        return ret;
    }
};<|endoftext|>


<commit_before>/**
 * Collection of utility functions.
 *
 * This source code is licensed under the MIT-style license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * Author: Chris Zieba (zieba.chris@gmail.com)
*/

var dodgercms = dodgercms || {};

dodgercms.utils = (function() {
  'use strict';

  /**
   * Returns the possible folders based on the list of S3 keys.
   *
   * @param {Array} Keys from S3
   * @return {Array}
  */
  function getFolders(objects) {
    var folders = ['/'];

    // Loop through each object in the list
    for (var i = 0; i < objects.length; i+=1) {
      var key = objects[i].Key;

      // Split and remove last slash for directory
      var parts = key.replace(/\/\s*$/, '').split('/');

      for (var j = 0; j < parts.length; j+=1) {
        var isFolder = false;

        // If the last part in the key has a trailing slash or if the part
        // is in not the last elemenet it is a path, it is a folder
        if ((j === parts.length-1 && key.substr(-1) === '/') || j !== parts.length-1) {
          isFolder = true;
        }

        if (isFolder) {
          var folder = parts.slice(0, j+1).join('/') + '/';
          // Push only if unique
          if ($.inArray(folder, folders) < 0) {
            folders.push(folder);
          }
        }
      }
    }

    return folders;
  }

  /**
   * Creates a new folder in S3.
   *
   * @param {String} key The new key to place in S3
   * @param {String} dataBucket The bucket where the markdown resides
   * @param {String} siteBucket The front end website bucket
   * @param {Function} callback
  */
  function newFolder(key, dataBucket, siteBucket, callback) {
    dodgercms.s3.putObject(key, dataBucket, function(err, data) {
      if (err) {
        callback(err);
      } else {
        dodgercms.s3.putObject(key, siteBucket, function(err, data) {
          if (err) {
            callback(err);
          } else {
            // Check if a callback was supplied
            if (typeof callback !== 'undefined') {
              callback(null, key);
            }
          }
        });
      }
    });
  }

  return {
    newFolder: newFolder,
    getFolders: getFolders
  };
}());<commit_msg>Add some utility functions<commit_after>/**
 * Collection of utility functions.
 *
 * This source code is licensed under the MIT-style license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * Author: Chris Zieba (zieba.chris@gmail.com)
*/

var dodgercms = dodgercms || {};

dodgercms.utils = (function() {
  'use strict';

  /**
   * Returns the possible folders based on the list of S3 keys.
   *
   * @param {Array} Keys from S3
   * @return {Array}
  */
  function getFolders(objects) {
    // Default to the root folder
    var folders = ['/'];

    // Loop through each object in the list
    for (var i = 0; i < objects.length; i+=1) {
      var key = objects[i].Key;

      // Split and remove last slash for directory
      var parts = key.replace(/\/\s*$/, '').split('/');

      for (var j = 0; j < parts.length; j+=1) {
        var isFolder = false;

        // If the last part in the key has a trailing slash or if the part
        // is in not the last elemenet it is a path, it is a folder
        if ((j === parts.length-1 && key.substr(-1) === '/') || j !== parts.length-1) {
          isFolder = true;
        }

        if (isFolder) {
          var folder = parts.slice(0, j+1).join('/') + '/';
          // Push only if unique
          if ($.inArray(folder, folders) < 0) {
            folders.push(folder);
          }
        }
      }
    }

    return folders;
  }

  /**
   * Creates a new folder in S3.
   *
   * @param {String} key The new key to place in S3
   * @param {String} dataBucket The bucket where the markdown resides
   * @param {String} siteBucket The front end website bucket
   * @param {Function} callback
  */
  function newFolder(key, dataBucket, siteBucket, callback) {
    dodgercms.s3.putObject(key, dataBucket, function(err, data) {
      if (err) {
        callback(err);
      } else {
        dodgercms.s3.putObject(key, siteBucket, function(err, data) {
          if (err) {
            callback(err);
          } else {
            // Check if a callback was supplied
            if (typeof callback !== 'undefined') {
              callback(null, key);
            }
          }
        });
      }
    });
  }

  /**
   * Checks if a given key is a folder.
   *
   * @param {String} key The key name
   * @return {Boolean}
  */
  function isFolder(key) {
    return (key.substr(-1) === '/') ? true : false;
  }

  /**
   * Returns the last part (file name) in the file path.
   *
   * @param {String} key The key name
   * @return {String} A new jsTree node
  */
  function getSlug(key) {
    var parts = key.split('/');
    return parts.pop();
  }

  return {
    newFolder: newFolder,
    isFolder: isFolder,
    getSlug: getSlug,
    getFolders: getFolders
  };
}());<|endoftext|>


<commit_before>var assert = require('assert')

exports.createTypeArray = function (type) {

  if (typeof type === 'string') type = [ type ]
  return type

}

exports.ownProperty = function (obj, propertyName) {

  var properties = []
    , property
    , i

  for (i in obj) {
    properties.push(i)
  }

  while ((property = properties.pop())) {
    if (property.toLowerCase() === propertyName.toLowerCase()) {
      return obj[property]
    }
  }

  return null

}

exports.validateTrueOptions = function (name, options) {

  assert(options === true, name + ' option requires a true value or should be removed')

}

exports.validateCodeOperatorOptions = function (name, options) {

  assert(options === true || Array.isArray(options)
    , name + ' option requires a true or array value or should be removed')

  if (options === true) options = this.codeOperatorTypes

  return options

}

exports.codeOperatorTypes =
  [ '-'
  , '='
  , '!='
  ]

exports.codeOperators =
  { '-':
    { filter: function (token) {
        return token.type === 'code' && !token.buffer && !token.mustEscape
      }
    , description: 'unbuffered code operator'
    }
  , '=':
    { filter: function (token) {
        return token.type === 'code' && token.buffer && token.mustEscape
      }
    , description: 'buffered code operator'
    }
  , '!=':
    { filter: function (token) {
        return token.type === 'code' && token.buffer && !token.mustEscape
      }
    , description: 'unescaped buffered code operator'
    }
  }

exports.htmlTagBoundaryTypes =
  [ ':'
  , 'start-pug-interpolation'
  , 'end-pug-interpolation'
  , 'newline'
  , 'indent'
  , 'outdent'
  , 'eos'
  ]

exports.concatenationRegex = /.['"]\s*(\+)|(\+)\s*['"]./
<commit_msg>> Adds function to normalize package names<commit_after>var assert = require('assert')
  , path = require('path')

exports.createTypeArray = function (type) {

  if (typeof type === 'string') type = [ type ]
  return type

}

exports.normalizePackageName = function (name, prefix) {

    if (name.indexOf('\\') > -1) {
      name = path.normalize(name).replace(/\\/g, '/')
    }

    if (name.indexOf(prefix + '-') !== 0) {
      name = prefix + '-' + name
    }

    return name

}

exports.ownProperty = function (obj, propertyName) {

  var properties = []
    , property
    , i

  for (i in obj) {
    properties.push(i)
  }

  while ((property = properties.pop())) {
    if (property.toLowerCase() === propertyName.toLowerCase()) {
      return obj[property]
    }
  }

  return null

}

exports.validateTrueOptions = function (name, options) {

  assert(options === true, name + ' option requires a true value or should be removed')

}

exports.validateCodeOperatorOptions = function (name, options) {

  assert(options === true || Array.isArray(options)
    , name + ' option requires a true or array value or should be removed')

  if (options === true) options = this.codeOperatorTypes

  return options

}

exports.codeOperatorTypes =
  [ '-'
  , '='
  , '!='
  ]

exports.codeOperators =
  { '-':
    { filter: function (token) {
        return token.type === 'code' && !token.buffer && !token.mustEscape
      }
    , description: 'unbuffered code operator'
    }
  , '=':
    { filter: function (token) {
        return token.type === 'code' && token.buffer && token.mustEscape
      }
    , description: 'buffered code operator'
    }
  , '!=':
    { filter: function (token) {
        return token.type === 'code' && token.buffer && !token.mustEscape
      }
    , description: 'unescaped buffered code operator'
    }
  }

exports.htmlTagBoundaryTypes =
  [ ':'
  , 'start-pug-interpolation'
  , 'end-pug-interpolation'
  , 'newline'
  , 'indent'
  , 'outdent'
  , 'eos'
  ]

exports.concatenationRegex = /.['"]\s*(\+)|(\+)\s*['"]./
<|endoftext|>


<commit_before>'use strict';

var qs = require('qs');
var crypto = require('crypto');

var hasOwn = {}.hasOwnProperty;
var isPlainObject = require('lodash.isplainobject');
var objectAssign = require('object-assign');

var utils = module.exports = {

  isAuthKey: function(key) {
    return typeof key == 'string' && /^(?:[a-z]{2}_)?[A-z0-9]{32}$/.test(key);
  },

  isOptionsHash: function(o) {
    return isPlainObject(o) && ['api_key', 'idempotency_key', 'stripe_account'].some(function(key) {
      return o.hasOwnProperty(key);
    });
  },

  /**
   * Stringifies an Object, accommodating nested objects
   * (forming the conventional key 'parent[child]=value')
   */
  stringifyRequestData: function(data) {
    return qs.stringify(data, {arrayFormat: 'brackets'});
  },

  /**
   * Outputs a new function with interpolated object property values.
   * Use like so:
   *   var fn = makeURLInterpolator('some/url/{param1}/{param2}');
   *   fn({ param1: 123, param2: 456 }); // => 'some/url/123/456'
   */
  makeURLInterpolator: (function() {
    var rc = {
      '\n': '\\n', '\"': '\\\"',
      '\u2028': '\\u2028', '\u2029': '\\u2029',
    };
    return function makeURLInterpolator(str) {
      var cleanString = str.replace(/["\n\r\u2028\u2029]/g, function($0) {
        return rc[$0];
      });
      return function(outputs) {
        return cleanString.replace(/\{([\s\S]+?)\}/g, function($0, $1) {
          return encodeURIComponent(outputs[$1] || '');
        });
      };
    };
  }()),

  /**
   * Return the data argument from a list of arguments
   */
  getDataFromArgs: function(args) {
    if (args.length > 0) {
      if (isPlainObject(args[0]) && !utils.isOptionsHash(args[0])) {
        return args.shift();
      }
    }
    return {};
  },

  /**
   * Return the options hash from a list of arguments
   */
  getOptionsFromArgs: function(args) {
    var opts = {
      auth: null,
      headers: {},
    }
    if (args.length > 0) {
      var arg = args[args.length - 1];
      if (utils.isAuthKey(arg)) {
        opts.auth = args.pop();
      } else if (utils.isOptionsHash(arg)) {
        var params = args.pop();
        if (params.api_key) {
          opts.auth = params.api_key;
        }
        if (params.idempotency_key) {
          opts.headers['Idempotency-Key'] = params.idempotency_key;
        }
        if (params.stripe_account) {
          opts.headers['Stripe-Account'] = params.stripe_account;
        }
      }
    }
    return opts;
  },

  /**
   * Provide simple "Class" extension mechanism
   */
  protoExtend: function(sub) {
    var Super = this;
    var Constructor = hasOwn.call(sub, 'constructor') ? sub.constructor : function() {
      Super.apply(this, arguments);
    };

    // This initialization logic is somewhat sensitive to be compatible with
    // divergent JS implementations like the one found in Qt. See here for more
    // context:
    //
    // https://github.com/stripe/stripe-node/pull/334
    objectAssign(Constructor, Super);
    Constructor.prototype = Object.create(Super.prototype);
    objectAssign(Constructor.prototype, sub);

    return Constructor;
  },

  /**
   * Convert an array into an object with integer string attributes
   */
  arrayToObject: function(arr) {
    if (Array.isArray(arr)) {
      var obj = {};
      arr.map(function(item, i) {
        obj[i.toString()] = item;
      });
      return obj;
    }
    return arr;
  },

  /**
  * Secure compare, from https://github.com/freewil/scmp
  */
  secureCompare: function(a, b) {
    var a = asBuffer(a);
    var b = asBuffer(b);

    // return early here if buffer lengths are not equal since timingSafeEqual
    // will throw if buffer lengths are not equal
    if (a.length !== b.length) {
      return false;
    }

    // use crypto.timingSafeEqual if available (since Node.js v6.6.0),
    // otherwise use our own scmp-internal function.
    if (crypto.timingSafeEqual) {
      return crypto.timingSafeEqual(a, b);
    }

    var len = a.length;
    var result = 0;

    for (var i = 0; i < len; ++i) {
      result |= a[i] ^ b[i];
    }
    return result === 0;
  },
};

function asBuffer(thing) {
  if (Buffer.isBuffer(thing)) {
    return thing;
  }

  return Buffer.from ? Buffer.from(thing) : new Buffer(thing);
}
<commit_msg>fixes #352 isOptionsHash - TypeError<commit_after>'use strict';

var qs = require('qs');
var crypto = require('crypto');

var hasOwn = {}.hasOwnProperty;
var isPlainObject = require('lodash.isplainobject');
var objectAssign = require('object-assign');

var utils = module.exports = {

  isAuthKey: function(key) {
    return typeof key == 'string' && /^(?:[a-z]{2}_)?[A-z0-9]{32}$/.test(key);
  },

  isOptionsHash: function(o) {
    return isPlainObject(o) && ['api_key', 'idempotency_key', 'stripe_account'].some(function(key) {
      return hasOwn.call(o, key);
    });
  },

  /**
   * Stringifies an Object, accommodating nested objects
   * (forming the conventional key 'parent[child]=value')
   */
  stringifyRequestData: function(data) {
    return qs.stringify(data, {arrayFormat: 'brackets'});
  },

  /**
   * Outputs a new function with interpolated object property values.
   * Use like so:
   *   var fn = makeURLInterpolator('some/url/{param1}/{param2}');
   *   fn({ param1: 123, param2: 456 }); // => 'some/url/123/456'
   */
  makeURLInterpolator: (function() {
    var rc = {
      '\n': '\\n', '\"': '\\\"',
      '\u2028': '\\u2028', '\u2029': '\\u2029',
    };
    return function makeURLInterpolator(str) {
      var cleanString = str.replace(/["\n\r\u2028\u2029]/g, function($0) {
        return rc[$0];
      });
      return function(outputs) {
        return cleanString.replace(/\{([\s\S]+?)\}/g, function($0, $1) {
          return encodeURIComponent(outputs[$1] || '');
        });
      };
    };
  }()),

  /**
   * Return the data argument from a list of arguments
   */
  getDataFromArgs: function(args) {
    if (args.length > 0) {
      if (isPlainObject(args[0]) && !utils.isOptionsHash(args[0])) {
        return args.shift();
      }
    }
    return {};
  },

  /**
   * Return the options hash from a list of arguments
   */
  getOptionsFromArgs: function(args) {
    var opts = {
      auth: null,
      headers: {},
    }
    if (args.length > 0) {
      var arg = args[args.length - 1];
      if (utils.isAuthKey(arg)) {
        opts.auth = args.pop();
      } else if (utils.isOptionsHash(arg)) {
        var params = args.pop();
        if (params.api_key) {
          opts.auth = params.api_key;
        }
        if (params.idempotency_key) {
          opts.headers['Idempotency-Key'] = params.idempotency_key;
        }
        if (params.stripe_account) {
          opts.headers['Stripe-Account'] = params.stripe_account;
        }
      }
    }
    return opts;
  },

  /**
   * Provide simple "Class" extension mechanism
   */
  protoExtend: function(sub) {
    var Super = this;
    var Constructor = hasOwn.call(sub, 'constructor') ? sub.constructor : function() {
      Super.apply(this, arguments);
    };

    // This initialization logic is somewhat sensitive to be compatible with
    // divergent JS implementations like the one found in Qt. See here for more
    // context:
    //
    // https://github.com/stripe/stripe-node/pull/334
    objectAssign(Constructor, Super);
    Constructor.prototype = Object.create(Super.prototype);
    objectAssign(Constructor.prototype, sub);

    return Constructor;
  },

  /**
   * Convert an array into an object with integer string attributes
   */
  arrayToObject: function(arr) {
    if (Array.isArray(arr)) {
      var obj = {};
      arr.map(function(item, i) {
        obj[i.toString()] = item;
      });
      return obj;
    }
    return arr;
  },

  /**
  * Secure compare, from https://github.com/freewil/scmp
  */
  secureCompare: function(a, b) {
    var a = asBuffer(a);
    var b = asBuffer(b);

    // return early here if buffer lengths are not equal since timingSafeEqual
    // will throw if buffer lengths are not equal
    if (a.length !== b.length) {
      return false;
    }

    // use crypto.timingSafeEqual if available (since Node.js v6.6.0),
    // otherwise use our own scmp-internal function.
    if (crypto.timingSafeEqual) {
      return crypto.timingSafeEqual(a, b);
    }

    var len = a.length;
    var result = 0;

    for (var i = 0; i < len; ++i) {
      result |= a[i] ^ b[i];
    }
    return result === 0;
  },
};

function asBuffer(thing) {
  if (Buffer.isBuffer(thing)) {
    return thing;
  }

  return Buffer.from ? Buffer.from(thing) : new Buffer(thing);
}
<|endoftext|>


<commit_before>exports.isServer  = process.title.indexOf('node') > -1
exports.isClient = !exports.isServer

Object.defineProperty(exports, 'requestContext', {
  get: function() {
    return exports.isClient ? window.app : process.domain.app
  }
})

exports.debug = function() {
  if (exports.isClient && typeof window !== 'undefined' && typeof window.swac !== 'undefined' && window.swac.debug === true)
    console.log.apply(console, arguments)
}

exports.aquireFragments = function(start, fragments, accept) {
  if (!accept) accept = function() { return true; }
  var treeWalker = document.createTreeWalker(start, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT, {
    acceptNode: function(node) {
      if (node.nodeType === Node.ELEMENT_NODE) {
        for (var i = 0; i < node.attributes.length; ++i) {
          var attr = node.attributes.item(i)
          if (attr.nodeName.lastIndexOf('data-bind-', 0) === 0) {
            var name = attr.nodeName.substr(10)
              , fragment = fragments[parseInt(attr.value)]
            fragment.attribute = node.attributes.getNamedItem(name)
          }
        }
        return NodeFilter.FILTER_SKIP
      }
      return accept(node) &&
        node.nodeValue[0] == '-'
          ? NodeFilter.FILTER_ACCEPT
          : NodeFilter.FILTER_SKIP
    }
  })
  while(treeWalker.nextNode()) {
    var value = treeWalker.currentNode.nodeValue, res
    if (res = value.match(/\-(\{(\d+))|((\d+)\})/)) {
      var fragment = fragments[res[2] || res[4]]
      if (res.index) /* closing */ fragment.endNode = treeWalker.currentNode
      else           /* opening */ fragment.startNode = treeWalker.currentNode
    }
  }
}

var EventEmitter = require('./eventemitter')
exports.eventify = function(obj) {
  EventEmitter.eventify(obj)
}

// returns a random v4 UUID
// from: https://gist.github.com/982883
exports.UUID = function b(
  a                  // placeholder
){
  return a           // if the placeholder was passed, return
    ? (              // a random number from 0 to 15
      a ^            // unless b is 8,
      Math.random()  // in which case
      * 16           // a random number from
      >> a/4         // 8 to 11
      ).toString(16) // in hexadecimal
    : (              // or otherwise a concatenated string:
      [1e7] +        // 10000000 +
      -1e3 +         // -1000 +
      -4e3 +         // -4000 +
      -8e3 +         // -80000000 +
      -1e11          // -100000000000,
      ).replace(     // replacing
        /[018]/g,    // zeroes, ones, and eights with
        b            // random hex digits
      )
}

exports.series = function(arr, fn, done) {
  var arr = arr.slice()
  !function async() {
    if (arr.length === 0) return done ? done() : undefined
    fn(arr.shift(), async, arr.length)
  }()
}

exports.chain = function(fn) {
  return new Chain(fn)
}

function Chain(fn) {
  var that = this
  this.queue = []
  this.waiting = false
  this.args = []
  this.callback = function() {
    that.args = Array.prototype.slice.call(arguments)
    var next = that.queue.shift()
    if (!next) return that.waiting = false
    that.waiting = true
    next.apply(null, that.args.concat(that.callback))
  }
  this.queue.push(fn)
  this.callback()
}

Chain.prototype.chain = function(fn) {
  this.queue.push(fn)
  if (!this.waiting) this.callback.apply(this, this.args)
  return this
}

exports.Wait = new EventEmitter
var wait = 0, waited = false
exports.wait = function(label) {
  waited = true
  ++wait
  // if (label) console.time(label)
  // console.log('wait ' + wait)
  // console.log((new Error).stack.split("\n")[2])
}
exports.done = function(label) {
  --wait
  // if (label) console.timeEnd(label)
  // console.log('done ' + wait)
  // console.log((new Error).stack.split("\n")[2])
  if (wait === 0) {
    exports.Wait.emit('ready')
    exports.Wait.removeAllListeners()
  }
}
exports.ready = function(fn) {
  if (exports.isReady) fn()
  else exports.Wait.on('ready', fn)
}
Object.defineProperty(exports, 'isReady', {
  enumerable: true,
  get: function() {
    return wait === 0 && waited
  }
})

var Factory = exports.Factory = function(/* base[, args...] */) {
  this.args = Array.prototype.slice.call(arguments)
  this.base = this.args.shift()
}

require('implode').register('Factory', Factory, ['args', 'base'])

Factory.prototype.new = function() {
  var args = Array.prototype.slice.call(arguments)
    , that = this
  function F() {
    return that.base.apply(this, that.args.concat(args))
  }
  F.prototype = this.base.prototype
  return new F()
}<commit_msg>Windows Compatibility<commit_after>exports.isServer = typeof module !== 'undefined' && module.exports
exports.isClient = !exports.isServer

Object.defineProperty(exports, 'requestContext', {
  get: function() {
    return exports.isClient ? window.app : process.domain.app
  }
})

exports.debug = function() {
  if (exports.isClient && typeof window !== 'undefined' && typeof window.swac !== 'undefined' && window.swac.debug === true)
    console.log.apply(console, arguments)
}

exports.aquireFragments = function(start, fragments, accept) {
  if (!accept) accept = function() { return true; }
  var treeWalker = document.createTreeWalker(start, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT, {
    acceptNode: function(node) {
      if (node.nodeType === Node.ELEMENT_NODE) {
        for (var i = 0; i < node.attributes.length; ++i) {
          var attr = node.attributes.item(i)
          if (attr.nodeName.lastIndexOf('data-bind-', 0) === 0) {
            var name = attr.nodeName.substr(10)
              , fragment = fragments[parseInt(attr.value)]
            fragment.attribute = node.attributes.getNamedItem(name)
          }
        }
        return NodeFilter.FILTER_SKIP
      }
      return accept(node) &&
        node.nodeValue[0] == '-'
          ? NodeFilter.FILTER_ACCEPT
          : NodeFilter.FILTER_SKIP
    }
  })
  while(treeWalker.nextNode()) {
    var value = treeWalker.currentNode.nodeValue, res
    if (res = value.match(/\-(\{(\d+))|((\d+)\})/)) {
      var fragment = fragments[res[2] || res[4]]
      if (res.index) /* closing */ fragment.endNode = treeWalker.currentNode
      else           /* opening */ fragment.startNode = treeWalker.currentNode
    }
  }
}

var EventEmitter = require('./eventemitter')
exports.eventify = function(obj) {
  EventEmitter.eventify(obj)
}

// returns a random v4 UUID
// from: https://gist.github.com/982883
exports.UUID = function b(
  a                  // placeholder
){
  return a           // if the placeholder was passed, return
    ? (              // a random number from 0 to 15
      a ^            // unless b is 8,
      Math.random()  // in which case
      * 16           // a random number from
      >> a/4         // 8 to 11
      ).toString(16) // in hexadecimal
    : (              // or otherwise a concatenated string:
      [1e7] +        // 10000000 +
      -1e3 +         // -1000 +
      -4e3 +         // -4000 +
      -8e3 +         // -80000000 +
      -1e11          // -100000000000,
      ).replace(     // replacing
        /[018]/g,    // zeroes, ones, and eights with
        b            // random hex digits
      )
}

exports.series = function(arr, fn, done) {
  var arr = arr.slice()
  !function async() {
    if (arr.length === 0) return done ? done() : undefined
    fn(arr.shift(), async, arr.length)
  }()
}

exports.chain = function(fn) {
  return new Chain(fn)
}

function Chain(fn) {
  var that = this
  this.queue = []
  this.waiting = false
  this.args = []
  this.callback = function() {
    that.args = Array.prototype.slice.call(arguments)
    var next = that.queue.shift()
    if (!next) return that.waiting = false
    that.waiting = true
    next.apply(null, that.args.concat(that.callback))
  }
  this.queue.push(fn)
  this.callback()
}

Chain.prototype.chain = function(fn) {
  this.queue.push(fn)
  if (!this.waiting) this.callback.apply(this, this.args)
  return this
}

exports.Wait = new EventEmitter
var wait = 0, waited = false
exports.wait = function(label) {
  waited = true
  ++wait
  // if (label) console.time(label)
  // console.log('wait ' + wait)
  // console.log((new Error).stack.split("\n")[2])
}
exports.done = function(label) {
  --wait
  // if (label) console.timeEnd(label)
  // console.log('done ' + wait)
  // console.log((new Error).stack.split("\n")[2])
  if (wait === 0) {
    exports.Wait.emit('ready')
    exports.Wait.removeAllListeners()
  }
}
exports.ready = function(fn) {
  if (exports.isReady) fn()
  else exports.Wait.on('ready', fn)
}
Object.defineProperty(exports, 'isReady', {
  enumerable: true,
  get: function() {
    return wait === 0 && waited
  }
})

var Factory = exports.Factory = function(/* base[, args...] */) {
  this.args = Array.prototype.slice.call(arguments)
  this.base = this.args.shift()
}

require('implode').register('Factory', Factory, ['args', 'base'])

Factory.prototype.new = function() {
  var args = Array.prototype.slice.call(arguments)
    , that = this
  function F() {
    return that.base.apply(this, that.args.concat(args))
  }
  F.prototype = this.base.prototype
  return new F()
}<|endoftext|>