<commit_before>const glob = require('glob');
const path = require('path');
const Logger = require("./lib/util/smashLogger");
const Config = require("./lib/core/config");
const Binder = require("./lib/core/binder");
const logger = new Logger("SmashJsServerless");
const SmashError = require("./lib/util/smashError");
const EXT_JS = ".js";
const DEEP_EXT_JS = "**/*.js";
const FILE_EXT_JS = "*.js";
const PATHS = {
    MIDDLEWARE: "lib/middleware/*",
    HANDLER: "controller",
    DATABASE: "database",
    UTIL: "util",
    HELPER: "helper",
    SINGLETON: "singleton",
    GLOBAL: "global",
};
const AWS_REGION = "AWS_REGION";

class Smash {
    constructor() {
        this._init();
    }

    _init() {
        this._binder = new Binder();
        this._config = null;
        this._middlewares = null;
        this._magics = [];
        this._handlers = null;
        this._containerEnv = {};
        this._path = "";
        this._singletons = {};
    }

    _clearExpose() {
        for (let i = 0, length = this._magics.length; i < length; i++) {
            this[this._magics[i]] = null;
        }
        this._magics = [];
        return this;
    }

    _processExpose(module) {
        if (typeof module !== 'object' || typeof module.expose !== 'function') {
            logger.error("Middlewares must be object with a function called expose, " + Logger.typeOf(module, module.expose));
            throw new Error("Middlewares must be object with a function called expose, " + Logger.typeOf(module, module.expose));
        }
        const expose = module.expose();
        const that = this;
        for (let i = 0, length = expose.length; i < length; i++) {
            if (expose[i].functionName && this[expose[i].functionName]) {
                logger.error("Function " + expose[i].functionName + " already exist in smash, overwrite is not allowed");
                throw new Error("Function " + expose[i].functionName + " already exist in smash, overwrite is not allowed");
            }
            if (expose[i].getterName && this[expose[i].getterName]) {
                logger.error("Getter " + expose[i].getterName + " already exist in smash, overwrite is not allowed");
                throw new Error("Getter " + expose[i].getterName + " already exist in smash, overwrite is not allowed");
            }
            if (expose[i].functionName) {
                this[expose[i].functionName] = function () {
                    const returnedValue = module[expose[i].function].apply(module, arguments);
                    if (expose[i].return === true) {
                        return returnedValue;
                    } else {
                        return that;
                    }
                };
                this._magics.push(expose[i].functionName);
            }
            if (expose[i].getterName) {
                this[expose[i].getterName] = module[expose[i].getter];
                this._magics.push(expose[i].getterName);
            }
        }
        return this;
    }

    _registerMiddlewares() {
        this._clearExpose();
        this._middlewares = [];
        const files = glob.sync(path.join(__dirname, PATHS.MIDDLEWARE, FILE_EXT_JS));
        for (let i = 0, length = files.length; i < length; i++) {
            const Module = require(path.resolve(files[i]));
            const module = new Module();
            this._processExpose(module);
            this._middlewares.push(module);
            logger.info("Register middleware: " + module.constructor.name);
        }
        return this;
    }

    loadGlobals({ ignoreOverride, silent } = { ignoreOverride: false, silent: false }) {
        const files = glob.sync(path.join(this._path, PATHS.GLOBAL, FILE_EXT_JS));
        for (let i = 0, length = files.length; i < length; i++) {
            const filePath = path.resolve(files[i]);
            const { name } = path.parse(filePath);
            const globalToExpose = require(filePath);
            if (ignoreOverride === false && global[name]) {
                throw new Error("Global variable " + name + " is already defined");
            }
            global[name] = globalToExpose;
            Object.freeze(globalToExpose);
            if (silent === false) {
                logger.info("Load global: " + name);
            }
        }
        return this;
    }

    clearGlobals() {
        const files = glob.sync(path.join(this._path, PATHS.GLOBAL, FILE_EXT_JS));
        for (let i = 0, length = files.length; i < length; i++) {
            const filePath = path.resolve(files[i]);
            const { name } = path.parse(filePath);
            delete global[name];
        }
        return this;
    }

    shutdown() {
        this.clearGlobals();
        this._clearExpose();
        this._init();
    }

    _clearHandlers() {
        const files = glob.sync(path.resolve(path.join(this._path, PATHS.HANDLER, DEEP_EXT_JS)));
        for (let i = 0, length = files.length; i < length; i++) {
            delete require.cache[require.resolve(path.resolve(files[i]))]
        }
        return this;
    }

    _registerHandlers() {
        this._clearHandlers();
        this._handlers = [];
        const files = glob.sync(path.resolve(path.join(this._path, PATHS.HANDLER, DEEP_EXT_JS)));
        for (let i = 0, length = files.length; i < length; i++) {
            try {
                this._handlers.push(require(path.resolve(files[i])));
            } catch (error) {
                logger.error("Failed to register handler " + files[i], error);
                throw new Error("Failed to boot smash");
            }
        }
        logger.info("Handler loaded: " + files.length);
        return this;
    }

    getHandlers() {
        let handlers = [];
        for (let i = 0, length = this._middlewares.length; i < length; i++) {
            handlers = handlers.concat(this._middlewares[i].getHandlers());
        }
        return handlers;
    }

    getRoutes() {
        for (let i = 0, length = this._middlewares.length; i < length; i++) {
            if (this._middlewares[i].getRoutes) {
                return this._middlewares[i].getRoutes();
            }
        }
        throw new Error("No middleware found to get routes");
    }

    _buildEnv(context) {
        delete this._env;
        this._env = {};
        Object.assign(this._env, this._containerEnv);
        if (typeof module === 'object') {
            Object.assign(this._env, context);
        }
        return this;
    }

    _buildContainerEnv(env = {}) {
        Object.assign(this._containerEnv, env);
        Object.assign(this._containerEnv, process.env);
        this._buildEnv();
        return this;
    }

    boot({ path = process.cwd(), global = {}, env = {} } = { path: process.cwd(), global: {}, env: {} }) {
        this._path = path;
        this._config = new Config(this._path);
        this.loadGlobals(global);
        this._buildContainerEnv(env);
        this._registerMiddlewares();
        this._registerHandlers();
    }

    handleEvent(event, context, callback) {
        if (this._middlewares === null) {
            logger.error("Smash has not been booted, you must call boot() first", event);
            callback(new Error("Smash has not been booted, you must call boot() first"));
        } else {
            this._buildEnv(context);
            for (let i = 0, length = this._middlewares.length; i < length; i++) {
                if (this._middlewares[i].isEvent(event)) {
                    this._middlewares[i].handleEvent(event, context, callback);
                    return this;
                }
            }
            //FIX ME use smashError instead
            logger.error("No middleware found to process event", event);
            callback(new Error("No middleware found to process event"));
        }
        return this;
    }

    get env() {
        return this._env;
    }

    getEnv(key) {
        return this._env[key];
    }

    getEnvs(keys) {
        const array = [];
        keys.forEach((key) => {
            array.push(this.getEnv(key));
        });
        return array;
    }

    getRegion() {
        return this._env[AWS_REGION];
    }

    setEnv(key, value) {
        if (!this._env) {
            this._env = {};
        }
        this._env[key] = value;
        return this;
    }

    loadModule(dir, module) {
        try {
            return require(path.resolve(path.join(this._path, dir, module + EXT_JS)));
        } catch (error) {
            logger.error("Failed to load module " + module, error, error.stack);
            throw error;
        }
    }

    util(module) {
        if (typeof module !== 'string' || module.length === 0) {
            throw new Error("First parameter of util must be a valid string, " + Logger.typeOf(module));
        }
        return this.loadModule(PATHS.UTIL, module);
    }

    helper(module) {
        if (typeof module !== 'string' || module.length === 0) {
            throw new Error("First parameter of helper must be a valid string, " + Logger.typeOf(module));
        }
        return this.loadModule(PATHS.HELPER, module);
    }

    _loadSingletonModule(module) {
        try {
            return this.loadModule(PATHS.SINGLETON, module);
        } catch (error) {
            return require(module);
        }
    }

    _instanciateModule(module) {
        if (module.constructor) {
            return new module();
        }
        return module;
    }

    _bootSingletonModule(module) {
        if (this._singletons[module].load) {
            this._singletons[module].load().catch(error => {
                logger.error("Failed to boot singleton module " + module, error);
            });
        }
    }

    singleton(module) {
        if (typeof module !== 'string' || module.length === 0) {
            throw new Error("First parameter of singleton must be a valid string, " + Logger.typeOf(module));
        }
        if (this._singletons[module]) {
            return this._singletons[module];
        } else {
            try {
                const requiredModule = this._loadSingletonModule(module);
                this._singletons[module] = this._instanciateModule(requiredModule);
                this._bootSingletonModule(module);
            } catch (error) {
                throw new Error("Cannot find module " + module);
            }
        }
    }

    global(module) {
        if (typeof module !== 'string' || module.length === 0) {
            throw new Error("First parameter of global must be a valid string, " + Logger.typeOf(module));
        }
        return this.loadModule(PATHS.GLOBAL, module);
    }

    database(module) {
        if (typeof module !== 'string' || module.length === 0) {
            throw new Error("First parameter of database must be a valid string, " + Logger.typeOf(module));
        }
        return this.loadModule(PATHS.DATABASE, module);
    }

    get config() {
        return this._config;
    }

    setCurrentEvent(event) {
        this._currentEvent = event;
        return this;
    }

    get binder() {
        return this._binder;
    }

    registerRequiredRule(...args) {
        return this.binder.registerRequiredRule(...args);
    }

    registerMergeRule(...args) {
        return this.binder.registerMergeRule(...args);
    }

    registerCleanRule(...args) {
        return this.binder.registerCleanRule(...args);
    }

    mergeObject(...args) {
        if (args.length === 2 && this._currentEvent && this._currentEvent.route && this._currentEvent.route.action) {
            args.unshift(this._currentEvent.route.action);
        }
        return this.binder.mergeObject(...args);
    }

    clean(...args) {
        return this.binder.clean(...args);
    }

    get DynamodbModel() {
        return require(path.resolve(path.join(__dirname, "lib/util/dynamodbModel.js")));
    }

    get Logger() {
        return require(path.resolve(path.join(__dirname, "lib/util/smashLogger.js")));
    }

    get Console() {
        logger.deprecated("smash.Console is deprecated, use smash.Logger in the future");
        return this.Logger;
    }

    set Console(console) {

    }

