<commit_before>// Part of <http://miracle.systems/p/h5.modbus> licensed under <MIT>

'use strict';

const EventEmitter = require('events').EventEmitter;
const Request = require('./Request');
const requests = require('./messages').requests;

/**
 * @private
 * @type {number}
 */
let TID = 0;

class Transaction extends EventEmitter
{
  /**
   * @param {TransactionOptions} options
   */
  constructor(options)
  {
    super();

    /**
     * @readonly
     * @type {string}
     */
    this.id = typeof options.id === 'string' ? options.id : `T~${++TID}`;

    /**
     * @readonly
     * @type {number}
     */
    this.unit = options.unit >= 0 ? options.unit : 1;

    /**
     * @readonly
     * @type {number}
     */
    this.maxRetries = options.maxRetries >= 0 ? options.maxRetries : 1;

    /**
     * @readonly
     * @type {number}
     */
    this.timeout = options.timeout > 0 ? options.timeout : 100;

    /**
     * @readonly
     * @type {number}
     */
    this.interval = options.interval >= 0 ? options.interval : -1;

    /**
     * @readonly
     * @type {Request}
     */
    this.request = typeof options.request.toBuffer === 'function'
      ? options.request
      : requests[options.request.functionCode].fromOptions(options.request);

    /**
     * @private
     * @type {?function(): void}
     */
    this.onDestroy = null;
  }

  destroy()
  {
    this.removeAllListeners();

    if (this.onDestroy)
    {
      this.onDestroy();
      this.onDestroy = null;
    }
  }

  /**
   * @returns {boolean}
   */
  isRepeatable()
  {
    return this.interval >= 0;
  }

  /**
   * @param {function(): void} onDestroy
   * @throws {Error} If this `Transaction` is already bound to another `Master`.
   */
  bind(onDestroy)
  {
    if (this.onDestroy)
    {
      throw new Error(`Transaction [${this.id}] is already bound to another Master.`);
    }

    this.onDestroy = onDestroy;
  }
}

module.exports = Transaction;

/**
 * @typedef {Object} TransactionOptions
 * @property {?string} [id]
 * @property {number} [unit=1]
 * @property {number} [maxRetries=1]
 * @property {number} [timeout=100]
 * @property {number} [interval=-1]
 * @property {(Request|{functionCode: FunctionCode})} [request]
 */
<commit_msg>Transaction: fixed an ESLint error.<commit_after>// Part of <http://miracle.systems/p/h5.modbus> licensed under <MIT>

'use strict';

const EventEmitter = require('events').EventEmitter;
const requests = require('./messages').requests;

/**
 * @private
 * @type {number}
 */
let TID = 0;

class Transaction extends EventEmitter
{
  /**
   * @param {TransactionOptions} options
   */
  constructor(options)
  {
    super();

    /**
     * @readonly
     * @type {string}
     */
    this.id = typeof options.id === 'string' ? options.id : `T~${++TID}`;

    /**
     * @readonly
     * @type {number}
     */
    this.unit = options.unit >= 0 ? options.unit : 1;

    /**
     * @readonly
     * @type {number}
     */
    this.maxRetries = options.maxRetries >= 0 ? options.maxRetries : 1;

    /**
     * @readonly
     * @type {number}
     */
    this.timeout = options.timeout > 0 ? options.timeout : 100;

    /**
     * @readonly
     * @type {number}
     */
    this.interval = options.interval >= 0 ? options.interval : -1;

    /**
     * @readonly
     * @type {Request}
     */
    this.request = typeof options.request.toBuffer === 'function'
      ? options.request
      : requests[options.request.functionCode].fromOptions(options.request);

    /**
     * @private
     * @type {?function(): void}
     */
    this.onDestroy = null;
  }

  destroy()
  {
    this.removeAllListeners();

    if (this.onDestroy)
    {
      this.onDestroy();
      this.onDestroy = null;
    }
  }

  /**
   * @returns {boolean}
   */
  isRepeatable()
  {
    return this.interval >= 0;
  }

  /**
   * @param {function(): void} onDestroy
   * @throws {Error} If this `Transaction` is already bound to another `Master`.
   */
  bind(onDestroy)
  {
    if (this.onDestroy)
    {
      throw new Error(`Transaction [${this.id}] is already bound to another Master.`);
    }

    this.onDestroy = onDestroy;
  }
}

module.exports = Transaction;

/**
 * @typedef {Object} TransactionOptions
 * @property {?string} [id]
 * @property {number} [unit=1]
 * @property {number} [maxRetries=1]
 * @property {number} [timeout=100]
 * @property {number} [interval=-1]
 * @property {(Request|{functionCode: FunctionCode})} [request]
 */
<|endoftext|>


<commit_before>/*
 * AMD Helper function module
 * Separated into its own file as this is the part needed for full AMD support in SFX builds
 *
 */
hookConstructor(function(constructor) {
  return function() {
    var loader = this;
    constructor.call(this);

    var commentRegEx = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg;
    var cjsRequirePre = "(?:^|[^$_a-zA-Z\\xA0-\\uFFFF.])";
    var cjsRequirePost = "\\s*\\(\\s*(\"([^\"]+)\"|'([^']+)')\\s*\\)";
    var fnBracketRegEx = /\(([^\)]*)\)/;
    var wsRegEx = /^\s+|\s+$/g;

    var requireRegExs = {};

    function getCJSDeps(source, requireIndex) {

      // remove comments
      source = source.replace(commentRegEx, '');

      // determine the require alias
      var params = source.match(fnBracketRegEx);
      var requireAlias = (params[1].split(',')[requireIndex] || 'require').replace(wsRegEx, '');

      // find or generate the regex for this requireAlias
      var requireRegEx = requireRegExs[requireAlias] || (requireRegExs[requireAlias] = new RegExp(cjsRequirePre + requireAlias + cjsRequirePost, 'g'));

      requireRegEx.lastIndex = 0;

      var deps = [];

      var match;
      while (match = requireRegEx.exec(source))
        deps.push(match[2] || match[3]);

      return deps;
    }

    /*
      AMD-compatible require
      To copy RequireJS, set window.require = window.requirejs = loader.amdRequire
    */
    function require(names, callback, errback, referer) {
      // in amd, first arg can be a config object... we just ignore
      if (typeof names == 'object' && !(names instanceof Array))
        return require.apply(null, Array.prototype.splice.call(arguments, 1, arguments.length - 1));

      // amd require
      if (typeof names == 'string' && typeof callback == 'function')
        names = [names];
      if (names instanceof Array) {
        var dynamicRequires = [];
        for (var i = 0; i < names.length; i++)
          dynamicRequires.push(loader['import'](names[i], referer));
        Promise.all(dynamicRequires).then(function(modules) {
          if (callback)
            callback.apply(null, modules);
        }, errback);
      }

      // commonjs require
      else if (typeof names == 'string') {
        var module = loader.get(names);
        return module.__useDefault ? module['default'] : module;
      }

      else
        throw new TypeError('Invalid require');
    };

    function define(name, deps, factory) {
      if (typeof name != 'string') {
        factory = deps;
        deps = name;
        name = null;
      }
      if (!(deps instanceof Array)) {
        factory = deps;
        deps = ['require', 'exports', 'module'].splice(0, factory.length);
      }

      if (typeof factory != 'function')
        factory = (function(factory) {
          return function() { return factory; }
        })(factory);

      // in IE8, a trailing comma becomes a trailing undefined entry
      if (deps[deps.length - 1] === undefined)
        deps.pop();

      // remove system dependencies
      var requireIndex, exportsIndex, moduleIndex;

      if ((requireIndex = indexOf.call(deps, 'require')) != -1) {

        deps.splice(requireIndex, 1);

        // only trace cjs requires for non-named
        // named defines assume the trace has already been done
        if (!name)
          deps = deps.concat(getCJSDeps(factory.toString(), requireIndex));
      }

      if ((exportsIndex = indexOf.call(deps, 'exports')) != -1)
        deps.splice(exportsIndex, 1);

      if ((moduleIndex = indexOf.call(deps, 'module')) != -1)
        deps.splice(moduleIndex, 1);

      var define = {
        name: name,
        deps: deps,
        execute: function(req, exports, module) {

          var depValues = [];
          for (var i = 0; i < deps.length; i++)
            depValues.push(req(deps[i]));

          module.uri = module.id;

          module.config = function() {};

          // add back in system dependencies
          if (moduleIndex != -1)
            depValues.splice(moduleIndex, 0, module);

          if (exportsIndex != -1)
            depValues.splice(exportsIndex, 0, exports);

          if (requireIndex != -1) {
            function contextualRequire(names, callback, errback) {
              if (typeof names == 'string' && typeof callback != 'function')
                return req(names);
              return require.call(loader, names, callback, errback, module.id);
            }
            contextualRequire.toUrl = function(name) {
              return loader.normalizeSync(name, module.id);
            };
            depValues.splice(requireIndex, 0, contextualRequire);
          }

          // set global require to AMD require
          var curRequire = __global.require;
          __global.require = require;

          var output = factory.apply(exportsIndex == -1 ? __global : exports, depValues);

          __global.require = curRequire;

          if (typeof output == 'undefined' && module)
            output = module.exports;

          if (typeof output != 'undefined')
            return output;
        }
      };

      // anonymous define
      if (!name) {
        // already defined anonymously -> throw
        if (lastModule.anonDefine)
          throw new TypeError('Multiple defines for anonymous module');
        lastModule.anonDefine = define;
      }
      // named define
      else {
        // if it has no dependencies and we don't have any other
        // defines, then let this be an anonymous define
        // this is just to support single modules of the form:
        // define('jquery')
        // still loading anonymously
        // because it is done widely enough to be useful
        if (deps.length == 0 && !lastModule.anonDefine && !lastModule.isBundle) {
          lastModule.anonDefine = define;
        }
        // otherwise its a bundle only
        else {
          // if there is an anonDefine already (we thought it could have had a single named define)
          // then we define it now
          // this is to avoid defining named defines when they are actually anonymous
          if (lastModule.anonDefine && lastModule.anonDefine.name)
            loader.registerDynamic(lastModule.anonDefine.name, lastModule.anonDefine.deps, false, lastModule.anonDefine.execute);

          lastModule.anonDefine = null;
        }

        // note this is now a bundle
        lastModule.isBundle = true;

        // define the module through the register registry
        loader.registerDynamic(name, define.deps, false, define.execute);
      }
    }
    define.amd = {};

    // adds define as a global (potentially just temporarily)
    function createDefine(loader) {
      lastModule.anonDefine = null;
      lastModule.isBundle = false;

      // ensure no NodeJS environment detection
      var oldModule = __global.module;
      var oldExports = __global.exports;
      var oldDefine = __global.define;

      __global.module = undefined;
      __global.exports = undefined;
      __global.define = define;

      return function() {
        __global.define = oldDefine;
        __global.module = oldModule;
        __global.exports = oldExports;
      };
    }

    var lastModule = {
      isBundle: false,
      anonDefine: null
    };

    loader.set('@@amd-helpers', loader.newModule({
      createDefine: createDefine,
      require: require,
      define: define,
      lastModule: lastModule
    }));
    loader.amdDefine = define;
    loader.amdRequire = require;
  };
});<commit_msg>toUrl to skip defaultJSExtensions<commit_after>/*
 * AMD Helper function module
 * Separated into its own file as this is the part needed for full AMD support in SFX builds
 *
 */