    smashError(...args) {
        logger.deprecated("Method smashError(options) is deprecated, use smash.errorUtil");
        return new SmashError.SmashError(...args);
    }

    get SmashError() {
        return SmashError;
    }

    logger(namespace) {
        return new Logger(namespace);
    }

    //FIX ME remove for the next major ??
    get codes() {
        return {
            badRequest: 400,
            unauthorized: 401,
            forbidden: 403,
            notFound: 404,
            conflict: 409,
            internalServerError: 500,
            notImplemented: 501,
            serviceUnavailable: 502
        };
    }
}

if (!global.smash) {
    global.smash = new Smash();
}
module.exports = global.smash;

<commit_msg>Remove useless extension when load module<commit_after>const glob = require('glob');
const path = require('path');
const Logger = require("./lib/util/smashLogger");
const Config = require("./lib/core/config");
const Binder = require("./lib/core/binder");
const logger = new Logger("SmashJsServerless");
const SmashError = require("./lib/util/smashError");
const DEEP_EXT_JS = "**/*.js";
const FILE_EXT_JS = "*.js";
const PATHS = {
    MIDDLEWARE: "lib/middleware/*",
    HANDLER: "controller",
    DATABASE: "database",
    UTIL: "util",
    HELPER: "helper",
    SINGLETON: "singleton",
    GLOBAL: "global",
};
const AWS_REGION = "AWS_REGION";

class Smash {
    constructor() {
        this._init();
    }

    _init() {
        this._binder = new Binder();
        this._config = null;
        this._middlewares = null;
        this._magics = [];
        this._handlers = null;
        this._containerEnv = {};
        this._path = "";
        this._singletons = {};
    }

    _clearExpose() {
        for (let i = 0, length = this._magics.length; i < length; i++) {
            this[this._magics[i]] = null;
        }
        this._magics = [];
        return this;
    }

    _processExpose(module) {
        if (typeof module !== 'object' || typeof module.expose !== 'function') {
            logger.error("Middlewares must be object with a function called expose, " + Logger.typeOf(module, module.expose));
            throw new Error("Middlewares must be object with a function called expose, " + Logger.typeOf(module, module.expose));
        }
        const expose = module.expose();
        const that = this;
        for (let i = 0, length = expose.length; i < length; i++) {
            if (expose[i].functionName && this[expose[i].functionName]) {
                logger.error("Function " + expose[i].functionName + " already exist in smash, overwrite is not allowed");
                throw new Error("Function " + expose[i].functionName + " already exist in smash, overwrite is not allowed");
            }
            if (expose[i].getterName && this[expose[i].getterName]) {
                logger.error("Getter " + expose[i].getterName + " already exist in smash, overwrite is not allowed");
                throw new Error("Getter " + expose[i].getterName + " already exist in smash, overwrite is not allowed");
            }
            if (expose[i].functionName) {
                this[expose[i].functionName] = function () {
                    const returnedValue = module[expose[i].function].apply(module, arguments);
                    if (expose[i].return === true) {
                        return returnedValue;
                    } else {
                        return that;
                    }
                };
                this._magics.push(expose[i].functionName);
            }
            if (expose[i].getterName) {
                this[expose[i].getterName] = module[expose[i].getter];
                this._magics.push(expose[i].getterName);
            }
        }
        return this;
    }

    _registerMiddlewares() {
        this._clearExpose();
        this._middlewares = [];
        const files = glob.sync(path.join(__dirname, PATHS.MIDDLEWARE, FILE_EXT_JS));
        for (let i = 0, length = files.length; i < length; i++) {
            const Module = require(path.resolve(files[i]));
            const module = new Module();
            this._processExpose(module);
            this._middlewares.push(module);
            logger.info("Register middleware: " + module.constructor.name);
        }
        return this;
    }

    loadGlobals({ ignoreOverride, silent } = { ignoreOverride: false, silent: false }) {
        const files = glob.sync(path.join(this._path, PATHS.GLOBAL, FILE_EXT_JS));
        for (let i = 0, length = files.length; i < length; i++) {
            const filePath = path.resolve(files[i]);
            const { name } = path.parse(filePath);
            const globalToExpose = require(filePath);
            if (ignoreOverride === false && global[name]) {
                throw new Error("Global variable " + name + " is already defined");
            }
            global[name] = globalToExpose;
            Object.freeze(globalToExpose);
            if (silent === false) {
                logger.info("Load global: " + name);
            }
        }
        return this;
    }

    clearGlobals() {
        const files = glob.sync(path.join(this._path, PATHS.GLOBAL, FILE_EXT_JS));
        for (let i = 0, length = files.length; i < length; i++) {
            const filePath = path.resolve(files[i]);
            const { name } = path.parse(filePath);
            delete global[name];
        }
        return this;
    }

    shutdown() {
        this.clearGlobals();
        this._clearExpose();
        this._init();
    }

    _clearHandlers() {
        const files = glob.sync(path.resolve(path.join(this._path, PATHS.HANDLER, DEEP_EXT_JS)));
        for (let i = 0, length = files.length; i < length; i++) {
            delete require.cache[require.resolve(path.resolve(files[i]))]
        }
        return this;
    }

    _registerHandlers() {
        this._clearHandlers();
        this._handlers = [];
        const files = glob.sync(path.resolve(path.join(this._path, PATHS.HANDLER, DEEP_EXT_JS)));
        for (let i = 0, length = files.length; i < length; i++) {
            try {
                this._handlers.push(require(path.resolve(files[i])));
            } catch (error) {
                logger.error("Failed to register handler " + files[i], error);
                throw new Error("Failed to boot smash");
            }
        }
        logger.info("Handler loaded: " + files.length);
        return this;
    }

    getHandlers() {
        let handlers = [];
        for (let i = 0, length = this._middlewares.length; i < length; i++) {
            handlers = handlers.concat(this._middlewares[i].getHandlers());
        }
        return handlers;
    }

    getRoutes() {
        for (let i = 0, length = this._middlewares.length; i < length; i++) {
            if (this._middlewares[i].getRoutes) {
                return this._middlewares[i].getRoutes();
            }
        }
        throw new Error("No middleware found to get routes");
    }

    _buildEnv(context) {
        delete this._env;
        this._env = {};
        Object.assign(this._env, this._containerEnv);
        if (typeof module === 'object') {
            Object.assign(this._env, context);
        }
        return this;
    }

    _buildContainerEnv(env = {}) {
        Object.assign(this._containerEnv, env);
        Object.assign(this._containerEnv, process.env);
        this._buildEnv();
        return this;
    }

    boot({ path = process.cwd(), global = {}, env = {} } = { path: process.cwd(), global: {}, env: {} }) {
        this._path = path;
        this._config = new Config(this._path);
        this.loadGlobals(global);
        this._buildContainerEnv(env);
        this._registerMiddlewares();
        this._registerHandlers();
    }

    handleEvent(event, context, callback) {
        if (this._middlewares === null) {
            logger.error("Smash has not been booted, you must call boot() first", event);
            callback(new Error("Smash has not been booted, you must call boot() first"));
        } else {
            this._buildEnv(context);
            for (let i = 0, length = this._middlewares.length; i < length; i++) {
                if (this._middlewares[i].isEvent(event)) {
                    this._middlewares[i].handleEvent(event, context, callback);
                    return this;
                }
            }
            //FIX ME use smashError instead
            logger.error("No middleware found to process event", event);
            callback(new Error("No middleware found to process event"));
        }
        return this;
    }

    get env() {
        return this._env;
    }

    getEnv(key) {
        return this._env[key];
    }

    getEnvs(keys) {
        const array = [];
        keys.forEach((key) => {
            array.push(this.getEnv(key));
        });
        return array;
    }

    getRegion() {
        return this._env[AWS_REGION];
    }

    setEnv(key, value) {
        if (!this._env) {
            this._env = {};
        }
        this._env[key] = value;
        return this;
    }

    loadModule(dir, module) {
        try {
            return require(path.resolve(path.join(this._path, dir, module)));
        } catch (error) {
            logger.error("Failed to load module " + module, error, error.stack);
            throw error;
        }
    }

    util(module) {
        if (typeof module !== 'string' || module.length === 0) {
            throw new Error("First parameter of util must be a valid string, " + Logger.typeOf(module));
        }
        return this.loadModule(PATHS.UTIL, module);
    }

    helper(module) {
        if (typeof module !== 'string' || module.length === 0) {
            throw new Error("First parameter of helper must be a valid string, " + Logger.typeOf(module));
        }
        return this.loadModule(PATHS.HELPER, module);
    }

    _loadSingletonModule(module) {
        try {
            return this.loadModule(PATHS.SINGLETON, module);
        } catch (error) {
            return require(module);
        }
    }

    _instanciateModule(module) {
        if (module.constructor) {
            return new module();
        }
        return module;
    }

    _bootSingletonModule(module) {
        if (this._singletons[module].load) {
            this._singletons[module].load().catch(error => {
                logger.error("Failed to boot singleton module " + module, error);
            });
        }
    }

    singleton(module) {
        if (typeof module !== 'string' || module.length === 0) {
            throw new Error("First parameter of singleton must be a valid string, " + Logger.typeOf(module));
        }
        if (this._singletons[module]) {
            return this._singletons[module];
        } else {
            try {
                const requiredModule = this._loadSingletonModule(module);
                this._singletons[module] = this._instanciateModule(requiredModule);
                this._bootSingletonModule(module);
            } catch (error) {
                throw new Error("Cannot find module " + module);
            }
        }
    }

    global(module) {
        if (typeof module !== 'string' || module.length === 0) {
            throw new Error("First parameter of global must be a valid string, " + Logger.typeOf(module));
        }
        return this.loadModule(PATHS.GLOBAL, module);
    }

    database(module) {
        if (typeof module !== 'string' || module.length === 0) {
            throw new Error("First parameter of database must be a valid string, " + Logger.typeOf(module));
        }
        return this.loadModule(PATHS.DATABASE, module);
    }

    get config() {
        return this._config;
    }

    setCurrentEvent(event) {
        this._currentEvent = event;
        return this;
    }

    get binder() {
        return this._binder;
    }

    registerRequiredRule(...args) {
        return this.binder.registerRequiredRule(...args);
    }

    registerMergeRule(...args) {
        return this.binder.registerMergeRule(...args);
    }

    registerCleanRule(...args) {
        return this.binder.registerCleanRule(...args);
    }

    mergeObject(...args) {
        if (args.length === 2 && this._currentEvent && this._currentEvent.route && this._currentEvent.route.action) {
            args.unshift(this._currentEvent.route.action);
        }
        return this.binder.mergeObject(...args);
    }

    clean(...args) {
        return this.binder.clean(...args);
    }

    get DynamodbModel() {
        return require(path.resolve(path.join(__dirname, "lib/util/dynamodbModel.js")));
    }

    get Logger() {
        return require(path.resolve(path.join(__dirname, "lib/util/smashLogger.js")));
    }

    get Console() {
        logger.deprecated("smash.Console is deprecated, use smash.Logger in the future");
        return this.Logger;
    }

    set Console(console) {

    }

    smashError(...args) {
        logger.deprecated("Method smashError(options) is deprecated, use smash.errorUtil");
        return new SmashError.SmashError(...args);
    }

    get SmashError() {
        return SmashError;
    }

    logger(namespace) {
        return new Logger(namespace);
    }

    //FIX ME remove for the next major ??
    get codes() {
        return {
            badRequest: 400,
            unauthorized: 401,
            forbidden: 403,
            notFound: 404,
            conflict: 409,
            internalServerError: 500,
            notImplemented: 501,
            serviceUnavailable: 502
        };
    }
}

if (!global.smash) {
    global.smash = new Smash();
}
module.exports = global.smash;

<|endoftext|>


<commit_before>/**
 *  queue.js
 */

/**
 *  deps
 */
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;

/**
 *  export class
 */
module.exports = Queue;

/**
 *  constructor
 */
function Queue(options) {
  if (!(this instanceof Queue))
    return new Queue(options);

  EventEmitter.call(this);
  options = options || {};
  this.concurrency = options.concurrency || 1;
  this.timeout = options.timeout || 0;
  this.pending = 0;
  this.session = 0;
  this.jobs = [];
}
inherits(Queue, EventEmitter);

/**
 *  expose selected array methods
 */
var arrayMethods = [
  'push',
  'unshift',
  'splice',
  'pop',
  'shift',
  'slice',
  'reverse',
  'indexOf',
  'lastIndexOf'
];

for (var method in arrayMethods) {
  (function(method) {
    Queue.prototype[method] = function() {
      return Array.prototype[method].apply(this.jobs, arguments);
    };
  })(arrayMethods[method]);
}

/**
 *  expose array.length
 */
Queue.prototype.__defineGetter__('length', function() {
 return this.pending + this.jobs.length;
});

/**
 *  start processing the queue
 */
Queue.prototype.start = function() {
  if (this.pending === this.concurrency) {
    return;
  }

  if (this.jobs.length === 0) {
    if (this.pending === 0) {
      done.call(this);
    }
    return;
  }

  var job = this.jobs.shift();
  var self = this;
  var once = true;
  var session = this.session;
  var timeoutId = null;
  var didTimeout = false;

  var next = function(err, result) {
    if (once && self.session === session) {
      once = false;
      self.pending--;
      if (timeoutId !== null) {
        clearTimeout(timeoutId);
      }
      if (err) {
        self.emit('error', err, job);
      } else if (didTimeout === false) {
        self.emit('success', result, job);
      }
      if (self.pending === 0 && self.jobs.length === 0) {
        done.call(self);
      } else {
        self.start();
      }
    }
  };

  if (this.timeout) {
    timeoutId = setTimeout(function() {
      didTimeout = true;
      if (self.listeners('timeout').length > 0) {
        self.emit('timeout', next, job);
      } else {
        next();
      }
    }, this.timeout);
  }

  this.pending++;
  job(next);

  if (this.jobs.length > 0) {
    this.start();
  }
};

/**
 *  clear the queue including any running jobs
 */
Queue.prototype.end = function(err) {
  if (this.jobs.length || this.pending) {
    this.jobs = [];
    this.pending = 0;
    this.session++;
    done.call(this, err);
  }
};

/**
 *  all done
 */
function done(err) {
  this.emit('end', err);
  this.session++;
};
<commit_msg>use @vvo's suggestion to use Object.defineProperty<commit_after>/**
 *  queue.js
 */

/**
 *  deps
 */
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;

/**
 *  export class
 */
module.exports = Queue;

/**
 *  constructor
 */
function Queue(options) {
  if (!(this instanceof Queue))
    return new Queue(options);

  EventEmitter.call(this);
  options = options || {};
  this.concurrency = options.concurrency || 1;
  this.timeout = options.timeout || 0;
  this.pending = 0;
  this.session = 0;
  this.jobs = [];
}
inherits(Queue, EventEmitter);

/**
 *  expose selected array methods
 */
var arrayMethods = [
  'push',
  'unshift',
  'splice',
  'pop',
  'shift',
  'slice',
  'reverse',
  'indexOf',
  'lastIndexOf'
];

for (var method in arrayMethods) {
  (function(method) {
    Queue.prototype[method] = function() {
      return Array.prototype[method].apply(this.jobs, arguments);
    };
  })(arrayMethods[method]);
}

/**
 *  expose array.length
 */
Object.defineProperty(Queue.prototype, 'length', { get: function() {
  return this.pending + this.jobs.length;
}});

/**
 *  start processing the queue
 */
Queue.prototype.start = function() {
  if (this.pending === this.concurrency) {
    return;
  }

  if (this.jobs.length === 0) {
    if (this.pending === 0) {
      done.call(this);
    }
    return;
  }

  var job = this.jobs.shift();
  var self = this;
  var once = true;
  var session = this.session;
  var timeoutId = null;
  var didTimeout = false;

  var next = function(err, result) {
    if (once && self.session === session) {
      once = false;
      self.pending--;
      if (timeoutId !== null) {
        clearTimeout(timeoutId);
      }
      if (err) {
        self.emit('error', err, job);
      } else if (didTimeout === false) {
        self.emit('success', result, job);
      }
      if (self.pending === 0 && self.jobs.length === 0) {
        done.call(self);
      } else {
        self.start();
      }
    }
  };

  if (this.timeout) {
    timeoutId = setTimeout(function() {
      didTimeout = true;
      if (self.listeners('timeout').length > 0) {
        self.emit('timeout', next, job);
      } else {
        next();
      }
    }, this.timeout);
  }

  this.pending++;
  job(next);

  if (this.jobs.length > 0) {
    this.start();
  }
};

/**
 *  clear the queue including any running jobs
 */
Queue.prototype.end = function(err) {
  if (this.jobs.length || this.pending) {
    this.jobs = [];
    this.pending = 0;
    this.session++;
    done.call(this, err);
  }
};

/**
 *  all done
 */
function done(err) {
  this.emit('end', err);
  this.session++;
};
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var assert = require('assert');
var Parser = require('jade/lib/parser.js');
var jade = require('jade/lib/runtime.js');
var React = require('react');
var staticModule = require('static-module');
var resolve = require('resolve');
var uglify = require('uglify-js');
var Compiler = require('./lib/compiler.js');
var JavaScriptCompressor = require('./lib/java-script-compressor.js');

var reactRuntimePath = require.resolve('react');

exports = (module.exports = browserifySupport);
function browserifySupport(options, extra) {
  function transform(filename) {
    function clientRequire(path) {
      return require(clientRequire.resolve(path));
    }
    clientRequire.resolve = function (path) {
      return resolve.sync(path, {
        basedir: path.dirname(filename)
      });
    };
    return staticModule({
      'react-jade': {
        compile: function (jadeSrc, localOptions) {
          localOptions = localOptions || {};
          for (var key in options) {
            if ((key in options) && !(key in localOptions))
            localOptions[key] = options[key];
          }
          localOptions.outputFile = filename;
          return compileClient(jadeSrc, localOptions);
        },
        compileFile: function (jadeFile, localOptions) {
          localOptions = localOptions || {};
          for (var key in options) {
            if ((key in options) && !(key in localOptions))
            localOptions[key] = options[key];
          }
          localOptions.outputFile = filename;
          return compileFileClient(jadeFile, localOptions);
        }
      }
    }, {
      vars: {
        __dirname: path.dirname(filename),
        __filename: path.resolve(filename),
        path: path,
        require: clientRequire
      }
    });
  }
  if (typeof options === 'string') {
    var file = options;
    options = extra || {};
    return transform(file);
  } else {
    options = options || {};
    return transform;
  }
}

function parse(str, options) {
  var options = options || {};
  var parser = new Parser(str, options.filename, options);
  var tokens;
  try {
    // Parse
    tokens = parser.parse();
  } catch (err) {
    parser = parser.context();
    jade.rethrow(err, parser.filename, parser.lexer.lineno, parser.input);
  }
  var compiler = new Compiler(tokens);

  var js = 'exports = function (locals, components) {' +
    'function getReactClass(name, args) { ' +
    'return (components && React.isValidClass(components[name])) ' +
        '? components[name].apply(components[name], args) ' +
        ': (React.DOM[name]) ? React.DOM[name].apply(React.DOM, args) : React.DOM.div.apply(React.DOM, args)' +
    '};' +
    'function jade_join_classes(val) {' +
    'return Array.isArray(val) ? val.map(jade_join_classes).filter(function (val) { return val != null && val !== ""; }).join(" ") : val;' +
    '};' +
    'var jade_mixins = {};' +
    'var jade_interp;' +
    'jade_variables(locals);' +
    compiler.compile() +
    '}';

  // Check that the compiled JavaScript code is valid thus far.
  // uglify-js throws very cryptic errors when it fails to parse code.
  try {
    Function('', js);
  } catch (ex) {
    console.log(js);
    throw ex;
  }

  var ast = uglify.parse(js, {filename: options.filename});

  ast.figure_out_scope();
  ast = ast.transform(uglify.Compressor({
    sequences: false,   // join consecutive statemets with the “comma operator"
    properties: true,   // optimize property access: a["foo"] → a.foo
    dead_code: true,    // discard unreachable code
    unsafe: true,       // some unsafe optimizations (see below)
    conditionals: true, // optimize if-s and conditional expressions
    comparisons: true,  // optimize comparisonsx
    evaluate: true,     // evaluate constant expressions
    booleans: true,     // optimize boolean expressions
    loops: true,        // optimize loops
    unused: true,       // drop unused variables/functions
    hoist_funs: true,   // hoist function declarations
    hoist_vars: false,  // hoist variable declarations
    if_return: true,    // optimize if-s followed by return/continue
    join_vars: false,   // join var declarations
    cascade: true,      // try to cascade `right` into `left` in sequences
    side_effects: true, // drop side-effect-free statements
    warnings: false,     // warn about potentially dangerous optimizations/code
    global_defs: {}     // global definitions));
  }));

  ast = ast.transform(new JavaScriptCompressor());

  ast.figure_out_scope();
  var globals = ast.globals.map(function (node, name) {
    return name;
  }).filter(function (name) {
    return name !== 'jade_variables' && name !== 'exports' && name !== 'Array' && name !== 'React';
  });

  js = ast.print_to_string({
    beautify: true,
    comments: true,
    indent_level: 2
  });
  assert(/^exports *= */.test(js));
  assert(/jade_variables\(locals\)/.test(js));

  js = js.replace(/\n? *jade_variables\(locals\);?/, globals.map(function (g) {
    return '  var ' + g + ' = ' + JSON.stringify(g) + ' in locals ? locals.' + g + ' : jade_globals_' + g + ';';
  }).join('\n'));
  return globals.map(function (g) {
    return 'var jade_globals_' + g + ' = typeof ' + g + ' === "undefined" ? undefined : ' + g + ';\n';
  }).join('') + js.replace(/^exports *= */, 'return ');
}