hookConstructor(function(constructor) {
  return function() {
    var loader = this;
    constructor.call(this);

    var commentRegEx = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg;
    var cjsRequirePre = "(?:^|[^$_a-zA-Z\\xA0-\\uFFFF.])";
    var cjsRequirePost = "\\s*\\(\\s*(\"([^\"]+)\"|'([^']+)')\\s*\\)";
    var fnBracketRegEx = /\(([^\)]*)\)/;
    var wsRegEx = /^\s+|\s+$/g;

    var requireRegExs = {};

    function getCJSDeps(source, requireIndex) {

      // remove comments
      source = source.replace(commentRegEx, '');

      // determine the require alias
      var params = source.match(fnBracketRegEx);
      var requireAlias = (params[1].split(',')[requireIndex] || 'require').replace(wsRegEx, '');

      // find or generate the regex for this requireAlias
      var requireRegEx = requireRegExs[requireAlias] || (requireRegExs[requireAlias] = new RegExp(cjsRequirePre + requireAlias + cjsRequirePost, 'g'));

      requireRegEx.lastIndex = 0;

      var deps = [];

      var match;
      while (match = requireRegEx.exec(source))
        deps.push(match[2] || match[3]);

      return deps;
    }

    /*
      AMD-compatible require
      To copy RequireJS, set window.require = window.requirejs = loader.amdRequire
    */
    function require(names, callback, errback, referer) {
      // in amd, first arg can be a config object... we just ignore
      if (typeof names == 'object' && !(names instanceof Array))
        return require.apply(null, Array.prototype.splice.call(arguments, 1, arguments.length - 1));

      // amd require
      if (typeof names == 'string' && typeof callback == 'function')
        names = [names];
      if (names instanceof Array) {
        var dynamicRequires = [];
        for (var i = 0; i < names.length; i++)
          dynamicRequires.push(loader['import'](names[i], referer));
        Promise.all(dynamicRequires).then(function(modules) {
          if (callback)
            callback.apply(null, modules);
        }, errback);
      }

      // commonjs require
      else if (typeof names == 'string') {
        var module = loader.get(names);
        return module.__useDefault ? module['default'] : module;
      }

      else
        throw new TypeError('Invalid require');
    };

    function define(name, deps, factory) {
      if (typeof name != 'string') {
        factory = deps;
        deps = name;
        name = null;
      }
      if (!(deps instanceof Array)) {
        factory = deps;
        deps = ['require', 'exports', 'module'].splice(0, factory.length);
      }

      if (typeof factory != 'function')
        factory = (function(factory) {
          return function() { return factory; }
        })(factory);

      // in IE8, a trailing comma becomes a trailing undefined entry
      if (deps[deps.length - 1] === undefined)
        deps.pop();

      // remove system dependencies
      var requireIndex, exportsIndex, moduleIndex;

      if ((requireIndex = indexOf.call(deps, 'require')) != -1) {

        deps.splice(requireIndex, 1);

        // only trace cjs requires for non-named
        // named defines assume the trace has already been done
        if (!name)
          deps = deps.concat(getCJSDeps(factory.toString(), requireIndex));
      }

      if ((exportsIndex = indexOf.call(deps, 'exports')) != -1)
        deps.splice(exportsIndex, 1);

      if ((moduleIndex = indexOf.call(deps, 'module')) != -1)
        deps.splice(moduleIndex, 1);

      var define = {
        name: name,
        deps: deps,
        execute: function(req, exports, module) {

          var depValues = [];
          for (var i = 0; i < deps.length; i++)
            depValues.push(req(deps[i]));

          module.uri = module.id;

          module.config = function() {};

          // add back in system dependencies
          if (moduleIndex != -1)
            depValues.splice(moduleIndex, 0, module);

          if (exportsIndex != -1)
            depValues.splice(exportsIndex, 0, exports);

          if (requireIndex != -1) {
            function contextualRequire(names, callback, errback) {
              if (typeof names == 'string' && typeof callback != 'function')
                return req(names);
              return require.call(loader, names, callback, errback, module.id);
            }
            contextualRequire.toUrl = function(name) {
              // normalize without defaultJSExtensions
              var defaultJSExtension = loader.defaultJSEXtensions && name.substr(name.length - 3, 3) != '.js';
              var url = loader.normalizeSync(name, module.id);
              if (defaultJSExtension && url.substr(url.length - 3, 3) == '.js')
                url = url.substr(0, url.length - 3);
              return url;
            };
            depValues.splice(requireIndex, 0, contextualRequire);
          }

          // set global require to AMD require
          var curRequire = __global.require;
          __global.require = require;

          var output = factory.apply(exportsIndex == -1 ? __global : exports, depValues);

          __global.require = curRequire;

          if (typeof output == 'undefined' && module)
            output = module.exports;

          if (typeof output != 'undefined')
            return output;
        }
      };

      // anonymous define
      if (!name) {
        // already defined anonymously -> throw
        if (lastModule.anonDefine)
          throw new TypeError('Multiple defines for anonymous module');
        lastModule.anonDefine = define;
      }
      // named define
      else {
        // if it has no dependencies and we don't have any other
        // defines, then let this be an anonymous define
        // this is just to support single modules of the form:
        // define('jquery')
        // still loading anonymously
        // because it is done widely enough to be useful
        if (deps.length == 0 && !lastModule.anonDefine && !lastModule.isBundle) {
          lastModule.anonDefine = define;
        }
        // otherwise its a bundle only
        else {
          // if there is an anonDefine already (we thought it could have had a single named define)
          // then we define it now
          // this is to avoid defining named defines when they are actually anonymous
          if (lastModule.anonDefine && lastModule.anonDefine.name)
            loader.registerDynamic(lastModule.anonDefine.name, lastModule.anonDefine.deps, false, lastModule.anonDefine.execute);

          lastModule.anonDefine = null;
        }

        // note this is now a bundle
        lastModule.isBundle = true;

        // define the module through the register registry
        loader.registerDynamic(name, define.deps, false, define.execute);
      }
    }
    define.amd = {};

    // adds define as a global (potentially just temporarily)
    function createDefine(loader) {
      lastModule.anonDefine = null;
      lastModule.isBundle = false;

      // ensure no NodeJS environment detection
      var oldModule = __global.module;
      var oldExports = __global.exports;
      var oldDefine = __global.define;

      __global.module = undefined;
      __global.exports = undefined;
      __global.define = define;

      return function() {
        __global.define = oldDefine;
        __global.module = oldModule;
        __global.exports = oldExports;
      };
    }

    var lastModule = {
      isBundle: false,
      anonDefine: null
    };

    loader.set('@@amd-helpers', loader.newModule({
      createDefine: createDefine,
      require: require,
      define: define,
      lastModule: lastModule
    }));
    loader.amdDefine = define;
    loader.amdRequire = require;
  };
});<|endoftext|>


<commit_before>angular.module('Leaf',['ui.router','ngSanitize','oc.lazyLoad','ui.sortable'])