function parseFile(filename, options) {
  var str = fs.readFileSync(filename, 'utf8').toString();
  var options = options || {};
  options.filename = path.resolve(filename);
  return parse(str, options);
}

exports.compile = function(str, options){
  options = options || { filename: '' }
  return Function('React', parse(str, options))(React);
}

exports.compileFile = compileFile;
function compileFile(filename, options) {
  return Function('React', parseFile(filename, options))(React);
}

exports.compileClient = compileClient;
function compileClient(str, options){
  options = options || { filename: '' };
  var react = options.outputFile ? path.relative(path.dirname(options.outputFile), reactRuntimePath) : reactRuntimePath;
  return '(function (React) {\n  ' +
    parse(str, options).split('\n').join('\n  ') +
    '\n}(typeof React !== "undefined" ? React : require("' + react.replace(/^([^\.])/, './$1').replace(/\\/g, '/') + '")))';
}

exports.compileFileClient = compileFileClient;
function compileFileClient(filename, options) {
  var str = fs.readFileSync(filename, 'utf8').toString();
  var options = options || {};
  options.filename = path.resolve(filename);
  return compileClient(str, options);
}
<commit_msg>Allow compileClient to disable require.<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var assert = require('assert');
var Parser = require('jade/lib/parser.js');
var jade = require('jade/lib/runtime.js');
var React = require('react');
var staticModule = require('static-module');
var resolve = require('resolve');
var uglify = require('uglify-js');
var Compiler = require('./lib/compiler.js');
var JavaScriptCompressor = require('./lib/java-script-compressor.js');

var reactRuntimePath = require.resolve('react');

exports = (module.exports = browserifySupport);
function browserifySupport(options, extra) {
  function transform(filename) {
    function clientRequire(path) {
      return require(clientRequire.resolve(path));
    }
    clientRequire.resolve = function (path) {
      return resolve.sync(path, {
        basedir: path.dirname(filename)
      });
    };
    return staticModule({
      'react-jade': {
        compile: function (jadeSrc, localOptions) {
          localOptions = localOptions || {};
          for (var key in options) {
            if ((key in options) && !(key in localOptions))
            localOptions[key] = options[key];
          }
          localOptions.outputFile = filename;
          return compileClient(jadeSrc, localOptions);
        },
        compileFile: function (jadeFile, localOptions) {
          localOptions = localOptions || {};
          for (var key in options) {
            if ((key in options) && !(key in localOptions))
            localOptions[key] = options[key];
          }
          localOptions.outputFile = filename;
          return compileFileClient(jadeFile, localOptions);
        }
      }
    }, {
      vars: {
        __dirname: path.dirname(filename),
        __filename: path.resolve(filename),
        path: path,
        require: clientRequire
      }
    });
  }
  if (typeof options === 'string') {
    var file = options;
    options = extra || {};
    return transform(file);
  } else {
    options = options || {};
    return transform;
  }
}

function parse(str, options) {
  var options = options || {};
  var parser = new Parser(str, options.filename, options);
  var tokens;
  try {
    // Parse
    tokens = parser.parse();
  } catch (err) {
    parser = parser.context();
    jade.rethrow(err, parser.filename, parser.lexer.lineno, parser.input);
  }
  var compiler = new Compiler(tokens);

  var js = 'exports = function (locals, components) {' +
    'function getReactClass(name, args) { ' +
    'return (components && React.isValidClass(components[name])) ' +
        '? components[name].apply(components[name], args) ' +
        ': (React.DOM[name]) ? React.DOM[name].apply(React.DOM, args) : React.DOM.div.apply(React.DOM, args)' +
    '};' +
    'function jade_join_classes(val) {' +
    'return Array.isArray(val) ? val.map(jade_join_classes).filter(function (val) { return val != null && val !== ""; }).join(" ") : val;' +
    '};' +
    'var jade_mixins = {};' +
    'var jade_interp;' +
    'jade_variables(locals);' +
    compiler.compile() +
    '}';

  // Check that the compiled JavaScript code is valid thus far.
  // uglify-js throws very cryptic errors when it fails to parse code.
  try {
    Function('', js);
  } catch (ex) {
    console.log(js);
    throw ex;
  }

  var ast = uglify.parse(js, {filename: options.filename});

  ast.figure_out_scope();
  ast = ast.transform(uglify.Compressor({
    sequences: false,   // join consecutive statemets with the “comma operator"
    properties: true,   // optimize property access: a["foo"] → a.foo
    dead_code: true,    // discard unreachable code
    unsafe: true,       // some unsafe optimizations (see below)
    conditionals: true, // optimize if-s and conditional expressions
    comparisons: true,  // optimize comparisonsx
    evaluate: true,     // evaluate constant expressions
    booleans: true,     // optimize boolean expressions
    loops: true,        // optimize loops
    unused: true,       // drop unused variables/functions
    hoist_funs: true,   // hoist function declarations
    hoist_vars: false,  // hoist variable declarations
    if_return: true,    // optimize if-s followed by return/continue
    join_vars: false,   // join var declarations
    cascade: true,      // try to cascade `right` into `left` in sequences
    side_effects: true, // drop side-effect-free statements
    warnings: false,     // warn about potentially dangerous optimizations/code
    global_defs: {}     // global definitions));
  }));

  ast = ast.transform(new JavaScriptCompressor());

  ast.figure_out_scope();
  var globals = ast.globals.map(function (node, name) {
    return name;
  }).filter(function (name) {
    return name !== 'jade_variables' && name !== 'exports' && name !== 'Array' && name !== 'React';
  });

  js = ast.print_to_string({
    beautify: true,
    comments: true,
    indent_level: 2
  });
  assert(/^exports *= */.test(js));
  assert(/jade_variables\(locals\)/.test(js));

  js = js.replace(/\n? *jade_variables\(locals\);?/, globals.map(function (g) {
    return '  var ' + g + ' = ' + JSON.stringify(g) + ' in locals ? locals.' + g + ' : jade_globals_' + g + ';';
  }).join('\n'));
  return globals.map(function (g) {
    return 'var jade_globals_' + g + ' = typeof ' + g + ' === "undefined" ? undefined : ' + g + ';\n';
  }).join('') + js.replace(/^exports *= */, 'return ');
}

function parseFile(filename, options) {
  var str = fs.readFileSync(filename, 'utf8').toString();
  var options = options || {};
  options.filename = path.resolve(filename);
  return parse(str, options);
}

exports.compile = function(str, options){
  options = options || { filename: '' }
  return Function('React', parse(str, options))(React);
}

exports.compileFile = compileFile;
function compileFile(filename, options) {
  return Function('React', parseFile(filename, options))(React);
}

exports.compileClient = compileClient;
function compileClient(str, options){
  options = options || { filename: '' };
  var react = options.outputFile ? path.relative(path.dirname(options.outputFile), reactRuntimePath) : reactRuntimePath;

  if (options.globalReact) {
    return '(function (React) {\n  ' +
      parse(str, options).split('\n').join('\n  ') +
      '\n}(React))';
  } else {
    return '(function (React) {\n  ' +
      parse(str, options).split('\n').join('\n  ') +
      '\n}(typeof React !== "undefined" ? React : require("' + react.replace(/^([^\.])/, './$1').replace(/\\/g, '/') + '")))';
  }
}

exports.compileFileClient = compileFileClient;
function compileFileClient(filename, options) {
  var str = fs.readFileSync(filename, 'utf8').toString();
  var options = options || {};
  options.filename = path.resolve(filename);
  return compileClient(str, options);
}
<|endoftext|>


<commit_before>var async       = require('async')
;

function plugin(schema) {
    /****************************************************************
     * Pre-Hooks
     * These hooks run before an instance has been updated
     * Puesto que el `iteree` consiste meramente en la ejecucion del
     * metodo pertinente en cada una de las iteraciones, los hooks
     * agregados a la coleccion de `pre-create` deben adecuarse a la
     * signatura `function(doc, cb)`
     */

    schema.preCreateMethods = [];
    schema.preCreate = function(fn){ schema.preCreateMethods.push(fn) };
    schema.methods.runPreMethods = function(methods, doc, callback){
        async.eachSeries(
            methods,
            function(method, signal){ method(doc, signal) },
            function(err){
                if (err){ throw err; }
                callback();
            }
        );
    };

    /****************************************************************
     * Post-Hooks
     * These hooks run after an instance has been updated
     * Puesto que el `iteree` consiste meramente en la ejecucion del
     * metodo pertinente en cada una de las iteraciones, los hooks
     * agregados a la coleccion de `pre-create` deben adecuarse a la
     * signatura `function(doc, cb)`
     */
    schema.postCreateMethods = [];
    schema.postCreate = function(fn){ schema.postCreateMethods.push(fn) };
    schema.methods.runPostMethods = function(methods, doc){
        async.eachSeries(
            methods,
            function(method, signal){ method(doc, signal) },
            function(err){
                if (err){ throw err; }
            }
        );
    };

    /****************************************************************
     * SETUP
     * En el seno de las funciones definidas, `self` se refiere al
     * documento mismo sobre el cual se opera las `hooks`.
     */
    schema.pre('validate', function(next){
            const DOC = this;
            DOC._wasNew = DOC.isNew;
            if (DOC.isNew) DOC.runPreMethods(schema.preCreateMethods, DOC, ()=>next());
            return;
        }
    );
    schema.post('save', function(){
            const DOC = this;
            if (DOC._wasNew) DOC.runPostMethods(schema.postCreateMethods, DOC);
            return;
        }
    );
}

module.exports = plugin;<commit_msg>Renombrado 'runPreMethods' a 'runPreCreateMethods'.<commit_after>var async       = require('async')
;

function plugin(schema) {
    /****************************************************************
     * Pre-Hooks
     * These hooks run before an instance has been updated
     * Puesto que el `iteree` consiste meramente en la ejecucion del
     * metodo pertinente en cada una de las iteraciones, los hooks
     * agregados a la coleccion de `pre-create` deben adecuarse a la
     * signatura `function(doc, cb)`
     */

    schema.preCreateMethods = [];
    schema.preCreate = function(fn){ schema.preCreateMethods.push(fn) };
    schema.methods.runPreCreateMethods = function(methods, doc, callback){
        async.eachSeries(
            methods,
            function(method, signal){ method(doc, signal) },
            function(err){
                if (err){ throw err; }
                callback();
            }
        );
    };

    /****************************************************************
     * Post-Hooks
     * These hooks run after an instance has been updated
     * Puesto que el `iteree` consiste meramente en la ejecucion del
     * metodo pertinente en cada una de las iteraciones, los hooks
     * agregados a la coleccion de `pre-create` deben adecuarse a la
     * signatura `function(doc, cb)`
     */
    schema.postCreateMethods = [];
    schema.postCreate = function(fn){ schema.postCreateMethods.push(fn) };
    schema.methods.runPostCreateMethods = function(methods, doc){
        async.eachSeries(
            methods,
            function(method, signal){ method(doc, signal) },
            function(err){
                if (err){ throw err; }
            }
        );
    };

    /****************************************************************
     * SETUP
     * En el seno de las funciones definidas, `self` se refiere al
     * documento mismo sobre el cual se opera las `hooks`.
     */
    schema.pre('validate', function(next){
            const DOC = this;
            DOC._wasNew = DOC.isNew;
            if (DOC.isNew) DOC.runPreCreateMethods(schema.preCreateMethods, DOC, ()=>next());
            return;
        }
    );
    schema.post('save', function(){
            const DOC = this;
            if (DOC._wasNew) DOC.runCreatePostMethods(schema.postCreateMethods, DOC);
            return;
        }
    );
}

module.exports = plugin;<|endoftext|>


<commit_before>/* globals require */

module.exports = function(gulp, modules) {

  'use strict';

  const fs = require('fs');
  const path = require('path');
  const yaml = require('js-yaml');
  const _ = require('lodash');
  let projectDir = path.join(__dirname, '../../');
  let projectConfig = {};

  // Load config from project.yml.
  try {
    projectConfig = yaml.safeLoad(fs.readFileSync(path.join(projectDir, 'project.yml'), 'utf8'));
  } catch (e) {}

  // Get local project config from local.project.yml and merge.
  try {
    let localConfig = yaml.safeLoad(fs.readFileSync(path.join(projectDir, 'local.project.yml'), 'utf8'));
    projectConfig = _.defaultsDeep(localConfig, projectConfig);
  } catch (e) {}

  /**
   * Sets environment variables defined in project.yml.
   *
   * @param {Object} projectConfig - Project configuration defined in
   *   project.yml.
   */
  function initEnvVars(projectConfig) {
    let defaults = _.get(projectConfig, 'env.default', {});

    _.forIn(projectConfig.env, function (vars, env) {
      let envVars = _.defaultsDeep(projectConfig.env[env], defaults);

      _.forIn(envVars, function (value, key) {
        process.env['ENV_' + env.toUpperCase() + '_' + key.toUpperCase()] = value;
      });
    });
  }

  // Set environment variables.
  initEnvVars(projectConfig);

  // Get available task modules.
  let modulesAvailable = fs.readdirSync(path.join(__dirname, 'gulp-tasks'));
  let lintModulesAvailable = [];

  // Loop over modules and include them.
  modulesAvailable.forEach( function (filename) {
    let moduleName = path.basename(filename, '.js')

    // If modules array is empty or if this module is specified, include it.
    if (!modules.length || modules.indexOf(moduleName) >= 0) {
      // Include the task module:
      require('./gulp-tasks/' + filename)(gulp, projectConfig, projectDir);

      if (['eslint', 'phpcs'].indexOf(moduleName) >= 0) {
        lintModulesAvailable.push(moduleName);
      }
    }
  });

  /**
   * Run all linting tests.
   */
  gulp.task('lint', 'Run all coding standard and style checking tools.', lintModulesAvailable);

};
<commit_msg>Log yaml.safeLoad errors.<commit_after>/* globals require */

module.exports = function(gulp, modules) {

  'use strict';

  const fs = require('fs');
  const path = require('path');
  const yaml = require('js-yaml');
  const _ = require('lodash');
  let projectDir = path.join(__dirname, '../../');
  let projectConfig = {};

  // Load config from project.yml.
  try {
    projectConfig = yaml.safeLoad(fs.readFileSync(path.join(projectDir, 'project.yml'), 'utf8'));
  } catch (e) {
    console.log(e.message);
  }

  // Get local project config from local.project.yml and merge.
  try {
    let localConfig = yaml.safeLoad(fs.readFileSync(path.join(projectDir, 'local.project.yml'), 'utf8'));
    projectConfig = _.defaultsDeep(localConfig, projectConfig);
  } catch (e) {
    console.log(e.message);
  }

  /**
   * Sets environment variables defined in project.yml.
   *
   * @param {Object} projectConfig - Project configuration defined in
   *   project.yml.
   */
  function initEnvVars(projectConfig) {
    let defaults = _.get(projectConfig, 'env.default', {});

    _.forIn(projectConfig.env, function (vars, env) {
      let envVars = _.defaultsDeep(projectConfig.env[env], defaults);

      _.forIn(envVars, function (value, key) {
        process.env['ENV_' + env.toUpperCase() + '_' + key.toUpperCase()] = value;
      });
    });
  }

  // Set environment variables.
  initEnvVars(projectConfig);

  // Get available task modules.
  let modulesAvailable = fs.readdirSync(path.join(__dirname, 'gulp-tasks'));
  let lintModulesAvailable = [];

  // Loop over modules and include them.
  modulesAvailable.forEach( function (filename) {
    let moduleName = path.basename(filename, '.js')

    // If modules array is empty or if this module is specified, include it.
    if (!modules.length || modules.indexOf(moduleName) >= 0) {
      // Include the task module:
      require('./gulp-tasks/' + filename)(gulp, projectConfig, projectDir);

      if (['eslint', 'phpcs'].indexOf(moduleName) >= 0) {
        lintModulesAvailable.push(moduleName);
      }
    }
  });

  /**
   * Run all linting tests.
   */
  gulp.task('lint', 'Run all coding standard and style checking tools.', lintModulesAvailable);

};
<|endoftext|>


<commit_before>(function () {
    'use strict';

    // The initialize function must be run each time a new page is loaded
    Office.initialize = function (reason) {
        $(document).ready(function () {
            app.initialize();

            sendRequest();
        });
    };

    function getSubjectRequest(id) {
        // Return a GetItem operation request for the subject of the specified item.
        var result =
     '<?xml version="1.0" encoding="utf-8"?>' +
     '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
     '               xmlns:xsd="http://www.w3.org/2001/XMLSchema"' +
     '               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"' +
     '               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">' +
     '  <soap:Header>' +
     '    <RequestServerVersion Version="Exchange2013" xmlns="http://schemas.microsoft.com/exchange/services/2006/types" soap:mustUnderstand="0" />' +
     '  </soap:Header>' +
     '  <soap:Body>' +
     '    <GetItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">' +
     '      <ItemShape>' +
     '        <t:BaseShape>IdOnly</t:BaseShape>' +
     '        <t:BodyType>Text</t:BodyType>' +
     '        <t:AdditionalProperties>' +
     '            <t:FieldURI FieldURI="item:Body"/>' +
     '        </t:AdditionalProperties>' +
     '      </ItemShape>' +
     '      <ItemIds><t:ItemId Id="' + id + '"/></ItemIds>' +
     '    </GetItem>' +
     '  </soap:Body>' +
     '</soap:Envelope>';

        return result;
    }

    function sendRequest() {
        var mailbox = Office.context.mailbox;
        mailbox.makeEwsRequestAsync(getSubjectRequest(mailbox.item.itemId), callback);
    }

    function callback(asyncResult) {
        var result = asyncResult.value;
        var context = asyncResult.context;

        console.log(result);
    }

})();
<commit_msg>new stuff<commit_after>(function () {
    'use strict';

    // The initialize function must be run each time a new page is loaded
    Office.initialize = function (reason) {
        $(document).ready(function () {
            app.initialize();

            sendRequest();
        });
    };

    function getSubjectRequest(id) {
        // Return a GetItem operation request for the subject of the specified item.
        var result =
     '<?xml version="1.0" encoding="utf-8"?>' +
     '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' +
     '               xmlns:xsd="http://www.w3.org/2001/XMLSchema"' +
     '               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"' +
     '               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">' +
     '  <soap:Header>' +
     '    <RequestServerVersion Version="Exchange2013" xmlns="http://schemas.microsoft.com/exchange/services/2006/types" soap:mustUnderstand="0" />' +
     '  </soap:Header>' +
     '  <soap:Body>' +
     '    <GetItem xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">' +
     '      <ItemShape>' +
     '        <t:BaseShape>IdOnly</t:BaseShape>' +
     '        <t:BodyType>Text</t:BodyType>' +
     '        <t:AdditionalProperties>' +
     '            <t:FieldURI FieldURI="item:Body"/>' +
     '        </t:AdditionalProperties>' +
     '      </ItemShape>' +
     '      <ItemIds><t:ItemId Id="' + id + '"/></ItemIds>' +
     '    </GetItem>' +
     '  </soap:Body>' +
     '</soap:Envelope>';

        return result;
    }

    function sendRequest() {
        var mailbox = Office.context.mailbox;
        mailbox.makeEwsRequestAsync(getSubjectRequest(mailbox.item.itemId), callback);
    }

    function callback(asyncResult) {
        var result = asyncResult.value;
        var context = asyncResult.context;
        var xmlDoc;

        console.log(result);

        if (window.DOMParser) {
            var parser = new DOMParser();
            xmlDoc = parser.parseFromString(result, "text/xml");
        } else { // Internet Explorer
            xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
            xmlDoc.async = false;
            xmlDoc.loadXML(result);
        }

        console.log(xmlDoc);
    }

})();
<|endoftext|>


<commit_before>var elements = [];