.config(['$urlMatcherFactoryProvider','$stateProvider','$urlRouterProvider','$locationProvider','$ocLazyLoadProvider',function($urlMatcherFactoryProvider,$stateProvider,$urlRouterProvider,$locationProvider,$ocLazyLoadProvider) {

  $urlMatcherFactoryProvider.strictMode(false);

  var modulesUrl = 'app/components/';

  $stateProvider

  // Setup.
  .state('setup',{
    url : '/setup',
    templateUrl : modulesUrl + 'setup/setup.html',
    title : 'Setup',
    controller : 'setupController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'setup/setup-service.js',
          modulesUrl + 'setup/setup.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Login.
  .state('login',{
    url : '/login',
    templateUrl : modulesUrl + 'auth/login.html',
    title : 'Login',
    controller : 'loginController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'auth/login.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Sign up.
  .state('signup',{
    url : '/signup/:token',
    templateUrl : modulesUrl + 'auth/signup.html',
    title : 'Sign up',
    controller : 'signupController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'users/invites-service.js',
          modulesUrl + 'auth/signup.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Lost password.
  .state('lostpassword',{
    url : '/lost-password',
    templateUrl : modulesUrl + 'auth/lost-password.html',
    title : 'Lost password',
    controller : 'lostpasswordController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'auth/lost-password.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Dashboard.
  .state('dashboard',{
    url : '/dashboard',
    templateUrl : modulesUrl + 'dashboard/dashboard.html',
    title : 'Dashboard',
    data : {active : 'dashboard'},
    controller : 'dashboardController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'dashboard/dashboard.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Editor (new post/page).
  .state('new-post',{
    url : '/editor',
    templateUrl : modulesUrl + 'posts/editor.html',
    title : 'Editor',
    data : {active : 'editor',nosearch : true},
    controller : 'editorController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          'assets/libs/jquery/syncscroll.js',
          modulesUrl + 'posts/editor.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Editor (edit post/page).
  .state('edit-post',{
    url : '/editor/:id',
    templateUrl : modulesUrl + 'posts/editor.html',
    title : 'Editor',
    data : {active : 'editor',nosearch : true},
    controller : 'editorController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          'assets/libs/jquery/syncscroll.js',
          modulesUrl + 'posts/editor.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Team.
  .state('users',{
    url : '/users',
    templateUrl : modulesUrl + 'users/users.html',
    title : 'Team',
    data : {active : 'users'},
    controller : 'usersController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'users/roles-service.js',
          modulesUrl + 'users/invites-service.js',
          modulesUrl + 'users/users-service.js',
          modulesUrl + 'users/users.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // User profile.
  .state('user',{
    url : '/users/:id',
    templateUrl : modulesUrl + 'users/user.html',
    title : 'Profile',
    data : {active : 'users',nosearch : true},
    controller : 'userController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'users/roles-service.js',
          modulesUrl + 'users/users-service.js',
          modulesUrl + 'users/user.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Posts and pages.
  .state('posts',{
    url : '/posts',
    templateUrl : modulesUrl + 'posts/posts.html',
    title : 'Posts',
    data : {active : 'posts'},
    controller : 'postsController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'posts/posts.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Comments.
  .state('comments',{
    url : '/comments',
    templateUrl : modulesUrl + 'comments/comments.html',
    title : 'Comments',
    data : {active : 'comments'},
    controller : 'commentsController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'comments/comments.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Media.
  .state('media',{
    url : '/media',
    templateUrl : modulesUrl + 'media/media.html',
    title : 'Media',
    data : {active : 'media'},
    controller : 'mediaController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'media/media.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Tags.
  .state('tags',{
    url : '/tags',
    templateUrl : modulesUrl + 'tags/tags.html',
    title : 'Tags',
    data : {active : 'tags'},
    controller : 'tagsController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'tags/tags-service.js',
          modulesUrl + 'tags/tags.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Navigation.
  .state('navigation',{
    url : '/navigation',
    templateUrl : modulesUrl + 'navigation/navigation.html',
    title : 'Navigation',
    data : {active : 'navigation',nosearch : true},
    controller : 'navigationController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'navigation/navigation-service.js',
          modulesUrl + 'navigation/navigation.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Sharing.
  .state('shares',{
    url : '/shares',
    templateUrl : modulesUrl + 'shares/shares.html',
    title : 'Sharing',
    data : {active : 'shares',nosearch : true},
    controller : 'sharesController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'shares/shares-service.js',
          modulesUrl + 'shares/shares.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Themes.
  .state('themes',{
    url : '/themes',
    templateUrl : modulesUrl + 'themes/themes.html',
    title : 'Themes',
    data : {active : 'themes'},
    controller : 'themesController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'themes/themes.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // General settings.
  .state('settings-general',{
    url : '/settings/general',
    templateUrl : modulesUrl + 'settings/general.html',
    title : 'General settings',
    data : {active : 'settings-general',nosearch : true},
    controller : 'settingsController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'users/roles-service.js',
          modulesUrl + 'themes/themes-service.js',
          modulesUrl + 'settings/settings-service.js',
          modulesUrl + 'settings/settings.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Contents settings.
  .state('settings-contents',{
    url : '/settings/contents',
    templateUrl : modulesUrl + 'settings/contents.html',
    title : 'Contents settings',
    data : {active : 'settings-contents',nosearch : true},
    controller : 'settingsController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'users/roles-service.js',
          modulesUrl + 'themes/themes-service.js',
          modulesUrl + 'settings/settings-service.js',
          modulesUrl + 'settings/settings.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Users settings.
  .state('settings-users',{
    url : '/settings/users',
    templateUrl : modulesUrl + 'settings/users.html',
    title : 'Users settings',
    data : {active : 'settings-users',nosearch : true},
    controller : 'settingsController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'users/roles-service.js',
          modulesUrl + 'themes/themes-service.js',
          modulesUrl + 'settings/settings-service.js',
          modulesUrl + 'settings/settings.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  })

  // Advanced settings.
  .state('settings-advanced',{
    url : '/settings/advanced',
    templateUrl : modulesUrl + 'settings/advanced.html',
    title : 'Advanced settings',
    data : {active : 'settings-advanced',nosearch : true},
    controller : 'settingsController',
    resolve : {
      deps : ['$ocLazyLoad',function($ocLazyLoad) {
        var deps = [
          modulesUrl + 'users/roles-service.js',
          modulesUrl + 'themes/themes-service.js',
          modulesUrl + 'settings/settings-service.js',
          modulesUrl + 'settings/settings.js'
        ];
        return $ocLazyLoad.load(deps);
      }]
    },
    cache : false
  });

  $urlRouterProvider.otherwise('/dashboard');

  $locationProvider.hashPrefix('').html5Mode(true);

}])

.run(['$rootScope','$location','$state','$http','$ocLazyLoad',function($rootScope,$location,$state,$http,$ocLazyLoad) {

  var deps = [
    'app/shared/filters.js',
    'app/shared/directives.js'
  ];

  $ocLazyLoad.load(deps);

  // Admin menu.
  $rootScope.adminMenu = [
    {
      id : 'general',
      title : '',
      items : [
        {id : 'dashboard',title : 'Dashboard',url : 'dashboard',icon : 'pulse',roles : []},
        {id : 'editor',title : 'Editor',url : 'editor',icon : 'pen-b',roles : []},
        {id : 'users',title : 'Team',url : 'users',icon : 'users',roles : []}
      ]
    },
    {
      id : 'contents',
      title : 'Contents',
      items : [
        {id : 'posts',title : 'Posts',url : 'posts',icon : 'copy',roles : []},
        {id : 'comments',title : 'Comments',url : 'comments',icon : 'bubble-a',roles : []},
        {id : 'media',title : 'Media',url : 'media',icon : 'image',roles : []}
      ]
    },
    {
      id : 'personalize',
      title : 'Personalize',
      items : [
        {id : 'tags',title : 'Tags',url : 'tags',icon : 'tags-a',roles : []},
        {id : 'navigation',title : 'Navigation',url : 'navigation',icon : 'compass',roles : []},
        {id : 'shares',title : 'Sharing',url : 'shares',icon : 'share-b',roles : []},
        {id : 'themes',title : 'Themes',url : 'themes',icon : 'brush',roles : []}
      ]
    },
    {
      id : 'settings',
      title : 'Settings',
      items : [
        {id : 'settings-general',title : 'General',url : 'settings/general',icon : 'gear',roles : []},
        {id : 'settings-contents',title : 'Contents',url : 'settings/contents',icon : 'folder-open-a',roles : []},
        {id : 'settings-users',title : 'Users',url : 'settings/users',icon : 'user',roles : []},
        {id : 'settings-advanced',title : 'Advanced',url : 'settings/advanced',icon : 'wrench-c',roles : []}
      ]
    }
  ];

  // Absolute URL for the domain (protocol + host + port).
  $rootScope.siteUrl = $location.protocol() + '://' + $location.host() + ':' + $location.port();

  // Map $state in the $rootScope.
  $rootScope.$state = $state;

  // Initialize loading modal.
  $rootScope.initLoading = function() {
    $rootScope.loading = 'Loading...';
    $('#loading-modal').modal({show : false,backdrop : 'static'});
  };

  // Show loading modal.
  $rootScope.showLoading = function(message) {
    if (message) $rootScope.loading = message;
    $('#loading-modal').modal('show');
  };

  // Hide loading modal.
  $rootScope.hideLoading = function() {
    $('#loading-modal').modal('hide');
  };

  // Initialize message modal.
  $rootScope.initMessage = function() {
    $rootScope.message = {
      text : '',
      severity : 'danger'
    };
    $('#message-modal').modal({show : false});
  };

  // Set message.
  $rootScope.setMessage = function(message,severity) {
    $rootScope.hideLoading();
    severity = severity || '';
    severity = severity.toLowerCase();

    var icons = {
      info : 'info-a',
      success : 'check',
      warning : 'alert-circle',
      danger : 'alert-triangle'
    };

    if (!icons.hasOwnProperty(severity)) severity = 'danger';

    $rootScope.message = {
      text : message,
      icon : icons[severity],
      severity : severity
    };
  };

  // Show message modal.
  $rootScope.showMessage = function(message,severity) {
    $rootScope.hideLoading();
    severity = severity || '';
    severity = severity.toLowerCase();

    var icons = {
      info : 'info-a',
      success : 'check',
      warning : 'alert-circle',
      danger : 'alert-triangle'
    };

    if (!icons.hasOwnProperty(severity)) severity = 'danger';

    $rootScope.message = {
      text : message,
      icon : icons[severity],
      severity : severity
    };

    $('#message-modal').modal('show');
  };

  // Initialize search.
  $rootScope.initSearch = function(event) {
    if (event) event.preventDefault();
    $rootScope.search = '';
  };

  // When a route changes, initialize search string.
  $rootScope.$on('$stateChangeStart',function(event) {
    $rootScope.initSearch();
  });

  // Load all settings.
  $rootScope.loadSettings = function() {
    $rootScope.settings = {};
    $http.get($rootScope.siteUrl + '/api/settings').then(function(res) {
      if (res.status===200) for (var i=0; i<res.data.length; i++) $rootScope.settings[res.data[i].name] = res.data[i];
    });
  };

  $rootScope.loadSettings();

  // Initialize system info.
  $rootScope.loadSystemInfo = function() {
    $rootScope.systemInfo = {
      env : {},
      platform : {},
      server : {},
      client : {
        useragent : navigator.userAgent || 'Unknown',
        engine : navigator.product || 'Unknown',
        online : navigator.onLine || false,
        geolocation : navigator.geolocation || false,
        cookies : navigator.cookieEnabled || false
      }
    };
    $http.get($rootScope.siteUrl + '/api/misc/system').then(function(res) {
      if (res.status===200) {
        $rootScope.systemInfo.env = res.data.env;
        $rootScope.systemInfo.platform = res.data.platform;
        $rootScope.systemInfo.server = res.data.server;
      }
    },
    function(err) {
      console.error(err);
    });
  };

  $rootScope.loadSystemInfo();

  // Check if an item in the admin menu is active.
  $rootScope.isActivePage = function(id) {
    return $state.current.data.active===id;
  };

  // Check if the search input is disabled.
  $rootScope.isSearchDisabled = function() {
    return $state.current.data.nosearch || false;
  };

  // Initialize header.
  $rootScope.initHeader = function() {

    $(window).on('resize',function() {
      $('#header').eq(0).css('left',($(window).width()>990)? '0' : '-304px');
    });

    $('#header nav').css('overflow','hidden');

    $('#header nav').on('mouseover',function() {
        $(this).css('overflow','auto');
    }).on('mouseout',function() {
        $(this).css('overflow','hidden');
    });

  };

  // Show header.
  $rootScope.showHeader = function() {
    $rootScope.hideSidebar();
    $('#header nav').scrollTop(0);
    $('#header').eq(0).animate({left : '0'},300);
  };

  // Hide header.
  $rootScope.hideHeader = function() {
    $('#header').eq(0).animate({left : '-304px'},300);
  };

  // Show sidebar.
  $rootScope.showSidebar = function(event) {
    if (event) event.preventDefault();
    $('#sidebar .content').scrollTop(0);
    $('#sidebar').eq(0).animate({right : '0'},300);
  };

  // Hide sidebar.
  $rootScope.hideSidebar = function(event) {
    if (event) event.preventDefault();
    $('#sidebar').eq(0).animate({right : '-309px'},300);
  };

  // Initialize help modal.
  $rootScope.initHelp = function(html) {
    $rootScope.help = html || '
No help is available for this page.
';
  };

  $rootScope.initHelp();

}]);<commit_msg>Delete app.js<commit_after><|endoftext|>


<commit_before>var config = require(__dirname+'/../../config/config.js');

/**
 * @requires config
 * @function getKey
 *
 * @description Gets admin password.
 * @param {getKeyCallback} fn - Callback that handles response upon getting key.
 */
function getKey(fn){
  key = config.get('KEY');
  if (key) {
    fn(null, key);
  } else {
    setKey(fn);
  }
};

module.exports = getKey;

<commit_msg>[BUG] Require setKey in getKey api call.<commit_after>var config = require(__dirname+'/../../config/config.js');
var setKey = require(__dirname+'/set_key.js');

/**
 * @requires config
 * @function getKey
 *
 * @description Gets admin password.
 * @param {getKeyCallback} fn - Callback that handles response upon getting key.
 */
function getKey(fn){
  key = config.get('KEY');
  if (key) {
    fn(null, key);
  } else {
    setKey(fn);
  }
};

module.exports = getKey;

<|endoftext|>


<commit_before>// Hack to always define a console
if (!window["console"]) {
    window.console = { log: function () { } };
}

function glinamespace(name) {
    var parts = name.split(".");
    var current = window;
    for (var n = 0; n < parts.length; n++) {
        var part = parts[n];
        current[part] = current[part] || {};
        current = current[part];
    }
    return current;
}

function glisubclass(parent, child, args) {
    parent.apply(child, args);

    // TODO: this sucks - do it right

    for (var propertyName in parent.prototype) {
        if (propertyName == "constructor") {
            continue;
        }
        if (!child.__proto__[propertyName]) {
            child.__proto__[propertyName] = parent.prototype[propertyName];
        }
    }

    for (var propertyName in parent) {
        child[propertyName] = parent[propertyName];
    }
};

function glitypename(value) {
    if (value) {
        var mangled = value.constructor.toString();
        if (mangled) {
            var matches = mangled.match(/function (.+)\(/);
            if (matches) {
                // ...function Foo()...
                if (matches[1] == "Object") {
                    // Hrm that's likely not right...
                    // constructor may be fubar
                    mangled = value.toString();
                } else {
                    return matches[1];
                }
            }

            // [object Foo]
            matches = mangled.match(/\[object (.+)\]/);
            if (matches) {
                return matches[1];
            }
        }
    }
    return null;
};

function scrollIntoViewIfNeeded(el) {
    if (el.scrollIntoViewIfNeeded) {
        el.scrollIntoViewIfNeeded();
    } else {
        // TODO: determine if el is in the current view of the parent
        var scrollTop = el.offsetParent.scrollTop;
        var scrollBottom = el.offsetParent.scrollTop + el.offsetParent.clientHeight;
        var elTop = el.offsetTop;
        var elBottom = el.offsetTop + el.offsetHeight;
        if ((elTop < scrollTop) || (elTop > scrollBottom)) {
            el.scrollIntoView();
        }
    }
};

(function () {
    var util = glinamespace("gli.util");

    // Adjust TypedArray types to have consistent toString methods
    var typedArrayToString = function () {
        var s = "";
        var maxIndex = Math.min(64, this.length);
        for (var n = 0; n < maxIndex; n++) {
            s += this[n];
            if (n < this.length - 1) {
                s += ",";
            }
        }
        if (maxIndex < this.length) {
            s += ",... (" + (this.length) + " total)";
        }
        return s;
    };
    Int8Array.prototype.toString = typedArrayToString;
    Uint8Array.prototype.toString = typedArrayToString;
    Int16Array.prototype.toString = typedArrayToString;
    Uint16Array.prototype.toString = typedArrayToString;
    Int32Array.prototype.toString = typedArrayToString;
    Uint32Array.prototype.toString = typedArrayToString;
    Float32Array.prototype.toString = typedArrayToString;

    util.isTypedArray = function (value) {
        if (value) {
            var typename = glitypename(value);
            switch (typename) {
                case "Int8Array":
                case "Uint8Array":
                case "Int16Array":
                case "Uint16Array":
                case "Int32Array":
                case "Uint32Array":
                case "Float32Array":
                    return true;
            }
            return false;
        } else {
            return false;
        }
    };

    util.isWebGLResource = function (value) {
        if (value) {
            var typename = glitypename(value);
            switch (typename) {
                case "WebGLBuffer":
                case "WebGLFramebuffer":
                case "WebGLProgram":
                case "WebGLRenderbuffer":
                case "WebGLShader":
                case "WebGLTexture":
                    return true;
            }
            return false;
        } else {
            return false;
        }
    }

    function prepareDocumentElement(el) {
        // FF requires all content be in a document before it'll accept it for playback
        if (window.navigator.product == "Gecko") {
            var frag = document.createDocumentFragment();
            frag.appendChild(el);
        }
    };

    util.clone = function (arg) {
        if (arg) {
            if ((arg.constructor == Number) || (arg.constructor == String)) {
                // Fast path for immutables
                return arg;
            } else if (arg.constructor == Array) {
                return arg.slice(); // ghetto clone
            } else if (arg instanceof ArrayBuffer) {
                // There may be a better way to do this, but I don't know it
                var target = new ArrayBuffer(arg.byteLength);
                var sourceView = new DataView(arg, 0, source.byteLength);
                var targetView = new DataView(target, 0, target.byteLength);
                for (var n = 0; n < source.byteLength; n++) {
                    targetView.setUInt8(n, sourceView.getUInt8(n));
                }
                return target;
            } else if (arg.__proto__.__proto__.constructor.toString().indexOf("ArrayBufferView") > 0) {
                //} else if (arg instanceof ArrayBufferView) {
                // HACK: at least Chromium doesn't have ArrayBufferView as a known type (for some reason)
                var target = null;
                if (arg instanceof Int8Array) {
                    target = new Int8Array(arg);
                } else if (arg instanceof Uint8Array) {
                    target = new Uint8Array(arg);
                } else if (arg instanceof Int16Array) {
                    target = new Int16Array(arg);
                } else if (arg instanceof Uint16Array) {
                    target = new Uint16Array(arg);
                } else if (arg instanceof Int32Array) {
                    target = new Int32Array(arg);
                } else if (arg instanceof Uint32Array) {
                    target = new Uint32Array(arg);
                } else if (arg instanceof Float32Array) {
                    target = new Float32Array(arg);
                } else if (arg instanceof Float64Array) {
                    target = new Float64Array(arg);
                } else {
                    target = arg;
                }
                return target;
            } else if (arg.__proto__.constructor.toString().indexOf("ImageData") > 0) {
                var dummyCanvas = document.createElement("canvas");
                var dummyContext = dummyCanvas.getContext("2d");
                var target = dummyContext.createImageData(arg);
                for (var n = 0; n < arg.data.length; n++) {
                    target.data[n] = arg.data[n];
                }
                return target;
            } else if (arg instanceof HTMLCanvasElement) {
                // TODO: better way of doing this?
                var target = arg.cloneNode(true);
                var ctx = target.getContext("2d");
                ctx.drawImage(arg, 0, 0);
                prepareDocumentElement(target);
                return target;
            } else if (arg instanceof HTMLImageElement) {
                // TODO: clone image data (src?)
                var target = arg.cloneNode(true);
                target.width = arg.width;
                target.height = arg.height;
                prepareDocumentElement(target);
                return target;
            } else if (arg instanceof HTMLVideoElement) {
                // TODO: clone video data (is this even possible? we want the exact frame at the time of upload - maybe preserve seek time?)
                var target = arg.cloneNode(true);
                prepareDocumentElement(target);
                return target;
            } else {
                return arg;
            }
        } else {
            return arg;
        }
    };

})();
<commit_msg>fixes for webkit<commit_after>// Hack to always define a console
if (!window["console"]) {
    window.console = { log: function () { } };
}

function glinamespace(name) {
    var parts = name.split(".");
    var current = window;
    for (var n = 0; n < parts.length; n++) {
        var part = parts[n];
        current[part] = current[part] || {};
        current = current[part];
    }
    return current;
}

function glisubclass(parent, child, args) {
    parent.apply(child, args);

    // TODO: this sucks - do it right

    for (var propertyName in parent.prototype) {
        if (propertyName == "constructor") {
            continue;
        }
        if (!child.__proto__[propertyName]) {
            child.__proto__[propertyName] = parent.prototype[propertyName];
        }
    }

    for (var propertyName in parent) {
        child[propertyName] = parent[propertyName];
    }
};

function glitypename(value) {
    function stripConstructor(value) {
        if (value) {
            return value.replace("Constructor", "");
        } else {
            return value;
        }
    };
    if (value) {
        var mangled = value.constructor.toString();
        if (mangled) {
            var matches = mangled.match(/function (.+)\(/);
            if (matches) {
                // ...function Foo()...
                if (matches[1] == "Object") {
                    // Hrm that's likely not right...
                    // constructor may be fubar
                    mangled = value.toString();
                } else {
                    return stripConstructor(matches[1]);
                }
            }

            // [object Foo]
            matches = mangled.match(/\[object (.+)\]/);
            if (matches) {
                return stripConstructor(matches[1]);
            }
        }
    }
    return null;
};

function scrollIntoViewIfNeeded(el) {
    if (el.scrollIntoViewIfNeeded) {
        el.scrollIntoViewIfNeeded();
    } else {
        // TODO: determine if el is in the current view of the parent
        var scrollTop = el.offsetParent.scrollTop;
        var scrollBottom = el.offsetParent.scrollTop + el.offsetParent.clientHeight;
        var elTop = el.offsetTop;
        var elBottom = el.offsetTop + el.offsetHeight;
        if ((elTop < scrollTop) || (elTop > scrollBottom)) {
            el.scrollIntoView();
        }
    }
};

(function () {
    var util = glinamespace("gli.util");

    // Adjust TypedArray types to have consistent toString methods
    var typedArrayToString = function () {
        var s = "";
        var maxIndex = Math.min(64, this.length);
        for (var n = 0; n < maxIndex; n++) {
            s += this[n];
            if (n < this.length - 1) {
                s += ",";
            }
        }
        if (maxIndex < this.length) {
            s += ",... (" + (this.length) + " total)";
        }
        return s;
    };
    Int8Array.prototype.toString = typedArrayToString;
    Uint8Array.prototype.toString = typedArrayToString;
    Int16Array.prototype.toString = typedArrayToString;
    Uint16Array.prototype.toString = typedArrayToString;
    Int32Array.prototype.toString = typedArrayToString;
    Uint32Array.prototype.toString = typedArrayToString;
    Float32Array.prototype.toString = typedArrayToString;

    util.isTypedArray = function (value) {
        if (value) {
            var typename = glitypename(value);
            switch (typename) {
                case "Int8Array":
                case "Uint8Array":
                case "Int16Array":
                case "Uint16Array":
                case "Int32Array":
                case "Uint32Array":
                case "Float32Array":
                    return true;
            }
            return false;
        } else {
            return false;
        }
    };

    util.isWebGLResource = function (value) {
        if (value) {
            var typename = glitypename(value);
            switch (typename) {
                case "WebGLBuffer":
                case "WebGLFramebuffer":
                case "WebGLProgram":
                case "WebGLRenderbuffer":
                case "WebGLShader":
                case "WebGLTexture":
                    return true;
            }
            return false;
        } else {
            return false;
        }
    }

    function prepareDocumentElement(el) {
        // FF requires all content be in a document before it'll accept it for playback
        if (window.navigator.product == "Gecko") {
            var frag = document.createDocumentFragment();
            frag.appendChild(el);
        }
    };

    util.clone = function (arg) {
        if (arg) {
            if ((arg.constructor == Number) || (arg.constructor == String)) {
                // Fast path for immutables
                return arg;
            } else if (arg.constructor == Array) {
                return arg.slice(); // ghetto clone
            } else if (arg instanceof ArrayBuffer) {
                // There may be a better way to do this, but I don't know it
                var target = new ArrayBuffer(arg.byteLength);
                var sourceView = new DataView(arg, 0, source.byteLength);
                var targetView = new DataView(target, 0, target.byteLength);
                for (var n = 0; n < source.byteLength; n++) {
                    targetView.setUInt8(n, sourceView.getUInt8(n));
                }
                return target;
            } else if (arg.__proto__.__proto__.constructor.toString().indexOf("ArrayBufferView") > 0) {
                //} else if (arg instanceof ArrayBufferView) {
                // HACK: at least Chromium doesn't have ArrayBufferView as a known type (for some reason)
                var target = null;
                if (arg instanceof Int8Array) {
                    target = new Int8Array(arg);
                } else if (arg instanceof Uint8Array) {
                    target = new Uint8Array(arg);
                } else if (arg instanceof Int16Array) {
                    target = new Int16Array(arg);
                } else if (arg instanceof Uint16Array) {
                    target = new Uint16Array(arg);
                } else if (arg instanceof Int32Array) {
                    target = new Int32Array(arg);
                } else if (arg instanceof Uint32Array) {
                    target = new Uint32Array(arg);
                } else if (arg instanceof Float32Array) {
                    target = new Float32Array(arg);
                } else if (arg instanceof Float64Array) {
                    target = new Float64Array(arg);
                } else {
                    target = arg;
                }
                return target;
            } else if (arg.__proto__.constructor.toString().indexOf("ImageData") > 0) {
                var dummyCanvas = document.createElement("canvas");
                var dummyContext = dummyCanvas.getContext("2d");
                var target = dummyContext.createImageData(arg);
                for (var n = 0; n < arg.data.length; n++) {
                    target.data[n] = arg.data[n];
                }
                return target;
            } else if (arg instanceof HTMLCanvasElement) {
                // TODO: better way of doing this?
                var target = arg.cloneNode(true);
                var ctx = target.getContext("2d");
                ctx.drawImage(arg, 0, 0);
                prepareDocumentElement(target);
                return target;
            } else if (arg instanceof HTMLImageElement) {
                // TODO: clone image data (src?)
                var target = arg.cloneNode(true);
                target.width = arg.width;
                target.height = arg.height;
                prepareDocumentElement(target);
                return target;
            } else if (arg instanceof HTMLVideoElement) {
                // TODO: clone video data (is this even possible? we want the exact frame at the time of upload - maybe preserve seek time?)
                var target = arg.cloneNode(true);
                prepareDocumentElement(target);
                return target;
            } else {
                return arg;
            }
        } else {
            return arg;
        }
    };

})();
<|endoftext|>


<commit_before>/*jshint esversion:6, node:true*/
/*
 * Application Core
 * https://github.com/goliatone/application-core
 *
 * Copyright (c) 2016 goliatone
 * Licensed under the MIT license.
 */
'use strict';

const path = require('path');
const glob = require('glob');
const extend = require('gextend');
const Keypath = require('gkeypath');
const EventEmitter = require('events');
const sanitizeName = require('./utils').sanitizeName;

const DEFAULTS = {
    logger: console,
    autorun: true,
    autoinitialize: true,
    name: 'Application',
    sanitizeName: sanitizeName,
    //TODO: monitoring should be enabled only for data processing apps.
    coremodules:['logger', 'errors', 'dispatcher', 'monitoring', 'repl'],
    basepath: process.cwd()
};

class Application extends EventEmitter {
    constructor(options){
        options = extend({}, DEFAULTS, options);

        super();

        if(options.autoinitialize) this.init(options);
    }

    init(config) {
        if(this.initialized) return;
        this.initialized = true;

        config = extend({}, DEFAULTS, config);

        extend(this, config);

        this.register(extend, 'extend');

        /*
         * This is not the most elegant solution
         * but
         */
        if(this.config.app) extend(this, this.config.app);

        this.config = Keypath.wrap(this.config, null, 'data');

        //FIGURE OUT HOW TO MERGE...
        var self = this;
        this.coremodules.map(function(module){
            console.log('coremodule', module);
            this.loadModule(module, path.resolve(path.join(__dirname, module)));
        }, this);

        if(this.loaders){
            //move to it's own file
            if(this.loaders.modules){
                // if(typeof this.loaders.modules === 'string') this.loaders.modules = [this.loaders.modules];
                this.loadDirectory(this.loaders.modules);
            }

            if(this.loaders.handlers){
                // if(typeof this.loaders.handlers === 'string') this.loaders.handlers = [this.loaders.handlers];
                this.loadHanlders(this.loaders.handlers);
            }
        }
    }

    register(instance, name){
        name = this.sanitizeName(name);
        console.log('- registering "%s"', name);
        this[name] = instance;
    }

    loadDirectory(dir, options){
        if(!path.isAbsolute(dir)){
            dir = path.join(getPathToMain(), dir);
        }

        this.logger.info('load directory %s', dir);

        var files = glob.sync(dir, options);
        var promises = files.map((file) => {
            return this.loadModule(getModuleName(file), file);
        });
        return Promise.all(promises);
    }

    loadHanlders(dir='handlers', options={}){
        if(!path.isAbsolute(dir)){
            dir = path.join(getPathToMain(), dir);
        }
        var pattern = dir;

        this.logger.info('- load handlers %s', dir);

        var files = glob.sync(pattern, options);
        var that = this;

        files.map((file) => {
            this.handle(getModuleName(file), require(file));
        });
    }

    loadModule(id, path){
        this.logger.info('- loading module "%s", %s', id, path);

        var instance,
            output = Promise.defer();

        try {
            //TODO: Define a module interface. Move this to a function that
            //we can override. Right now a module has to have a "init" function.
            instance = require(path).init(this, this.config.get(id, {}));
            output.resolve(instance);
        } catch (e) {
            this.logger.error('ERROR loading module "%s"', id);
            this.logger.error('path %s', path);
            this.logger.error(e.message);
            this.logger.error(e.stack);
            output.reject(e);
        }

        if(instance){
            this.register(instance, id);
        }

        return output.promise;
    }

    resolve(id){
        //This method could return a Promise and a proxy,
        //were we use the proxy to handle calls for instance
        //while its being loaded...
        var instance = this[id];
        return Promise.resolve(instance);
    }

    run(){
        if(this.didRun) return;
        this.didRun = true;

        //TODO: ideally we would have a way to manage each
        //cycle of running hooks. We would register a handler
        //and each whould return a promise, we wouldn't start
        //a new lifecycle until all are done

        setTimeout(() => {
            this.logger.info('Emit "run.pre"');
            this.emit('run.pre');

            this.logger.info('Emit "run"');
            this.emit('run');

            this.logger.info('Emit "run.post"');
            this.emit('run.post');
        }, 0);
    }

    //TODO: rename as command or registerCommand
    handle(event, handler){
        /*
         * Here Were Dragons... if you uncomment this
         * log, handler gets executed (?) and takes everything
         * out of wack.
         */
        // this.logger.info('- register handler for %s', event, handler);

        this.logger.info('- register handler for %s', event);
        handler = handler.bind(this);

        this.on(event, handler);
    }

    close(code, label){
        //here we could run a close routing. Whatever it is, it should not
        //take more than 10 seconds- Serene's default
        return Promise.resolve();
    }

    static loadConfig(options={}, asObject=true){
        if(!options.basepath) options.basepath = getPathToMain();

        var libDefaults = require('simple-config-loader')({
            basepath: __dirname
        });

        options = extend({}, DEFAULTS, libDefaults.data, options);

        var config = require('simple-config-loader')({
            config: options,
            basepath: process.cwd()
        });

        if(asObject) return config._target;
        return config;
    }
}

function getPathToMain(){
    var sep = require('path').sep;
    var main = process.argv[1];
    main = main.split(sep);
    main.pop();
    main = main.join(sep);
    return main;
}

function getModuleName(file){
    return path.basename(file).replace(path.extname(file), '');
}

/**
 * Exports module
 */
module.exports = Application;
<commit_msg>wip application<commit_after>/*jshint esversion:6, node:true*/
/*
 * Application Core
 * https://github.com/goliatone/application-core
 *
 * Copyright (c) 2016 goliatone
 * Licensed under the MIT license.
 */
'use strict';

const path = require('path');
const glob = require('glob');
const extend = require('gextend');
const Keypath = require('gkeypath');
const EventEmitter = require('events');
const PluginLoader = require('in');
const sanitizeName = require('./utils').sanitizeName;

const DEFAULTS = {
    logger: console,
    autorun: true,
    autoinitialize: true,
    name: 'Application',
    sanitizeName: sanitizeName,
    //TODO: monitoring should be enabled only for data processing apps.
    coremodules: ['./logger', './errors', './dispatcher', './monitoring', './repl'],
    basepath: process.cwd()
};

class Application extends EventEmitter {
    constructor(options){
        options = extend({}, DEFAULTS, options);

        super();

        if(options.autoinitialize) this.init(options);
    }

    init(config) {
        if(this.initialized) return;
        this.initialized = true;

        config = extend({}, DEFAULTS, config);

        extend(this, config);

        /*
         * This is not the most elegant solution
         * but
         */
        if(this.config.app) extend(this, this.config.app);

        this.config = Keypath.wrap(this.config, null, 'data');

        ///*
        const loader = new PluginLoader({
            context: this,
            basepath: __dirname,
            mountHandler: function _mount(bean, context){
                var plugin = bean.plugin;
                var config = context.config.get(bean.id, {});
                var instance = plugin.init(context, config);
                context.register(instance, bean.id);
                return plugin;
            },
            afterMount: function(context){
                context.emit('coreplugins.ready');
                context.logger.log('Core modules loaded!');
            }
        });

        this.register(extend, 'extend');

        loader.mountList(this.coremodules)
            .then(()=>{
                if(!this.loaders) return;
                if(this.loaders.modules){
                    let modulepath = path.resolve(this.loaders.modules);
                    loader.mountDirectory(modulepath);
                }

                if(this.loaders.handlers){
                    // if(typeof this.loaders.handlers === 'string') this.loaders.handlers = [this.loaders.handlers];
                    this.loadHanlders(this.loaders.handlers);
                }
            }).catch((err)=>{
                console.log('ERROR', err.message);
                console.log('ERROR', err.stack);
            });
        //*/

        /*var self = this;

        if(this.loaders){
            //move to it's own file
            if(this.loaders.modules){
                // if(typeof this.loaders.modules === 'string') this.loaders.modules = [this.loaders.modules];
                this.loadDirectory(this.loaders.modules);
            }

            if(this.loaders.handlers){
                // if(typeof this.loaders.handlers === 'string') this.loaders.handlers = [this.loaders.handlers];
                this.loadHanlders(this.loaders.handlers);
            }
        }*/
    }

    register(instance, name){
        name = this.sanitizeName(name);
        this[name] = instance;
    }

    loadDirectory(dir, options){
        if(!path.isAbsolute(dir)){
            dir = path.join(getPathToMain(), dir);
        }

        this.logger.info('load directory %s', dir);

        var files = glob.sync(dir, options);
        var promises = files.map((file) => {
            return this.loadModule(getModuleName(file), file);
        });
        return Promise.all(promises);
    }

    loadHanlders(dir='handlers', options={}){
        if(!path.isAbsolute(dir)){
            dir = path.join(getPathToMain(), dir);
        }
        var pattern = dir;

        this.logger.info('- load handlers %s', dir);

        var files = glob.sync(pattern, options);
        var that = this;

        files.map((file) => {
            this.handle(getModuleName(file), require(file));
        });
    }

    loadModule(id, path){
        this.logger.info('- loading module "%s", %s', id, path);

        var instance,
            output = Promise.defer();

        try {
            //TODO: Define a module interface. Move this to a function that
            //we can override. Right now a module has to have a "init" function.
            instance = require(path).init(this, this.config.get(id, {}));
            output.resolve(instance);
        } catch (e) {
            this.logger.error('ERROR loading module "%s"', id);
            this.logger.error('path %s', path);
            this.logger.error(e.message);
            this.logger.error(e.stack);
            output.reject(e);
        }

        if(instance){
            this.register(instance, id);
        }

        return output.promise;
    }

    resolve(id){
        //This method could return a Promise and a proxy,
        //were we use the proxy to handle calls for instance
        //while its being loaded...
        var instance = this[id];
        return Promise.resolve(instance);
    }

    run(){
        if(this.didRun) return;
        this.didRun = true;

        //TODO: ideally we would have a way to manage each
        //cycle of running hooks. We would register a handler
        //and each whould return a promise, we wouldn't start
        //a new lifecycle until all are done

        setTimeout(() => {
            this.logger.info('Emit "run.pre"');
            this.emit('run.pre');

            this.logger.info('Emit "run"');
            this.emit('run');

            this.logger.info('Emit "run.post"');
            this.emit('run.post');
        }, 0);
    }

    //TODO: rename as command or registerCommand
    handle(event, handler){
        /*
         * Here Were Dragons... if you uncomment this
         * log, handler gets executed (?) and takes everything
         * out of wack.
         */
        // this.logger.info('- register handler for %s', event, handler);

        this.logger.info('- register handler for %s', event);
        handler = handler.bind(this);

        this.on(event, handler);
    }

    close(code, label){
        //here we could run a close routing. Whatever it is, it should not
        //take more than 10 seconds- Serene's default
        return Promise.resolve();
    }

    set name(name = ''){
        this._name = name;
        //we have not run extend and sanitizeName is
        //not part of the prototype :)
        this._slug = sanitizeName(name);
    }
    get name(){
        return this._name;
    }

    static loadConfig(options={}, asObject=true){
        if(!options.basepath) options.basepath = getPathToMain();

        var libDefaults = require('simple-config-loader')({
            basepath: __dirname
        });

        options = extend({}, DEFAULTS, libDefaults.data, options);

        var config = require('simple-config-loader')({
            config: options,
            basepath: process.cwd()
        });

        if(asObject) return config._target;
        return config;
    }
}

function getPathToMain(){
    var sep = require('path').sep;
    var main = process.argv[1];
    main = main.split(sep);
    main.pop();
    main = main.join(sep);
    return main;
}

function getModuleName(file){
    return path.basename(file).replace(path.extname(file), '');
}

/**
 * Exports module
 */
module.exports = Application;
<|endoftext|>


<commit_before>
'use strict';

/**
 * Module dependencies.
 */

const isGeneratorFunction = require('is-generator-function');
const debug = require('debug')('koa:application');
const onFinished = require('on-finished');
const response = require('./response');
const compose = require('koa-compose');
const isJSON = require('koa-is-json');
const context = require('./context');
const request = require('./request');
const statuses = require('statuses');
const Cookies = require('cookies');
const accepts = require('accepts');
const Emitter = require('events');
const assert = require('assert');
const Stream = require('stream');
const http = require('http');
const only = require('only');
const convert = require('koa-convert');
const deprecate = require('depd')('koa');

/**
 * Expose `Application` class.
 * Inherits from `Emitter.prototype`.
 */

module.exports = class Application extends Emitter {
  /**
   * Initialize a new `Application`.
   *
   * @api public
   */

  constructor() {
    super();

    this.proxy = false;
    this.middleware = [];
    this.subdomainOffset = 2;
    this.env = process.env.NODE_ENV || 'development';
    this.context = Object.create(context);
    this.request = Object.create(request);
    this.response = Object.create(response);
  }

  /**
   * Shorthand for:
   *
   *    http.createServer(app.callback()).listen(...)
   *
   * @param {Mixed} ...
   * @return {Server}
   * @api public
   */

  listen(...args) {
    debug('listen');
    const server = http.createServer(this.callback());
    return server.listen(...args);
  }

  /**
   * Return JSON representation.
   * We only bother showing settings.
   *
   * @return {Object}
   * @api public
   */

  toJSON() {
    return only(this, [
      'subdomainOffset',
      'proxy',
      'env'
    ]);
  }

  /**
   * Inspect implementation.
   *
   * @return {Object}
   * @api public
   */

  inspect() {
    return this.toJSON();
  }

  /**
   * Use the given middleware `fn`.
   *
   * Old-style middleware will be converted.
   *
   * @param {Function} fn
   * @return {Application} self
   * @api public
   */

  use(fn) {
    if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
    if (isGeneratorFunction(fn)) {
      deprecate('Support for generators will be removed in v3. ' +
                'See the documentation for examples of how to convert old middleware ' +
                'https://github.com/koajs/koa/blob/master/docs/migration.md');
      fn = convert(fn);
    }
    debug('use %s', fn._name || fn.name || '-');
    this.middleware.push(fn);
    return this;
  }

  /**
   * Return a request handler callback
   * for node's native http server.
   *
   * @return {Function}
   * @api public
   */

  callback() {
    const fn = compose(this.middleware);

    if (!this.listeners('error').length) this.on('error', this.onerror);

    const handleRequest = (req, res) => {
      const ctx = this.createContext(req, res);
      return this.handleRequest(ctx, fn);
    };

    return handleRequest;
  }

  /**
   * Handle request in callback.
   *
   * @api private
   */

  handleRequest(ctx, fnMiddleware) {
    const res = ctx.res;
    res.statusCode = 404;
    const onerror = err => ctx.onerror(err);
    const handleResponse = () => respond(ctx);
    onFinished(res, onerror);
    return fnMiddleware(ctx).then(handleResponse).catch(onerror);
  }

  /**
   * Initialize a new context.
   *
   * @api private
   */

  createContext(req, res) {
    const context = Object.create(this.context);
    const request = context.request = Object.create(this.request);
    const response = context.response = Object.create(this.response);
    context.app = request.app = response.app = this;
    context.req = request.req = response.req = req;
    context.res = request.res = response.res = res;
    request.ctx = response.ctx = context;
    request.response = response;
    response.request = request;
    context.originalUrl = request.originalUrl = req.url;
    context.cookies = new Cookies(req, res, {
      keys: this.keys,
      secure: request.secure
    });
    request.ip = request.ips[0] || req.socket.remoteAddress || '';
    context.accept = request.accept = accepts(req);
    context.state = {};
    return context;
  }

  /**
   * Default error handler.
   *
   * @param {Error} err
   * @api private
   */

  onerror(err) {
    assert(err instanceof Error, `non-error thrown: ${err}`);

    if (404 == err.status || err.expose) return;
    if (this.silent) return;

    const msg = err.stack || err.toString();
    console.error();
    console.error(msg.replace(/^/gm, '  '));
    console.error();
  }
};

/**
 * Response helper.
 */

function respond(ctx) {
  // allow bypassing koa
  if (false === ctx.respond) return;

  const res = ctx.res;
  if (!ctx.writable) return;

  let body = ctx.body;
  const code = ctx.status;

  // ignore body
  if (statuses.empty[code]) {
    // strip headers
    ctx.body = null;
    return res.end();
  }

  if ('HEAD' == ctx.method) {
    if (!res.headersSent && isJSON(body)) {
      ctx.length = Buffer.byteLength(JSON.stringify(body));
    }
    return res.end();
  }

  // status body
  if (null == body) {
    body = ctx.message || String(code);
    if (!res.headersSent) {
      ctx.type = 'text';
      ctx.length = Buffer.byteLength(body);
    }
    return res.end(body);
  }

  // responses
  if (Buffer.isBuffer(body)) return res.end(body);
  if ('string' == typeof body) return res.end(body);
  if (body instanceof Stream) return body.pipe(res);

  // body: json
  body = JSON.stringify(body);
  if (!res.headersSent) {
    ctx.length = Buffer.byteLength(body);
  }
  res.end(body);
}
<commit_msg>chore: Using "listenerCount" instead of "listeners" (#1184)<commit_after>
'use strict';

/**
 * Module dependencies.
 */

const isGeneratorFunction = require('is-generator-function');
const debug = require('debug')('koa:application');
const onFinished = require('on-finished');
const response = require('./response');
const compose = require('koa-compose');
const isJSON = require('koa-is-json');
const context = require('./context');
const request = require('./request');
const statuses = require('statuses');
const Cookies = require('cookies');
const accepts = require('accepts');
const Emitter = require('events');
const assert = require('assert');
const Stream = require('stream');
const http = require('http');
const only = require('only');
const convert = require('koa-convert');
const deprecate = require('depd')('koa');

/**
 * Expose `Application` class.
 * Inherits from `Emitter.prototype`.
 */

module.exports = class Application extends Emitter {
  /**
   * Initialize a new `Application`.
   *
   * @api public
   */

  constructor() {
    super();

    this.proxy = false;
    this.middleware = [];
    this.subdomainOffset = 2;
    this.env = process.env.NODE_ENV || 'development';
    this.context = Object.create(context);
    this.request = Object.create(request);
    this.response = Object.create(response);
  }

  /**
   * Shorthand for:
   *
   *    http.createServer(app.callback()).listen(...)
   *
   * @param {Mixed} ...
   * @return {Server}
   * @api public
   */

  listen(...args) {
    debug('listen');
    const server = http.createServer(this.callback());
    return server.listen(...args);
  }

  /**
   * Return JSON representation.
   * We only bother showing settings.
   *
   * @return {Object}
   * @api public
   */

  toJSON() {
    return only(this, [
      'subdomainOffset',
      'proxy',
      'env'
    ]);
  }

  /**
   * Inspect implementation.
   *
   * @return {Object}
   * @api public
   */

  inspect() {
    return this.toJSON();
  }

  /**
   * Use the given middleware `fn`.
   *
   * Old-style middleware will be converted.
   *
   * @param {Function} fn
   * @return {Application} self
   * @api public
   */

  use(fn) {
    if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
    if (isGeneratorFunction(fn)) {
      deprecate('Support for generators will be removed in v3. ' +
                'See the documentation for examples of how to convert old middleware ' +
                'https://github.com/koajs/koa/blob/master/docs/migration.md');
      fn = convert(fn);
    }
    debug('use %s', fn._name || fn.name || '-');
    this.middleware.push(fn);
    return this;
  }

  /**
   * Return a request handler callback
   * for node's native http server.
   *
   * @return {Function}
   * @api public
   */

  callback() {
    const fn = compose(this.middleware);

    if (!this.listenerCount('error')) this.on('error', this.onerror);

    const handleRequest = (req, res) => {
      const ctx = this.createContext(req, res);
      return this.handleRequest(ctx, fn);
    };

    return handleRequest;
  }

  /**
   * Handle request in callback.
   *
   * @api private
   */

  handleRequest(ctx, fnMiddleware) {
    const res = ctx.res;
    res.statusCode = 404;
    const onerror = err => ctx.onerror(err);
    const handleResponse = () => respond(ctx);
    onFinished(res, onerror);
    return fnMiddleware(ctx).then(handleResponse).catch(onerror);
  }

  /**
   * Initialize a new context.
   *
   * @api private
   */

  createContext(req, res) {
    const context = Object.create(this.context);
    const request = context.request = Object.create(this.request);
    const response = context.response = Object.create(this.response);
    context.app = request.app = response.app = this;
    context.req = request.req = response.req = req;
    context.res = request.res = response.res = res;
    request.ctx = response.ctx = context;
    request.response = response;
    response.request = request;
    context.originalUrl = request.originalUrl = req.url;
    context.cookies = new Cookies(req, res, {
      keys: this.keys,
      secure: request.secure
    });
    request.ip = request.ips[0] || req.socket.remoteAddress || '';
    context.accept = request.accept = accepts(req);
    context.state = {};
    return context;
  }

  /**
   * Default error handler.
   *
   * @param {Error} err
   * @api private
   */

  onerror(err) {
    assert(err instanceof Error, `non-error thrown: ${err}`);

    if (404 == err.status || err.expose) return;
    if (this.silent) return;

    const msg = err.stack || err.toString();
    console.error();
    console.error(msg.replace(/^/gm, '  '));
    console.error();
  }
};

/**
 * Response helper.
 */

function respond(ctx) {
  // allow bypassing koa
  if (false === ctx.respond) return;

  const res = ctx.res;
  if (!ctx.writable) return;

  let body = ctx.body;
  const code = ctx.status;

  // ignore body
  if (statuses.empty[code]) {
    // strip headers
    ctx.body = null;
    return res.end();
  }

  if ('HEAD' == ctx.method) {
    if (!res.headersSent && isJSON(body)) {
      ctx.length = Buffer.byteLength(JSON.stringify(body));
    }
    return res.end();
  }

  // status body
  if (null == body) {
    body = ctx.message || String(code);
    if (!res.headersSent) {
      ctx.type = 'text';
      ctx.length = Buffer.byteLength(body);
    }
    return res.end(body);
  }

  // responses
  if (Buffer.isBuffer(body)) return res.end(body);
  if ('string' == typeof body) return res.end(body);
  if (body instanceof Stream) return body.pipe(res);

  // body: json
  body = JSON.stringify(body);
  if (!res.headersSent) {
    ctx.length = Buffer.byteLength(body);
  }
  res.end(body);
}
<|endoftext|>


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

var debug = require('debug')('koa:application');
var Emitter = require('events').EventEmitter;
var compose = require('koa-compose');
var context = require('./context');
var request = require('./request');
var response = require('./response');
var Cookies = require('cookies');
var Keygrip = require('keygrip');
var assert = require('assert');
var http = require('http');
var co = require('co');

/**
 * Application prototype.
 */

var app = Application.prototype;

/**
 * Expose `Application`.
 */

exports = module.exports = Application;

/**
 * Initialize a new `Application`.
 *
 * @api public
 */

function Application() {
  if (!(this instanceof Application)) return new Application;
  this.env = process.env.NODE_ENV || 'development';
  this.on('error', this.onerror);
  this.outputErrors = 'test' != this.env;
  this.subdomainOffset = 2;
  this.poweredBy = true;
  this.jsonSpaces = 2;
  this.middleware = [];
  this.context = Object.create(context);
  this.request = Object.create(request);
  this.response = Object.create(response);
}

/**
 * Inherit from `Emitter.prototype`.
 */

Application.prototype.__proto__ = Emitter.prototype;

/**
 * Shorthand for:
 *
 *    http.createServer(app.callback()).listen(...)
 *
 * @param {Mixed} ...
 * @return {Server}
 * @api public
 */

app.listen = function(){
  debug('listen');
  var server = http.createServer(this.callback());
  return server.listen.apply(server, arguments);
};

/**
 * Use the given middleware `fn`.
 *
 * @param {GeneratorFunction} fn
 * @return {Application} self
 * @api public
 */

app.use = function(fn){
  assert('GeneratorFunction' == fn.constructor.name, 'app.use() requires a generator function');
  debug('use %s', fn.name || '-');
  this.middleware.push(fn);
  return this;
};

/**
 * Return a request handler callback
 * for node's native http server.
 *
 * @return {Function}
 * @api public
 */

app.callback = function(){
  var mw = [respond].concat(this.middleware);
  var gen = compose(mw);
  var fn = co(gen);
  var self = this;

  return function(req, res, next){
    var ctx = self.createContext(req, res);
    next = next || ctx.onerror;
    ctx.onSocketError(next);
    fn.call(ctx, next);
  }
};

/**
 * Set signed cookie keys.
 *
 * These are passed to [KeyGrip](https://github.com/jed/keygrip),
 * however you may also pass your own `KeyGrip` instance. For
 * example the following are acceptable:
 *
 *   app.keys = ['im a newer secret', 'i like turtle'];
 *   app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');
 *
 * @param {Array|KeyGrip} keys
 * @api public
 */

app.__defineSetter__('keys', function(keys){
  var ok = Array.isArray(keys) || keys instanceof Keygrip;
  debug('keys %j', keys);
  if (!ok) throw new TypeError('app.keys must be an array or Keygrip');
  if (!(keys instanceof Keygrip)) keys = new Keygrip(keys);
  this._keys = keys;
});

/**
 * Get `Keygrip` instance.
 *
 * @return {Keygrip}
 * @api public
 */

app.__defineGetter__('keys', function(){
  return this._keys;
});

/**
 * Initialize a new context.
 *
 * @api private
 */

app.createContext = function(req, res){
  var context = Object.create(this.context);
  var request = context.request = Object.create(this.request);
  var response = context.response = Object.create(this.response);
  context.app = request.app = response.app = this;
  context.req = request.req = response.req = req;
  context.res = request.res = response.res = res;
  request.ctx = response.ctx = context;
  request.response = response;
  response.request = request;
  context.onerror = context.onerror.bind(context);
  context.originalUrl = request.originalUrl = req.url;
  context.cookies = new Cookies(req, res, this.keys);
  return context;
};

/**
 * Default error handler.
 *
 * @param {Error} err
 * @api private
 */

app.onerror = function(err){
  if (!this.outputErrors) return;
  if (404 == err.status) return;
  console.error(err.stack);
};

/**
 * Response middleware.
 */

function *respond(next){
  this.status = 200;
  if (this.app.poweredBy) this.set('X-Powered-By', 'koa');

  yield next;

  var res = this.res;
  var body = this.body;
  var head = 'HEAD' == this.method;
  var noContent = ~[204, 205, 304].indexOf(this.status);

  // 404
  if (null == body && 200 == this.status) {
    this.status = 404;
  }

  // ignore body
  if (noContent) return res.end();

  // status body
  if (null == body) {
    this.type = 'text';
    body = http.STATUS_CODES[this.status];
  }

  // Buffer body
  if (Buffer.isBuffer(body)) {
    if (head) return res.end();
    return res.end(body);
  }

  // string body
  if ('string' == typeof body) {
    if (head) return res.end();
    return res.end(body);
  }

  // Stream body
  if ('function' == typeof body.pipe) {
    if (!~body.listeners('error').indexOf(this.onerror)) body.on('error', this.onerror);

    if (head) {
      if (body.close) body.close();
      return res.end();
    }

    return body.pipe(res);
  }

  // body: json
  body = JSON.stringify(body, null, this.app.jsonSpaces);
  this.length = Buffer.byteLength(body);
  if (head) return res.end();
  res.end(body);
}
<commit_msg>remove `next` in callback for now<commit_after>/**
 * Module dependencies.
 */

var debug = require('debug')('koa:application');
var Emitter = require('events').EventEmitter;
var compose = require('koa-compose');
var context = require('./context');
var request = require('./request');
var response = require('./response');
var Cookies = require('cookies');
var Keygrip = require('keygrip');
var assert = require('assert');
var http = require('http');
var co = require('co');

/**
 * Application prototype.
 */

var app = Application.prototype;

/**
 * Expose `Application`.
 */

exports = module.exports = Application;

/**
 * Initialize a new `Application`.
 *
 * @api public
 */

function Application() {
  if (!(this instanceof Application)) return new Application;
  this.env = process.env.NODE_ENV || 'development';
  this.on('error', this.onerror);
  this.outputErrors = 'test' != this.env;
  this.subdomainOffset = 2;
  this.poweredBy = true;
  this.jsonSpaces = 2;
  this.middleware = [];
  this.context = Object.create(context);
  this.request = Object.create(request);
  this.response = Object.create(response);
}

/**
 * Inherit from `Emitter.prototype`.
 */

Application.prototype.__proto__ = Emitter.prototype;

/**
 * Shorthand for:
 *
 *    http.createServer(app.callback()).listen(...)
 *
 * @param {Mixed} ...
 * @return {Server}
 * @api public
 */

app.listen = function(){
  debug('listen');
  var server = http.createServer(this.callback());
  return server.listen.apply(server, arguments);
};

/**
 * Use the given middleware `fn`.
 *
 * @param {GeneratorFunction} fn
 * @return {Application} self
 * @api public
 */

app.use = function(fn){
  assert('GeneratorFunction' == fn.constructor.name, 'app.use() requires a generator function');
  debug('use %s', fn.name || '-');
  this.middleware.push(fn);
  return this;
};

/**
 * Return a request handler callback
 * for node's native http server.
 *
 * @return {Function}
 * @api public
 */

app.callback = function(){
  var mw = [respond].concat(this.middleware);
  var gen = compose(mw);
  var fn = co(gen);
  var self = this;

  return function(req, res){
    var ctx = self.createContext(req, res);
    ctx.onSocketError(ctx.onerror);
    fn.call(ctx, ctx.onerror);
  }
};

/**
 * Set signed cookie keys.
 *
 * These are passed to [KeyGrip](https://github.com/jed/keygrip),
 * however you may also pass your own `KeyGrip` instance. For
 * example the following are acceptable:
 *
 *   app.keys = ['im a newer secret', 'i like turtle'];
 *   app.keys = new KeyGrip(['im a newer secret', 'i like turtle'], 'sha256');
 *
 * @param {Array|KeyGrip} keys
 * @api public
 */

app.__defineSetter__('keys', function(keys){
  var ok = Array.isArray(keys) || keys instanceof Keygrip;
  debug('keys %j', keys);
  if (!ok) throw new TypeError('app.keys must be an array or Keygrip');
  if (!(keys instanceof Keygrip)) keys = new Keygrip(keys);
  this._keys = keys;
});

/**
 * Get `Keygrip` instance.
 *
 * @return {Keygrip}
 * @api public
 */

app.__defineGetter__('keys', function(){
  return this._keys;
});

/**
 * Initialize a new context.
 *
 * @api private
 */

app.createContext = function(req, res){
  var context = Object.create(this.context);
  var request = context.request = Object.create(this.request);
  var response = context.response = Object.create(this.response);
  context.app = request.app = response.app = this;
  context.req = request.req = response.req = req;
  context.res = request.res = response.res = res;
  request.ctx = response.ctx = context;
  request.response = response;
  response.request = request;
  context.onerror = context.onerror.bind(context);
  context.originalUrl = request.originalUrl = req.url;
  context.cookies = new Cookies(req, res, this.keys);
  return context;
};

/**
 * Default error handler.
 *
 * @param {Error} err
 * @api private
 */

app.onerror = function(err){
  if (!this.outputErrors) return;
  if (404 == err.status) return;
  console.error(err.stack);
};

/**
 * Response middleware.
 */

function *respond(next){
  this.status = 200;
  if (this.app.poweredBy) this.set('X-Powered-By', 'koa');

  yield next;

  var res = this.res;
  var body = this.body;
  var head = 'HEAD' == this.method;
  var noContent = ~[204, 205, 304].indexOf(this.status);

  // 404
  if (null == body && 200 == this.status) {
    this.status = 404;
  }

  // ignore body
  if (noContent) return res.end();

  // status body
  if (null == body) {
    this.type = 'text';
    body = http.STATUS_CODES[this.status];
  }

  // Buffer body
  if (Buffer.isBuffer(body)) {
    if (head) return res.end();
    return res.end(body);
  }

  // string body
  if ('string' == typeof body) {
    if (head) return res.end();
    return res.end(body);
  }

  // Stream body
  if ('function' == typeof body.pipe) {
    if (!~body.listeners('error').indexOf(this.onerror)) body.on('error', this.onerror);

    if (head) {
      if (body.close) body.close();
      return res.end();
    }

    return body.pipe(res);
  }

  // body: json
  body = JSON.stringify(body, null, this.app.jsonSpaces);
  this.length = Buffer.byteLength(body);
  if (head) return res.end();
  res.end(body);
}
<|endoftext|>