function parseData(data) {
    var $data = $(data);
    var elements = [];

    $("Element", $data).each(function() {
        var element = {
            heading: $("Heading", this).text(),
            question: $("Question", this).text(),
            tag: $("Tag", this).text(),
            options: [],
            default: null,
            score: $("Score", this).text(),
            validate: $("Validate", this).text()
        };

        $("Option", this).each(function() {
            var option = {
                label: $("Label", this).text(),
                value: $("Value", this).text(),
                default: $("Default", this).length > 0
            };

            if (option.default)
                element.default = option.value;

            element.options.push(option);
        });

        elements.push(element);
    });

    return elements;
}

function buildElements() {
    var panels = {};

    $.each(elements, function(i, element) {
        var $item = $("

").addClass("list-group-item clearfix").attr("id", element.tag);
        $item.append(element.question);

        var $group = $("

").addClass("btn-group pull-right").attr('data-toggle', 'buttons');

        $.each(element.options, function(j, option) {
            var $label = $("").addClass("btn btn-default").text(option.label);
            var $input = $("<input></input>").attr("type", "radio").attr("name", element.tag).attr("autocomplete", "off").val(option.value);

            if (option.default)
            {
                $label.addClass("active");
                $input.attr("checked", "checked");
            }

            $input.on("change", function() {
                doScore();
                checkDefault(element.tag);
            });

            $label.append($input);
            $group.append($label);
        });

        $item.append($group);

        if (!(element.heading in panels))
        {
            var $panel = $("

").addClass("panel panel-default");
            var $heading = $("

").addClass("panel-heading").text(element.heading);
            var $list = $("

").addClass("list-group");

            var $error = $("

").addClass("list-group-item list-group-item-danger error").hide();
            $list.append($error);

            $panel.append($heading);
            $panel.append($list);

            panels[element.heading] = $panel;
        }

        $(".list-group", panels[element.heading]).append($item);
    });

    $.each(panels, function(heading, $panel) {
        $("#elements").append($panel);
    });
}

function checkDefault(tag) {
    var answer = $("input[name=" + tag + "]:checked").val();

    $.each(elements, function(i, element) {
        if (element.tag == tag) {
            var $item = $("#" + tag);
            $item.removeClass('list-group-item-info');

            if (answer != element.default)
                $item.addClass('list-group-item-info');

            return true;
        }
    });
}

function loadAnswers(answers) {
    $.each(answers, function(tag, answer) {
        $("input[name=" + tag + "]").attr("checked", "").parent().removeClass("active");
        $("input[name=" + tag + "][value=" + answer + "]").attr("checked", "checked").parent().addClass("active");

        checkDefault(tag);
    });
}

$(function() {
    $.get("data/trashtrek-et.xml", function(data) {
        elements = parseData(data);
        buildElements();
        loadAnswers(JSON.parse($("#formanswers").val()));
        doScore();
    });

    $("#submitform").on("submit", function(e) {
        var score = doScore();
        var good = doValidate();
        if (good) {
            $("#submit").removeClass("btn-danger").addClass("btn-success");

            var answers = JSON.stringify(getAnswers());
            $("#formanswers").val(answers);

            var alertStr = $("#submitform input").map(function() {
                return $(this).attr("name") + "=" + $(this).val();
            }).get().join("\n");

            alert(alertStr);
        }
        else {
            $("#submit").addClass("btn-danger");

            // http://stackoverflow.com/a/6677069
            $("html, body").animate({
                scrollTop: $(".error:visible", "#elements").first().parents(".panel").offset().top - $("#elements").offset().top
            }, "slow");

            e.preventDefault();
        }
    });
});

// Used in data functions
function isEmpty(val) {
    return (val === undefined || val == null || val.length <= 0) ? true : false;
}

function getAnswers() {
    var answers = {};
    $.each(elements, function(i, element) {
        answers[element.tag] = $("input[name=" + element.tag + "]:checked").val();
    });
    return answers;
}

function getScore() {
    var context = {
        answers: getAnswers()
    };

    var score = 0;

    // http://stackoverflow.com/a/25859853
    function evalInContext(js, context) {
        //# Return the results of the in-line anonymous function we .call with the passed context
        return function() { return eval(js); }.call(context);
    }

    $.each(elements, function(i, element) {
        evalInContext(element.score, context);
    });

    return Math.max(0, score);
}

function getErrors() {
    var context = {
        answers: getAnswers()
    };

    // http://stackoverflow.com/a/25859853
    function evalInContext(js, context) {
        //# Return the results of the in-line anonymous function we .call with the passed context
        return function() { return eval(js); }.call(context);
    }

    var errors = {};
    $.each(elements, function(i, element) {
        var ret = evalInContext(element.validate, context);

        if (ret && ret.highlight) {
            errors[element.tag] = ret.msg;
        }
    });

    return errors;
}

function doScore() {
    var score = getScore();
    $("#score").text(score);
    $("#formscore").val(score);
    return score;
}

function doValidate() {
    $icon = $("").addClass("glyphicon glyphicon-alert").html(" ");

    var errors = getErrors();
    var errorcnt = 0;

    $(".error", "#elements").data("current", false);

    $.each(elements, function(i, element) {
        var $panel = $("#" + element.tag, "#elements").parents(".panel");
        var $error = $(".error", $panel);

        if (element.tag in errors) {
            errorcnt++;

            $error.text(errors[element.tag]);
            $error.prepend($icon.clone());
            if ($error.is(":hidden"))
                $error.slideDown();

            $error.data("current", true);
        }
        else {
            if ($error.is(":visible") && !$error.data("current"))
                $error.slideUp();
        }
    });

    return errorcnt == 0;
}
<commit_msg>Bold words instead of all caps<commit_after>var elements = [];

function parseData(data) {
    var $data = $(data);
    var elements = [];

    $("Element", $data).each(function() {
        var element = {
            heading: $("Heading", this).text(),
            question: $("Question", this).text(),
            tag: $("Tag", this).text(),
            options: [],
            default: null,
            score: $("Score", this).text(),
            validate: $("Validate", this).text()
        };

        $("Option", this).each(function() {
            var option = {
                label: $("Label", this).text(),
                value: $("Value", this).text(),
                default: $("Default", this).length > 0
            };

            if (option.default)
                element.default = option.value;

            element.options.push(option);
        });

        elements.push(element);
    });

    return elements;
}

function emphasize(str) {
    return str.replace(/[A-ZÕÄÖÜ]+(?![a-zõäöü])/g, function(match, offset) {
        if (offset > 0)
            return "" + match.toLowerCase() + "";
        else
            return "" + match[0] + match.substr(1).toLowerCase() + "";
    });
}

function buildElements() {
    var panels = {};

    $.each(elements, function(i, element) {
        var $item = $("

").addClass("list-group-item clearfix").attr("id", element.tag);
        $item.append(emphasize(element.question));

        var $group = $("

").addClass("btn-group pull-right").attr('data-toggle', 'buttons');

        $.each(element.options, function(j, option) {
            var $label = $("").addClass("btn btn-default").text(option.label);
            var $input = $("<input></input>").attr("type", "radio").attr("name", element.tag).attr("autocomplete", "off").val(option.value);

            if (option.default)
            {
                $label.addClass("active");
                $input.attr("checked", "checked");
            }

            $input.on("change", function() {
                doScore();
                checkDefault(element.tag);
            });

            $label.append($input);
            $group.append($label);
        });

        $item.append($group);

        if (!(element.heading in panels))
        {
            var $panel = $("

").addClass("panel panel-default");
            var $heading = $("

").addClass("panel-heading").text(element.heading);
            var $list = $("

").addClass("list-group");

            var $error = $("

").addClass("list-group-item list-group-item-danger error").hide();
            $list.append($error);

            $panel.append($heading);
            $panel.append($list);

            panels[element.heading] = $panel;
        }

        $(".list-group", panels[element.heading]).append($item);
    });

    $.each(panels, function(heading, $panel) {
        $("#elements").append($panel);
    });
}

function checkDefault(tag) {
    var answer = $("input[name=" + tag + "]:checked").val();

    $.each(elements, function(i, element) {
        if (element.tag == tag) {
            var $item = $("#" + tag);
            $item.removeClass('list-group-item-info');

            if (answer != element.default)
                $item.addClass('list-group-item-info');

            return true;
        }
    });
}

function loadAnswers(answers) {
    $.each(answers, function(tag, answer) {
        $("input[name=" + tag + "]").attr("checked", "").parent().removeClass("active");
        $("input[name=" + tag + "][value=" + answer + "]").attr("checked", "checked").parent().addClass("active");

        checkDefault(tag);
    });
}

$(function() {
    $.get("data/trashtrek-et.xml", function(data) {
        elements = parseData(data);
        buildElements();
        loadAnswers(JSON.parse($("#formanswers").val()));
        doScore();
    });

    $("#submitform").on("submit", function(e) {
        var score = doScore();
        var good = doValidate();
        if (good) {
            $("#submit").removeClass("btn-danger").addClass("btn-success");

            var answers = JSON.stringify(getAnswers());
            $("#formanswers").val(answers);

            var alertStr = $("#submitform input").map(function() {
                return $(this).attr("name") + "=" + $(this).val();
            }).get().join("\n");

            alert(alertStr);
        }
        else {
            $("#submit").addClass("btn-danger");

            // http://stackoverflow.com/a/6677069
            $("html, body").animate({
                scrollTop: $(".error:visible", "#elements").first().parents(".panel").offset().top - $("#elements").offset().top
            }, "slow");

            e.preventDefault();
        }
    });
});

// Used in data functions
function isEmpty(val) {
    return (val === undefined || val == null || val.length <= 0) ? true : false;
}

function getAnswers() {
    var answers = {};
    $.each(elements, function(i, element) {
        answers[element.tag] = $("input[name=" + element.tag + "]:checked").val();
    });
    return answers;
}

function getScore() {
    var context = {
        answers: getAnswers()
    };

    var score = 0;

    // http://stackoverflow.com/a/25859853
    function evalInContext(js, context) {
        //# Return the results of the in-line anonymous function we .call with the passed context
        return function() { return eval(js); }.call(context);
    }

    $.each(elements, function(i, element) {
        evalInContext(element.score, context);
    });

    return Math.max(0, score);
}

function getErrors() {
    var context = {
        answers: getAnswers()
    };

    // http://stackoverflow.com/a/25859853
    function evalInContext(js, context) {
        //# Return the results of the in-line anonymous function we .call with the passed context
        return function() { return eval(js); }.call(context);
    }

    var errors = {};
    $.each(elements, function(i, element) {
        var ret = evalInContext(element.validate, context);

        if (ret && ret.highlight) {
            errors[element.tag] = ret.msg;
        }
    });

    return errors;
}

function doScore() {
    var score = getScore();
    $("#score").text(score);
    $("#formscore").val(score);
    return score;
}

function doValidate() {
    $icon = $("").addClass("glyphicon glyphicon-alert").html(" ");

    var errors = getErrors();
    var errorcnt = 0;

    $(".error", "#elements").data("current", false);

    $.each(elements, function(i, element) {
        var $panel = $("#" + element.tag, "#elements").parents(".panel");
        var $error = $(".error", $panel);

        if (element.tag in errors) {
            errorcnt++;

            $error.text(errors[element.tag]);
            $error.prepend($icon.clone());
            if ($error.is(":hidden"))
                $error.slideDown();

            $error.data("current", true);
        }
        else {
            if ($error.is(":visible") && !$error.data("current"))
                $error.slideUp();
        }
    });

    return errorcnt == 0;
}
<|endoftext|>


<commit_before>const AppDirectory = require('appdirectory');
const {EventEmitter} = require('events');
const FileManager = require('file-manager');

const HandlerManager = require('./components/classes/HandlerManager.js');
const SteamChatRoomClient = require('./components/chatroom.js');

const DefaultOptions = require('./resources/default_options.js');

class SteamUser extends EventEmitter {
	constructor(options) {
		super();

		this.steamID = null;

		this.chat = new SteamChatRoomClient(this);

		// Account info
		this.limitations = null;
		this.vac = null;
		this.wallet = null;
		this.emailInfo = null;
		this.licenses = null;
		this.gifts = null;

		// Friends and users info
		this.users = {};
		this.groups = {};
		this.chats = {};
		this.myFriends = {};
		this.myGroups = {};
		this.myFriendGroups = {};
		this.myNicknames = {};
		this.steamServers = {};
		this.contentServersReady = false;
		this.playingState = {blocked: false, appid: 0};
		this._playingBlocked = false;
		this._playingAppIds = [];

		this._gcTokens = []; // game connect tokens
		this._connectTime = 0;
		this._connectionCount = 0;
		this._connectTimeout = 1000;
		this._authSeqMe = 0;
		this._authSeqThem = 0;
		this._hSteamPipe = Math.floor(Math.random() * 1000000) + 1;
		this._contentServers = [];
		this._contentServersTimestamp = 0;
		this._contentServerTokens = {};
		this._lastNotificationCounts = {};
		this._sessionID = 0;
		this._jobs = {};
		this._richPresenceLocalization = {};

		// App and package cache
		this._changelistUpdateTimer = null;
		this.picsCache = {
			changenumber: 0,
			apps: {},
			packages: {}
		};

		this._sentry = null;

		this.options = options || {};

		for (let i in DefaultOptions) {
			if (!DefaultOptions.hasOwnProperty(i)) {
				continue;
			}

			if (typeof this.options[i] === 'undefined') {
				this.options[i] = DefaultOptions[i];
			}
		}

		this._checkOptionTypes();

		if (!this.options.dataDirectory && this.options.dataDirectory !== null) {
			if (process.env.OPENSHIFT_DATA_DIR) {
				this.options.dataDirectory = process.env.OPENSHIFT_DATA_DIR + '/node-steamuser';
			} else {
				this.options.dataDirectory = (new AppDirectory({
					appName: 'node-steamuser',
					appAuthor: 'doctormckay'
				})).userData();
			}
		}

		if (this.options.dataDirectory) {
			this.storage = new FileManager(this.options.dataDirectory);
		}

		if (this.options.webCompatibilityMode && this.options.protocol == SteamUser.EConnectionProtocol.TCP) {
			this._warn('webCompatibilityMode is enabled so connection protocol is being forced to WebSocket.');
		}
	}

	get packageName() {
		return require('./package.json').name;
	}

	get packageVersion() {
		return require('./package.json').version;
	}

	/**
	 * Set a configuration option.
	 * @param {string} option
	 * @param {*} value
	 */
	setOption(option, value) {
		this._setOption(option, value);
		this._checkOptionTypes();
	}

	/**
	 * Set one or more configuration options
	 * @param {object} options
	 */
	setOptions(options) {
		for (let i in options) {
			this._setOption(i, options[i]);
		}

		this._checkOptionTypes();
	}

	/**
	 * Actually commit an option change. This is a separate method since user-facing methods need to be able to call
	 * _checkOptionTypes() but we also want to be able to change options internally without calling it.
	 * @param {string} option
	 * @param {*} value
	 * @private
	 */
	_setOption(option, value) {
		this.options[option] = value;

		// Handle anything that needs to happen when particular options update
		switch (option) {
			case 'dataDirectory':
				if (!this.storage) {
					this.storage = new FileManager(value);
				} else {
					this.storage.directory = value;
				}

				break;

			case 'enablePicsCache':
				this._resetChangelistUpdateTimer();
				this._getLicenseInfo();
				break;

			case 'changelistUpdateInterval':
				this._resetChangelistUpdateTimer();
				break;

			case 'webCompatibilityMode':
			case 'protocol':
				if (
					(option == 'webCompatibilityMode' && value && this.options.protocol == SteamUser.EConnectionProtocol.TCP) ||
					(option == 'protocol' && value == SteamUser.EConnectionProtocol.TCP && this.options.webCompatibilityMode)
				) {
					this._warn('webCompatibilityMode is enabled so connection protocol is being forced to WebSocket');
				}
				break;
		}
	}

	/**
	 * Make sure that the types of all options are valid.
	 * @private
	 */
	_checkOptionTypes() {
		// We'll infer types from DefaultOptions, but stuff that's null (for example) needs to be defined explicitly
		let types = {
			httpProxy: 'string',
			localAddress: 'string',
			localPort: 'number',
			machineIdFormat: 'array'
		};

		for (let opt in DefaultOptions) {
			if (types[opt]) {
				// already specified
				continue;
			}

			types[opt] = typeof DefaultOptions[opt];
		}

		for (let opt in this.options) {
			if (!types[opt]) {
				// no type specified for this option, so bail
				continue;
			}

			let requiredType = types[opt];
			let providedType = typeof this.options[opt];
			if (providedType == 'object' && Array.isArray(this.options[opt])) {
				providedType = 'array';
			} else if (requiredType == 'number' && providedType == 'string' && !isNaN(this.options[opt])) {
				providedType = 'number';
				this.options[opt] = parseFloat(this.options[opt]);
			}

			if (this.options[opt] !== null && requiredType != providedType) {
				this._warn(`Incorrect type '${providedType}' provided for option ${opt}, '${requiredType}' expected. Resetting to default value ${DefaultOptions[opt]}`);
				this._setOption(opt, DefaultOptions[opt]);
			}
		}
	}

	/**
	 * Issue a warning
	 * @param msg
	 * @private
	 */
	_warn(msg) {
		process.emitWarning(msg, 'Warning', 'steam-user');
	}
}

// I don't think it's possible to do this via class syntax, so add these onto the prototype
SteamUser.prototype._handlers = {};
SteamUser.prototype._handlerManager = new HandlerManager();

// Export the SteamUser class before we require components that demand it
module.exports = SteamUser;

// Add enums
require('./resources/enums.js');

// Tack on our extra enums
SteamUser.CurrencyData = require('./resources/CurrencyData.js');
SteamUser.EClientUIMode = require('./resources/EClientUIMode.js');
SteamUser.EConnectionProtocol = require('./resources/EConnectionProtocol.js');
SteamUser.EMachineIDType = require('./resources/EMachineIDType.js');
SteamUser.EPurchaseResult = require('./resources/EPurchaseResult.js');
SteamUser.EPrivacyState = require('./resources/EPrivacyState.js');

// And finally, require all the components that add their own methods to the class' prototype
require('./components/connection.js');
require('./components/messages.js');
require('./components/filestorage.js');
require('./components/webapi.js');
require('./components/logon.js');
require('./components/sentry.js');
require('./components/web.js');
require('./components/notifications.js');
require('./components/apps.js');
require('./components/appauth.js');
require('./components/account.js');
require('./components/gameservers.js');
require('./components/utility.js');
require('./components/trading.js');
require('./components/friends.js');
require('./components/chat.js');
require('./components/twofactor.js');
require('./components/pubfiles.js');
require('./components/cdn.js');
require('./components/econ.js');
require('./components/store.js');
require('./components/gamecoordinator.js');

/**
 * Called when the request completes.
 * @callback SteamUser~genericEResultCallback
 * @param {Error|null} err - Error object on failure (with eresult property), null on success (represents EResult 1 - OK)
 */
<commit_msg>Make http:// protocol prefix optional in httpProxy<commit_after>const AppDirectory = require('appdirectory');
const {EventEmitter} = require('events');
const FileManager = require('file-manager');

const HandlerManager = require('./components/classes/HandlerManager.js');
const SteamChatRoomClient = require('./components/chatroom.js');

const DefaultOptions = require('./resources/default_options.js');

class SteamUser extends EventEmitter {
	constructor(options) {
		super();

		this.steamID = null;

		this.chat = new SteamChatRoomClient(this);

		// Account info
		this.limitations = null;
		this.vac = null;
		this.wallet = null;
		this.emailInfo = null;
		this.licenses = null;
		this.gifts = null;

		// Friends and users info
		this.users = {};
		this.groups = {};
		this.chats = {};
		this.myFriends = {};
		this.myGroups = {};
		this.myFriendGroups = {};
		this.myNicknames = {};
		this.steamServers = {};
		this.contentServersReady = false;
		this.playingState = {blocked: false, appid: 0};
		this._playingBlocked = false;
		this._playingAppIds = [];

		this._gcTokens = []; // game connect tokens
		this._connectTime = 0;
		this._connectionCount = 0;
		this._connectTimeout = 1000;
		this._authSeqMe = 0;
		this._authSeqThem = 0;
		this._hSteamPipe = Math.floor(Math.random() * 1000000) + 1;
		this._contentServers = [];
		this._contentServersTimestamp = 0;
		this._contentServerTokens = {};
		this._lastNotificationCounts = {};
		this._sessionID = 0;
		this._jobs = {};
		this._richPresenceLocalization = {};

		// App and package cache
		this._changelistUpdateTimer = null;
		this.picsCache = {
			changenumber: 0,
			apps: {},
			packages: {}
		};

		this._sentry = null;

		this.options = options || {};

		for (let i in DefaultOptions) {
			if (!DefaultOptions.hasOwnProperty(i)) {
				continue;
			}

			if (typeof this.options[i] === 'undefined') {
				this.options[i] = DefaultOptions[i];
			}
		}

		this._checkOptionTypes();

		if (!this.options.dataDirectory && this.options.dataDirectory !== null) {
			if (process.env.OPENSHIFT_DATA_DIR) {
				this.options.dataDirectory = process.env.OPENSHIFT_DATA_DIR + '/node-steamuser';
			} else {
				this.options.dataDirectory = (new AppDirectory({
					appName: 'node-steamuser',
					appAuthor: 'doctormckay'
				})).userData();
			}
		}

		if (this.options.dataDirectory) {
			this.storage = new FileManager(this.options.dataDirectory);
		}

		if (this.options.webCompatibilityMode && this.options.protocol == SteamUser.EConnectionProtocol.TCP) {
			this._warn('webCompatibilityMode is enabled so connection protocol is being forced to WebSocket.');
		}
	}

	get packageName() {
		return require('./package.json').name;
	}

	get packageVersion() {
		return require('./package.json').version;
	}

	/**
	 * Set a configuration option.
	 * @param {string} option
	 * @param {*} value
	 */
	setOption(option, value) {
		this._setOption(option, value);
		this._checkOptionTypes();
	}

	/**
	 * Set one or more configuration options
	 * @param {object} options
	 */
	setOptions(options) {
		for (let i in options) {
			this._setOption(i, options[i]);
		}

		this._checkOptionTypes();
	}

	/**
	 * Actually commit an option change. This is a separate method since user-facing methods need to be able to call
	 * _checkOptionTypes() but we also want to be able to change options internally without calling it.
	 * @param {string} option
	 * @param {*} value
	 * @private
	 */
	_setOption(option, value) {
		this.options[option] = value;

		// Handle anything that needs to happen when particular options update
		switch (option) {
			case 'dataDirectory':
				if (!this.storage) {
					this.storage = new FileManager(value);
				} else {
					this.storage.directory = value;
				}

				break;

			case 'enablePicsCache':
				this._resetChangelistUpdateTimer();
				this._getLicenseInfo();
				break;

			case 'changelistUpdateInterval':
				this._resetChangelistUpdateTimer();
				break;

			case 'webCompatibilityMode':
			case 'protocol':
				if (
					(option == 'webCompatibilityMode' && value && this.options.protocol == SteamUser.EConnectionProtocol.TCP) ||
					(option == 'protocol' && value == SteamUser.EConnectionProtocol.TCP && this.options.webCompatibilityMode)
				) {
					this._warn('webCompatibilityMode is enabled so connection protocol is being forced to WebSocket');
				}
				break;

			case 'httpProxy':
				if (typeof this.options.httpProxy == 'string' && !this.options.httpProxy.includes('://')) {
					this.options.httpProxy = 'http://' + this.options.httpProxy;
				}
				break;
		}
	}

	/**
	 * Make sure that the types of all options are valid.
	 * @private
	 */
	_checkOptionTypes() {
		// We'll infer types from DefaultOptions, but stuff that's null (for example) needs to be defined explicitly
		let types = {
			httpProxy: 'string',
			localAddress: 'string',
			localPort: 'number',
			machineIdFormat: 'array'
		};

		for (let opt in DefaultOptions) {
			if (types[opt]) {
				// already specified
				continue;
			}

			types[opt] = typeof DefaultOptions[opt];
		}

		for (let opt in this.options) {
			if (!types[opt]) {
				// no type specified for this option, so bail
				continue;
			}

			let requiredType = types[opt];
			let providedType = typeof this.options[opt];
			if (providedType == 'object' && Array.isArray(this.options[opt])) {
				providedType = 'array';
			} else if (requiredType == 'number' && providedType == 'string' && !isNaN(this.options[opt])) {
				providedType = 'number';
				this.options[opt] = parseFloat(this.options[opt]);
			}

			if (this.options[opt] !== null && requiredType != providedType) {
				this._warn(`Incorrect type '${providedType}' provided for option ${opt}, '${requiredType}' expected. Resetting to default value ${DefaultOptions[opt]}`);
				this._setOption(opt, DefaultOptions[opt]);
			}
		}
	}

	/**
	 * Issue a warning
	 * @param msg
	 * @private
	 */
	_warn(msg) {
		process.emitWarning(msg, 'Warning', 'steam-user');
	}
}

// I don't think it's possible to do this via class syntax, so add these onto the prototype
SteamUser.prototype._handlers = {};
SteamUser.prototype._handlerManager = new HandlerManager();

// Export the SteamUser class before we require components that demand it
module.exports = SteamUser;

// Add enums
require('./resources/enums.js');

// Tack on our extra enums
SteamUser.CurrencyData = require('./resources/CurrencyData.js');
SteamUser.EClientUIMode = require('./resources/EClientUIMode.js');
SteamUser.EConnectionProtocol = require('./resources/EConnectionProtocol.js');
SteamUser.EMachineIDType = require('./resources/EMachineIDType.js');
SteamUser.EPurchaseResult = require('./resources/EPurchaseResult.js');
SteamUser.EPrivacyState = require('./resources/EPrivacyState.js');

// And finally, require all the components that add their own methods to the class' prototype
require('./components/connection.js');
require('./components/messages.js');
require('./components/filestorage.js');
require('./components/webapi.js');
require('./components/logon.js');
require('./components/sentry.js');
require('./components/web.js');
require('./components/notifications.js');
require('./components/apps.js');
require('./components/appauth.js');
require('./components/account.js');
require('./components/gameservers.js');
require('./components/utility.js');
require('./components/trading.js');
require('./components/friends.js');
require('./components/chat.js');
require('./components/twofactor.js');
require('./components/pubfiles.js');
require('./components/cdn.js');
require('./components/econ.js');
require('./components/store.js');
require('./components/gamecoordinator.js');

/**
 * Called when the request completes.
 * @callback SteamUser~genericEResultCallback
 * @param {Error|null} err - Error object on failure (with eresult property), null on success (represents EResult 1 - OK)
 */
<|endoftext|>


<commit_before>// Models
exports.models = {
  Article: require('./src/models/Article.js'),
  Blacklist: require('./src/models/Blacklist.js'),
  FailRecord: require('./src/models/FailRecord.js'),
  Feed: require('./src/models/Feed.js'),
  Feedback: require('./src/models/Feedback.js'),
  FilteredFormat: require('./src/models/FilteredFormat.js'),
  KeyValue: require('./src/models/KeyValue.js'),
  Patron: require('./src/models/Patron.js'),
  Profile: require('./src/models/Profile.js'),
  Rating: require('./src/models/Rating.js'),
  Schedule: require('./src/models/Schedule.js'),
  ScheduleStats: require('./src/models/ScheduleStats.js'),
  Subscriber: require('./src/models/Subscriber.js'),
  Supporter: require('./src/models/Supporter.js')
}

// Structures
exports.Article = require('./src/structs/Article.js')
exports.Client = require('./src/structs/Client.js')
exports.ClientManager = require('./src/structs/ClientManager.js')
exports.FeedData = require('./src/structs/FeedData.js')

// Database Structures
exports.Blacklist = require('./src/structs/db/Blacklist.js')
exports.FailRecord = require('./src/structs/db/FailRecord.js')
exports.Feed = require('./src/structs/db/Feed.js')
exports.FilteredFormat = require('./src/structs/db/FilteredFormat.js')
exports.KeyValue = require('./src/structs/db/KeyValue.js')
exports.Patron = require('./src/structs/db/Patron.js')
exports.Profile = require('./src/structs/db/Profile.js')
exports.Schedule = require('./src/structs/db/Schedule.js')
exports.ScheduleStats = require('./src/structs/db/ScheduleStats.js')
exports.Subscriber = require('./src/structs/db/Subscriber.js')
exports.Supporter = require('./src/structs/db/Supporter.js')

// Utils
exports.FeedFetcher = require('./src/util/FeedFetcher.js')
exports.validateConfig = require('./src/util/config/schema').validate
exports.migrations = {
  v6: require('./scripts/pre_v6.js')
}

// Errors
exports.errors = {
  FeedParserError: require('./src/structs/errors/FeedParserError.js'),
  RequestError: require('./src/structs/errors/RequestError.js')
}
<commit_msg>Export GuildData<commit_after>// Models
exports.models = {
  Article: require('./src/models/Article.js'),
  Blacklist: require('./src/models/Blacklist.js'),
  FailRecord: require('./src/models/FailRecord.js'),
  Feed: require('./src/models/Feed.js'),
  Feedback: require('./src/models/Feedback.js'),
  FilteredFormat: require('./src/models/FilteredFormat.js'),
  KeyValue: require('./src/models/KeyValue.js'),
  Patron: require('./src/models/Patron.js'),
  Profile: require('./src/models/Profile.js'),
  Rating: require('./src/models/Rating.js'),
  Schedule: require('./src/models/Schedule.js'),
  ScheduleStats: require('./src/models/ScheduleStats.js'),
  Subscriber: require('./src/models/Subscriber.js'),
  Supporter: require('./src/models/Supporter.js')
}

// Structures
exports.Article = require('./src/structs/Article.js')
exports.Client = require('./src/structs/Client.js')
exports.ClientManager = require('./src/structs/ClientManager.js')
exports.FeedData = require('./src/structs/FeedData.js')
exports.GuildData = require('./src/structs/GuildData.js')

// Database Structures
exports.Blacklist = require('./src/structs/db/Blacklist.js')
exports.FailRecord = require('./src/structs/db/FailRecord.js')
exports.Feed = require('./src/structs/db/Feed.js')
exports.FilteredFormat = require('./src/structs/db/FilteredFormat.js')
exports.KeyValue = require('./src/structs/db/KeyValue.js')
exports.Patron = require('./src/structs/db/Patron.js')
exports.Profile = require('./src/structs/db/Profile.js')
exports.Schedule = require('./src/structs/db/Schedule.js')
exports.ScheduleStats = require('./src/structs/db/ScheduleStats.js')
exports.Subscriber = require('./src/structs/db/Subscriber.js')
exports.Supporter = require('./src/structs/db/Supporter.js')

// Utils
exports.FeedFetcher = require('./src/util/FeedFetcher.js')
exports.validateConfig = require('./src/util/config/schema').validate
exports.migrations = {
  v6: require('./scripts/pre_v6.js')
}

// Errors
exports.errors = {
  FeedParserError: require('./src/structs/errors/FeedParserError.js'),
  RequestError: require('./src/structs/errors/RequestError.js')
}
<|endoftext|>