<commit_before>
var query   = require('querystring');

var express = require('express'),
  bodyParser = require('body-parser'),
  multipart = require('connect-multiparty'),
  cookieParser = require('cookie-parser'),
  session = require('express-session'),
  favicon = require('serve-favicon');

var gate    = require('./lib/core'), keeper;

function Guardian (config) {
  config = require('./config')(config);
  var app = express()
    .use(favicon(__dirname+'/favicon.ico'))
    // body parser
    .use(bodyParser.json())
    .use(bodyParser.urlencoded({extended: true}))
    .use(multipart())
    // session
    .use(cookieParser())
    .use(session({
      name: 'grant', secret: 'very secret',
      saveUninitialized: true, resave: true
    }));

  app.get('/connect/:provider', function (req, res) {
    var provider = config.app[req.params.provider];
    var server = config.server;
    req.session.provider = req.params.provider;

    // Generate options object
    var opts = {
      clientId: provider['client_id'],
      clientSecret: provider['client_secret'],
      consumerKey: provider['consumer_key'],
      consumerSecret: provider['consumer_secret'],
      grantType: provider['grant_type'],
      state: provider['state'],
      scope: provider['scope'],
      baseUrl: provider['base_url'],
      requestUrl: provider['request_url'],
      accessUrl: provider['access_url'],
      accessName: provider['access_name'],
      authorizeUrl: provider['authorize_url'],
      authorizeMethod: provider['authorize_method'],
      signatureMethod: provider['signature_method'],
      oauth_token: provider['oauth_token'],
      // callbackUrl: provider['redirect'] ? provider['redirect'] : server.protocol + '://' + server.host + '/callback',
      callbackUrl: server.protocol+'://'+server.host+'/connect/'+provider.name+'/callback',
      version: provider['version'],
      headers: provider['headers'],
      // custom
      // made type parameter optional for dropbox
      type: provider['type'],
      // used to set access_type=offline for google
      access_type: provider['access_type'],
      // used to set permissions for flickr
      perms: provider['perms'],

      auth: {
        type: (provider['auth_type'] || 'oauth').replace(/[^a-z]/g, ''),
        flow: (provider['auth_flow'] || '').replace(/[^a-z\_]/g, ''),
        version: isNaN(parseInt(provider['auth_version'], 10)) ? false : parseInt(provider['auth_version'], 10),
        leg: isNaN(parseInt(provider['auth_leg'], 10)) ? false : parseInt(provider['auth_leg'], 10)
      },

      done: {
        callback: provider['callback']
      }
    };

    // 1. Load plugin
    // 2. Run validation
    // 3. Store options object
    try {
      var path = gate.generatePluginPath(opts.auth);
      var plugin = gate.requirePlugin(opts.auth);
      var error = plugin.validate(opts);

      // Check plugin
      if (!plugin) {
        throw new Error("PLUGIN_MISSING");
      }

      // Check plugin validation
      if (error) {
        return res.jsonp(500, {
          code: 'PLUGIN_VALIDATION',
          message: error
        });
      }

      // Convert underscores in signature method to dashes
      if (opts.signatureMethod && opts.signatureMethod.indexOf("_"))
        opts.signatureMethod = opts.signatureMethod.replace('_', '-');

      // Retrieve session data
      req.session.data = opts;

      // Setup data from response on session data object
      if (req.param('url'))
        req.session.data.call_url = req.param('url');

      if (req.param('method'))
        req.session.data.call_method = req.param('method');

      if (req.param('body'))
        req.session.data.call_body = req.param('body');

      if (req.param('parameters'))
        req.session.data.parameters = req.param('parameters');

      // Invoke guardian gatekeeper
      keeper = gate({ req: req, res: res });
      keeper.invokeStep(1);
    } catch (e) {
      res.jsonp(500, {
        code: 'PLUGIN_MISSING',
        message: 'Invalid plugin specified, could not find plugin: ' + opts.auth.type.toLowerCase() + path.flow + path.version + path.leg
      });
    }
  });

  app.get('/step/:number', function (req, res) {
    keeper = gate({ req: req, res: res });
    keeper.invokeStep(parseInt(req.params.number, 10));
  });

  app.get('/connect/:provider/callback', function (req, res) {
    var plugin;
    var step;
    var data;
    var args;

    if (!req.session.data) {
      return res.json(500, {
        code: 'MISSING_SESSION_DETAILS',
        message: 'Session details are missing, perhaps the redirect url is on another server or the request timed out.'
      });
    }

    // Parse session data
    data = JSON.parse(JSON.stringify(req.session.data));

    // Include plugin
    plugin = gate.requirePlugin(data.auth);

    if (!plugin.step.callback) {
      return res.json(500, {
        code: 'MISSING_CALLBACK_STEP',
        message: 'Callback step is missing, unable to continue authentication process.'
      });
    }

    // Fetch information from previously set data.
    step = req.session.data.step;
    args = {};

    // Retrieve information returned from authentication step
    if (req.param('oauth_token'))
      args.token = req.param('oauth_token');

    if (req.param('oauth_verifier'))
      args.verifier = req.param('oauth_verifier');

    if (req.param('code'))
      args.code = req.param('code');

    if (req.param('state'))
      args.state = req.param('state');

    // Next?
    plugin.step.callback.next({ req: req, res: res }, args, function (response) {
      if (response) {
        return (!data.done.callback || data.done.callback == "oob")
          ? res.json(response)
          : res.redirect(data.done.callback + '?' + query.stringify(response));
      }

      if ((step + 1) > plugin.steps) {
        return res.json(500, {
          code: 'ALL_STEPS_COMPLETE',
          message: 'All steps have been completed, authentication should have happened, please try again.'
        });
      }

      res.redirect('/step/' + (step + 1));
    });
  });

  return app;
}

exports = module.exports = Guardian;
<commit_msg>Expose grant config<commit_after>
var query   = require('querystring');

var express = require('express'),
  bodyParser = require('body-parser'),
  multipart = require('connect-multiparty'),
  cookieParser = require('cookie-parser'),
  session = require('express-session'),
  favicon = require('serve-favicon');

var gate = require('./lib/core'), keeper;

function Guardian (config) {
  var app = express()
    .use(favicon(__dirname+'/favicon.ico'))
    // body parser
    .use(bodyParser.json())
    .use(bodyParser.urlencoded({extended: true}))
    .use(multipart())
    // session
    .use(cookieParser())
    .use(session({
      name: 'grant', secret: 'very secret',
      saveUninitialized: true, resave: true
    }));
  app.config = require('./config')(config);

  app.get('/connect/:provider', function (req, res) {
    var provider = app.config.app[req.params.provider];
    var server = app.config.server;
    req.session.provider = req.params.provider;

    // Generate options object
    var opts = {
      clientId: provider['client_id'],
      clientSecret: provider['client_secret'],
      consumerKey: provider['consumer_key'],
      consumerSecret: provider['consumer_secret'],
      grantType: provider['grant_type'],
      state: provider['state'],
      scope: provider['scope'],
      baseUrl: provider['base_url'],
      requestUrl: provider['request_url'],
      accessUrl: provider['access_url'],
      accessName: provider['access_name'],
      authorizeUrl: provider['authorize_url'],
      authorizeMethod: provider['authorize_method'],
      signatureMethod: provider['signature_method'],
      oauth_token: provider['oauth_token'],
      // callbackUrl: provider['redirect'] ? provider['redirect'] : server.protocol + '://' + server.host + '/callback',
      callbackUrl: server.protocol+'://'+server.host+'/connect/'+provider.name+'/callback',
      version: provider['version'],
      headers: provider['headers'],
      // custom
      // made type parameter optional for dropbox
      type: provider['type'],
      // used to set access_type=offline for google
      access_type: provider['access_type'],
      // used to set permissions for flickr
      perms: provider['perms'],

      auth: {
        type: (provider['auth_type'] || 'oauth').replace(/[^a-z]/g, ''),
        flow: (provider['auth_flow'] || '').replace(/[^a-z\_]/g, ''),
        version: isNaN(parseInt(provider['auth_version'], 10)) ? false : parseInt(provider['auth_version'], 10),
        leg: isNaN(parseInt(provider['auth_leg'], 10)) ? false : parseInt(provider['auth_leg'], 10)
      },

      done: {
        callback: provider['callback']
      }
    };

    // 1. Load plugin
    // 2. Run validation
    // 3. Store options object
    try {
      var path = gate.generatePluginPath(opts.auth);
      var plugin = gate.requirePlugin(opts.auth);
      var error = plugin.validate(opts);

      // Check plugin
      if (!plugin) {
        throw new Error("PLUGIN_MISSING");
      }

      // Check plugin validation
      if (error) {
        return res.jsonp(500, {
          code: 'PLUGIN_VALIDATION',
          message: error
        });
      }

      // Convert underscores in signature method to dashes
      if (opts.signatureMethod && opts.signatureMethod.indexOf("_"))
        opts.signatureMethod = opts.signatureMethod.replace('_', '-');

      // Retrieve session data
      req.session.data = opts;

      // Setup data from response on session data object
      if (req.param('url'))
        req.session.data.call_url = req.param('url');

      if (req.param('method'))
        req.session.data.call_method = req.param('method');

      if (req.param('body'))
        req.session.data.call_body = req.param('body');

      if (req.param('parameters'))
        req.session.data.parameters = req.param('parameters');

      // Invoke guardian gatekeeper
      keeper = gate({ req: req, res: res });
      keeper.invokeStep(1);
    } catch (e) {
      res.jsonp(500, {
        code: 'PLUGIN_MISSING',
        message: 'Invalid plugin specified, could not find plugin: ' + opts.auth.type.toLowerCase() + path.flow + path.version + path.leg
      });
    }
  });

  app.get('/step/:number', function (req, res) {
    keeper = gate({ req: req, res: res });
    keeper.invokeStep(parseInt(req.params.number, 10));
  });

  app.get('/connect/:provider/callback', function (req, res) {
    var plugin;
    var step;
    var data;
    var args;

    if (!req.session.data) {
      return res.json(500, {
        code: 'MISSING_SESSION_DETAILS',
        message: 'Session details are missing, perhaps the redirect url is on another server or the request timed out.'
      });
    }

    // Parse session data
    data = JSON.parse(JSON.stringify(req.session.data));

    // Include plugin
    plugin = gate.requirePlugin(data.auth);

    if (!plugin.step.callback) {
      return res.json(500, {
        code: 'MISSING_CALLBACK_STEP',
        message: 'Callback step is missing, unable to continue authentication process.'
      });
    }

    // Fetch information from previously set data.
    step = req.session.data.step;
    args = {};

    // Retrieve information returned from authentication step
    if (req.param('oauth_token'))
      args.token = req.param('oauth_token');

    if (req.param('oauth_verifier'))
      args.verifier = req.param('oauth_verifier');

    if (req.param('code'))
      args.code = req.param('code');

    if (req.param('state'))
      args.state = req.param('state');

    // Next?
    plugin.step.callback.next({ req: req, res: res }, args, function (response) {
      if (response) {
        return (!data.done.callback || data.done.callback == "oob")
          ? res.json(response)
          : res.redirect(data.done.callback + '?' + query.stringify(response));
      }

      if ((step + 1) > plugin.steps) {
        return res.json(500, {
          code: 'ALL_STEPS_COMPLETE',
          message: 'All steps have been completed, authentication should have happened, please try again.'
        });
      }

      res.redirect('/step/' + (step + 1));
    });
  });

  return app;
}

exports = module.exports = Guardian;
<|endoftext|>


<commit_before>
// require dependencies
const lock      = require ('async-lock');
const util      = require ('util');
const redis     = require ('redis');
const events    = require ('events');
const winston   = require ('winston');
const redisEE   = require ('redis-eventemitter');
const redisLock = require ('redis-lock');
const edenModel = require ('edenjs-model');

// require local dependencies
const log    = require ('lib/utilities/log');
const config = require ('config');

// require cached resources
const models  = cache ('models');
const daemons = cache ('daemons');

// build classes
let error = require ('pretty-error');

// set error
error = new error ();

// create redis cache
let cached = require ('cacheman-redis');

// create cache
cached = new cached (config.get ('redis'));

// build error handler
process.on ('unhandledRejection', (e) => {
  // log error
  console.log (error.render (e));
});
process.on ('uncaughtException', (e) => {
  // log error
  console.log (error.render (e));
});

/**
 * build eden class
 */
class eden {

  /**
   * construct eden class
   */
  constructor () {
    // bind private variables
    this._lock   = {};
    this._ctrl   = {};
    this._hooks  = {};
    this._daemon = {};

    // bind methods
    this.start      = this.start.bind (this);
    this.error      = this.error.bind (this);
    this.require    = this.require.bind (this);
    this.controller = this.controller.bind (this);

    // bind event methods
    this.on   = this.on.bind (this);
    this.off  = this.off.bind (this);
    this.emit = this.emit.bind (this);
    this.once = this.once.bind (this);

    // bind lock methods
    this.lock = this.lock.bind (this);

    // bind hook methods
    this.pre  = this.pre.bind (this);
    this.post = this.post.bind (this);
    this.hook = this.hook.bind (this);

    // bind cache methods
    this.get   = this.get.bind (this);
    this.set   = this.set.bind (this);
    this.del   = this.del.bind (this);
    this.cache = this.get.bind (this);

    // bind private methods
    this._port     = this._port.bind (this);
    this._locks    = this._locks.bind (this);
    this._events   = this._events.bind (this);
    this._logger   = this._logger.bind (this);
    this._daemons  = this._daemons.bind (this);
    this._database = this._database.bind (this);
  }

  ////////////////////////////////////////////////////////////////////////////
  //
  //  Main Methods
  //
  ////////////////////////////////////////////////////////////////////////////

  /**
   * start eden framework
   *
   * @param {Object} opts
   */
  async start (opts) {
    // set variables
    this.id       = opts.id;
    this.port     = opts.port || this._port ();
    this.host     = opts.host || config.get ('host') || '0.0.0.0';
    this.view     = false;
    this.email    = false;
    this.pubsub   = false;
    this.events   = false;
    this.logger   = opts.logger || this._logger ();
    this.express  = opts.express;
    this.compute  = !opts.express;
    this.database = false;

    // bind events/lock methods
    this._locks ();
    this._events ();

    // connect database
    await this._database ();

    // require router
    let router = require ('./eden/router');

    // bind eden classes
    this.router = opts.express ? new router () : false;

    // build daemons
    await this._daemons ();
  }

  /**
   * require file
   *
   * @param  {String}   file
   * @param  {Boolean}  doNew
   *
   * @return {Promise}
   */
  require (file) {
    // log which file to require
    this.logger.log ('debug', 'requiring ' + file, {
      'class' : 'eden'
    });

    // try catch
    try {
      // try require
      let req = require (file);

      // resolve
      return req;
    } catch (e) {
      // print error
      this.error (e);

      // exit process
      process.exit ();
    }
  }

  /**
   * run controller
   *
   * @param  {String} file
   *
   * @return {[type]}      [description]
   */
  async controller (file) {
    // try catch
    try {
      // check if controller registered
      if (!this._ctrl[file]) {
        // require controller
        let ctrl = await this.require (file);

        // register controller
        this._ctrl[file] = new ctrl ();
      }

      // resolve
      return this._ctrl[file];
    } catch (e) {
      // print error
      this.error (e);

      // exit process
      process.exit ();
    }
  }

  /**
   * pretty prints error
   *
   * @param  {Error} e
   */
  error (e) {
    // log error
    console.log (error.render (e));

    // emit error
    this.emit ('eden:error', e);
  }

  //////////////////////////////////////////////////////////////////////////////
  //
  //  Event Methods
  //
  //////////////////////////////////////////////////////////////////////////////

  /**
   * on function
   *
   * @param  {String}   str
   * @param  {Function} fn
   * @param  {Boolean}  all
   */
  on (str, fn, all) {
    // on str/fn
    if (all) {
      // pubsub on
      this.pubsub.on (str, (channel, data) => {
        // run function
        fn (data);
      });
    } else {
      // add event listener
      this.events.on (str, fn);
    }
  }

  /**
   * on function
   *
   * @param  {String}   str
   * @param  {Function} fn
   * @param  {Boolean}  all
   */
  once (str, fn, all) {
    // on str/fn
    if (all) {
      // pubsub on
      this.pubsub.once (str, (channel, data) => {
        // run function
        fn (data);
      });
    } else {
      // add event listener
      this.events.once (str, fn);
    }
  }

  /**
   * on function
   *
   * @param  {String}   str
   * @param  {Function} fn
   * @param  {Boolean}  all
   *
   * @return {*}
   */
  off (str, fn, all) {
    // remove listener
    return this[all ? 'pubsub' : 'events'][(fn ? 'removeListener' : 'removeAllListeners')] (str, fn);
  }

  /**
   * on function
   *
   * @param  {String}  str
   * @param  {Array}   args
   *
   * @return {*}
   */
  emit (str, ...args) {
    // let all
    let all = typeof args[args.length - 1] === 'boolean' ? args[args.length - 1] : false;

    // emit function
    return this[all ? 'pubsub' : 'events'].emit.apply (this[all ? 'pubsub' : 'events'], [str, ...args]);
  }

  /**
   * emit to main thread
   *
   * @param {String} str
   * @param {Object} obj
   *
   * @return {*}
   */
  main (str, obj) {
    // emit function
    return this.pubsub.emit ('main', {
      'type' : str,
      'data' : obj
    });
  }

  //////////////////////////////////////////////////////////////////////////////
  //
  //  Lock Methods
  //
  //////////////////////////////////////////////////////////////////////////////

  /**
   * returns lock
   * @param  {String}  key
   * @param  {Boolean} all
   *
   * @return {Promise}
   */
  async lock (key, all) {
    // set dones
    let callbacks = [];

    // add to callbacks
    callbacks.push (await new Promise ((res) => {
      // resolve acquire
      this._lock.local.acquire (key, res);
    }));
    if (all) callbacks.push (await this._lock.redis (key));

    // return complete function
    return () => {
      // loop callbacks
      callbacks.forEach ((cb) => {
        // run callback
        cb ();
      });
    };
  }

  //////////////////////////////////////////////////////////////////////////////
  //
  //  Cache Methods
  //
  //////////////////////////////////////////////////////////////////////////////

  /**
   * sets cache
   *
   * @param  {String}   key
   * @param  {Function} notCached
   *
   * @return {*}
   */
  get (key, notCached) {
    // return Promise
    return new Promise ((resolve, reject) => {
      // cache get
      cached.get (key, async (err, value) => {
        // check err
        if (err) return reject (err);

        // check value
        if (value === null && notCached) {
          // set value
          return resolve (await this.set (key, await notCached ()));
        }

        // check value
        if (value && typeof value === 'object' && value.id && value.model) {
          // load type
          value = model (value.model).findById (value.id);
        }

        // return value
        resolve (value);
      });
    });
  }

  /**
   * sets cache
   *
   * @param  {String} key
   * @param  {*} value
   *
   * @return {*}
   */
  set (key, value) {
    // return Promise
    return new Promise ((resolve, reject) => {
      // check value
      if (value instanceof require ('model') && value.get && value.get ('_id')) {
        // set value
        value = {
          'id'    : value.get ('_id').toString (),
          'model' : value.constructor.name
        };
      }

      // set cache value
      cached.set (key, value, (err, value) => {
        // check err
        if (err) return reject (err);

        // resolve
        resolve (value);
      });
    });
  }

  /**
   * delete cache by key
   *
   * @param {String} key
   *
   * @returns {Promise}
   */
  del (key) {
    // return Promise
    return new Promise ((resolve, reject) => {
      // delete from cache
      cached.del (key, (err) => {
        // check err
        if (err) return reject (err);

        // resolve
        resolve ();
      });
    });
  }

  //////////////////////////////////////////////////////////////////////////////
  //
  //  Hook Methods
  //
  //////////////////////////////////////////////////////////////////////////////

  /**
   * add post hook to act as pre
   *
   * @param {String} hook
   * @param {Function} fn
   */
  pre (hook, fn) {
    // check hook
    this.__hook (hook);

    // add to post
    this._hooks[hook].pre.push (fn);
  }

  /**
   * add post hook to act as pre
   *
   * @param {String} hook
   * @param {Function} fn
   */
  post (hook, fn) {
    // check hook
    this.__hook (hook);

    // add to post
    this._hooks[hook].post.push (fn);
  }

  /**
   * adds kareem hook
   *
   * @param {String} hook
   */
  async hook (hook, ...args) {
    // set fn
    let fn = false;

    // get function
    if (args.length > 1 && args[args.length - 1] instanceof Function && typeof args[args.length - 1] === 'function' && args[args.length - 1].call) fn = args.splice (-1)[0];

    // check hook
    this.__hook (hook);

    // exec pres
    for (var a = 0; a < this._hooks[hook].pre.length; a++) {
      // exec pre
      await this._hooks[hook].pre[a] (...args);
    }

    // exec actual function
    if (fn) await fn (...args);

    // exec post
    for (var b = 0; b < this._hooks[hook].post.length; b++) {
      // exec pre
      await this._hooks[hook].post[b] (...args);
    }
  }

  /**
   * checks hook
   *
   * @param {String} hook
   *
   * @private
   */
  __hook (hook) {
    // check hook exists
    if (!this._hooks[hook]) this._hooks[hook] = {
      'pre'  : [],
      'post' : []
    };
  }

  //////////////////////////////////////////////////////////////////////////////
  //
  //  Private Methods
  //
  //////////////////////////////////////////////////////////////////////////////

  /**
   * registers port
   *
   * @private
   *
   * @returns {String}
   */
  _port () {
    // check if main should build
    if (!this.express) return;

    // return true port if clustered
    this.port = config.get ('port');

    // log port
    this.logger.log ('info', 'using express on port ' + this.port, {
      'class' : 'eden'
    });

    // resolve
    return this.port;
  }

  /**
   * registers logger
   *
   * @private
   * @return {winston} logger
   */
  _logger () {
    // set logger
    return new winston.Logger ({
      'level'      : config.get ('logLevel')  || 'info',
      'transports' : [
        new (winston.transports.Console) ({
          'colorize'  : true,
          'formatter' : log,
          'timestamp' : true
        })
      ]
    });
  }

  /**
   * registers eden event emitter
   *
   * @private
   */
  _locks () {
    // get connection
    let conn = config.get ('redis');

    // set prefix
    conn.prefix = config.get ('domain') + '.lock';

    // create events redis instance
    let client = redis.createClient (conn);

    // create new events class
    this._lock = {
      'redis' : util.promisify (redisLock (client)),
      'local' : new lock ({
        'maxPending' : config.get ('lock.maxPending')
      })
    };
  }

  /**
   * registers eden event emitter
   *
   * @private
   */
  _events () {
    // get connection
    let conn = config.get ('redis');

    // set prefix
    conn.prefix = config.get ('domain') + '.event';

    // create events redis instance
    this.pubsub = redisEE (conn);

    // create new events class
    this.events = new events ();

    // on function
    if (this.main) {
      // only on this thread
      this.pubsub.on ('main', (channel, data) => {
        // emit to this thread
        this.emit (data.type, data.data);
      });
    }
  }

  /**
   * registers mongodb database
   *
   * @private
   */
  async _database () {
    // connects to mongo database
    let lock = await this.lock ('database.register', true);
    let plug = new edenModel.plugs[config.get ('database.plug')] (config.get ('database.config'));

    // log registering
    this.logger.log ('info', 'registering database', {
      'class' : 'eden'
    });

    // construct database with plug
    this.database = new edenModel.Db (plug);

    // register models
    for (var key in models) {
      // get model
      let Model = model (key);

      // register
      await this.database.register (Model);

      // await initialize
      await Model.initialize ();
    }

    // log registered
    this.logger.log ('info', 'registered database', {
      'class' : 'eden'
    });

    // unlock
    lock ();
  }

  /**
   * builds daemons
   *
   * @private
   */
  async _daemons () {
    // loop daemons
    for (var file in daemons) {
      // check if should require
      if (!daemons[file].compute && this.compute) continue;
      if (!daemons[file].express && this.express) continue;

      // require daemon
      await this.controller (file);

      // run daemon
      try {
        // log daemon
        this.logger.log ('info', 'running daemon ' + daemons[file].name, {
          'class' : 'eden'
        });
      } catch (e) {
        // print error
        this.error (e);

        // log daemon
        this.logger.log ('error', 'daemon ' + daemons[file].name + ' failed!', {
          'class' : 'eden'
        });
      }
    }
  }
}

/**
 * export eden class
 *
 * @type {eden}
 */
exports = module.exports = new eden ();
<commit_msg>promisify cacheman logic in eden core<commit_after>
// require dependencies
const lock      = require ('async-lock');
const util      = require ('util');
const redis     = require ('redis');
const events    = require ('events');
const winston   = require ('winston');
const redisEE   = require ('redis-eventemitter');
const cacheman  = require ('cacheman-redis');
const redisLock = require ('redis-lock');
const edenModel = require ('edenjs-model');

// require local dependencies
const log    = require ('lib/utilities/log');
const config = require ('config');

// require cached resources
const models  = cache ('models');
const daemons = cache ('daemons');

// build classes
let error = require ('pretty-error');

// set error
error = new error ();

// build error handler
process.on ('unhandledRejection', (e) => {
  // log error
  console.log (error.render (e));
});
process.on ('uncaughtException', (e) => {
  // log error
  console.log (error.render (e));
});

/**
 * build eden class
 */
class eden {

  /**
   * construct eden class
   */
  constructor () {
    // bind private variables
    this._lock   = {};
    this._ctrl   = {};
    this._hooks  = {};
    this._cache  = {};
    this._daemon = {};

    // bind methods
    this.start      = this.start.bind (this);
    this.error      = this.error.bind (this);
    this.require    = this.require.bind (this);
    this.controller = this.controller.bind (this);

    // bind event methods
    this.on   = this.on.bind (this);
    this.off  = this.off.bind (this);
    this.emit = this.emit.bind (this);
    this.once = this.once.bind (this);

    // bind lock methods
    this.lock = this.lock.bind (this);

    // bind hook methods
    this.pre  = this.pre.bind (this);
    this.post = this.post.bind (this);
    this.hook = this.hook.bind (this);

    // bind cache methods
    this.get   = this.get.bind (this);
    this.set   = this.set.bind (this);
    this.del   = this.del.bind (this);
    this.cache = this.get.bind (this);
    this.clear = this.clear.bind (this);

    // bind private methods
    this._port     = this._port.bind (this);
    this._locks    = this._locks.bind (this);
    this._caches   = this._caches.bind (this);
    this._events   = this._events.bind (this);
    this._logger   = this._logger.bind (this);
    this._daemons  = this._daemons.bind (this);
    this._database = this._database.bind (this);
  }

  ////////////////////////////////////////////////////////////////////////////
  //
  //  Main Methods
  //
  ////////////////////////////////////////////////////////////////////////////

  /**
   * start eden framework
   *
   * @param {Object} opts
   */
  async start (opts) {
    // set variables
    this.id       = opts.id;
    this.port     = opts.port || this._port ();
    this.host     = opts.host || config.get ('host') || '0.0.0.0';
    this.view     = false;
    this.email    = false;
    this.pubsub   = false;
    this.events   = false;
    this.logger   = opts.logger || this._logger ();
    this.express  = opts.express;
    this.compute  = !opts.express;
    this.database = false;

    // bind events/lock methods
    this._locks ();
    this._caches ();
    this._events ();

    // connect database
    await this._database ();

    // require router
    let router = require ('./eden/router');

    // bind eden classes
    this.router = opts.express ? new router () : false;

    // build daemons
    await this._daemons ();
  }

  /**
   * require file
   *
   * @param  {String}   file
   * @param  {Boolean}  doNew
   *
   * @return {Promise}
   */
  require (file) {
    // log which file to require
    this.logger.log ('debug', 'requiring ' + file, {
      'class' : 'eden'
    });

    // try catch
    try {
      // try require
      let req = require (file);

      // resolve
      return req;
    } catch (e) {
      // print error
      this.error (e);

      // exit process
      process.exit ();
    }
  }

  /**
   * run controller
   *
   * @param  {String} file
   *
   * @return {[type]}      [description]
   */
  async controller (file) {
    // try catch
    try {
      // check if controller registered
      if (!this._ctrl[file]) {
        // require controller
        let ctrl = await this.require (file);

        // register controller
        this._ctrl[file] = new ctrl ();
      }

      // resolve
      return this._ctrl[file];
    } catch (e) {
      // print error
      this.error (e);

      // exit process
      process.exit ();
    }
  }

  /**
   * pretty prints error
   *
   * @param  {Error} e
   */
  error (e) {
    // log error
    console.log (error.render (e));

    // emit error
    this.emit ('eden.error', e);
  }

  //////////////////////////////////////////////////////////////////////////////
  //
  //  Event Methods
  //
  //////////////////////////////////////////////////////////////////////////////

  /**
   * on function
   *
   * @param  {String}   str
   * @param  {Function} fn
   * @param  {Boolean}  all
   */
  on (str, fn, all) {
    // on str/fn
    if (all) {
      // pubsub on
      this.pubsub.on (str, (channel, data) => {
        // run function
        fn (data);
      });
    } else {
      // add event listener
      this.events.on (str, fn);
    }
  }

  /**
   * on function
   *
   * @param  {String}   str
   * @param  {Function} fn
   * @param  {Boolean}  all
   */
  once (str, fn, all) {
    // on str/fn
    if (all) {
      // pubsub on
      this.pubsub.once (str, (channel, data) => {
        // run function
        fn (data);
      });
    } else {
      // add event listener
      this.events.once (str, fn);
    }
  }

  /**
   * on function
   *
   * @param  {String}   str
   * @param  {Function} fn
   * @param  {Boolean}  all
   *
   * @return {*}
   */
  off (str, fn, all) {
    // remove listener
    return this[all ? 'pubsub' : 'events'][(fn ? 'removeListener' : 'removeAllListeners')] (str, fn);
  }

  /**
   * on function
   *
   * @param  {String}  str
   * @param  {Array}   args
   *
   * @return {*}
   */
  emit (str, ...args) {
    // let all
    let all = typeof args[args.length - 1] === 'boolean' ? args[args.length - 1] : false;

    // emit function
    return this[all ? 'pubsub' : 'events'].emit.apply (this[all ? 'pubsub' : 'events'], [str, ...args]);
  }

  /**
   * emit to main thread
   *
   * @param {String} str
   * @param {Object} obj
   *
   * @return {*}
   */
  main (str, obj) {
    // emit function
    return this.pubsub.emit ('main', {
      'type' : str,
      'data' : obj
    });
  }

  //////////////////////////////////////////////////////////////////////////////
  //
  //  Lock Methods
  //
  //////////////////////////////////////////////////////////////////////////////

  /**
   * returns lock
   * @param  {String}  key
   * @param  {Boolean} all
   *
   * @return {Promise}
   */
  async lock (key, all) {
    // set dones
    let callbacks = [];

    // add to callbacks
    callbacks.push (await new Promise ((res) => {
      // resolve acquire
      this._lock.local.acquire (key, res);
    }));
    if (all) callbacks.push (await this._lock.redis (key));

    // return complete function
    return () => {
      // loop callbacks
      callbacks.forEach ((cb) => {
        // run callback
        cb ();
      });
    };
  }

  //////////////////////////////////////////////////////////////////////////////
  //
  //  Cache Methods
  //
  //////////////////////////////////////////////////////////////////////////////

  /**
   * sets cache
   *
   * @param  {String}   key
   * @param  {Function} notCached
   *
   * @return {*}
   */
  async get (key, notCached) {
    // promisify get
    let get = util.promisify (this._cache.get.bind (this._cache));

    // get value
    let value = await get (key);

    // check key
    if (value === null && notCached) {
      // set cached
      value = await notCached ();

      // set
      await this.set (key, value);
    }

    // check value
    if (value && typeof value === 'object' && value.id && value.model) {
      // load type
      value = model (value.model).findById (value.id);
    }

    // return cached
    return value;
  }

  /**
   * sets cache
   *
   * @param  {String} key
   * @param  {*} value
   *
   * @return {*}
   */
  async set (key, value) {
    // promisify get
    let set = util.promisify (this._cache.set.bind (this._cache));

    // create original value
    let original = value;

    // check value
    if (value instanceof require ('model') && value.get ('_id')) {
      // set value
      value = {
        'id'    : value.get ('_id').toString (),
        'model' : value.constructor.name
      };
    }

    // await get
    await set (key, value);

    // return value
    return original;
  }

  /**
   * delete cache by key
   *
   * @param {String} key
   *
   * @returns {Promise}
   */
  del (key) {
    // promisify get
    let del = util.promisify (this._cache.del.bind (this._cache));

    // await get
    return del (key);
  }

  /**
   * delete cache
   *
   * @returns {Promise}
   */
  clear () {
    // promisify get
    let clear = util.promisify (this._cache.clear.bind (this._cache));

    // await get
    return clear ();
  }

  //////////////////////////////////////////////////////////////////////////////
  //
  //  Hook Methods
  //
  //////////////////////////////////////////////////////////////////////////////

  /**
   * add post hook to act as pre
   *
   * @param {String} hook
   * @param {Function} fn
   */
  pre (hook, fn) {
    // check hook
    this.__hook (hook);

    // add to post
    this._hooks[hook].pre.push (fn);
  }

  /**
   * add post hook to act as pre
   *
   * @param {String} hook
   * @param {Function} fn
   */
  post (hook, fn) {
    // check hook
    this.__hook (hook);

    // add to post
    this._hooks[hook].post.push (fn);
  }

  /**
   * adds kareem hook
   *
   * @param {String} hook
   */
  async hook (hook, ...args) {
    // set fn
    let fn = false;

    // get function
    if (args.length > 1 && args[args.length - 1] instanceof Function && typeof args[args.length - 1] === 'function' && args[args.length - 1].call) fn = args.splice (-1)[0];

    // check hook
    this.__hook (hook);

    // exec pres
    for (var a = 0; a < this._hooks[hook].pre.length; a++) {
      // exec pre
      await this._hooks[hook].pre[a] (...args);
    }

    // exec actual function
    if (fn) await fn (...args);

    // exec post
    for (var b = 0; b < this._hooks[hook].post.length; b++) {
      // exec pre
      await this._hooks[hook].post[b] (...args);
    }
  }

  /**
   * checks hook
   *
   * @param {String} hook
   *
   * @private
   */
  __hook (hook) {
    // check hook exists
    if (!this._hooks[hook]) this._hooks[hook] = {
      'pre'  : [],
      'post' : []
    };
  }

  //////////////////////////////////////////////////////////////////////////////
  //
  //  Private Methods
  //
  //////////////////////////////////////////////////////////////////////////////

  /**
   * registers port
   *
   * @private
   *
   * @returns {String}
   */
  _port () {
    // check if main should build
    if (!this.express) return;

    // return true port if clustered
    this.port = config.get ('port');

    // log port
    this.logger.log ('info', 'using express on port ' + this.port, {
      'class' : 'eden'
    });

    // resolve
    return this.port;
  }

  /**
   * registers logger
   *
   * @private
   * @return {winston} logger
   */
  _logger () {
    // set logger
    return new winston.Logger ({
      'level'      : config.get ('logLevel')  || 'info',
      'transports' : [
        new (winston.transports.Console) ({
          'colorize'  : true,
          'formatter' : log,
          'timestamp' : true
        })
      ]
    });
  }

  /**
   * registers eden event emitter
   *
   * @private
   */
  _locks () {
    // get connection
    let conn = config.get ('redis');

    // set prefix
    conn.prefix = config.get ('domain') + '.lock';

    // create events redis instance
    let client = redis.createClient (conn);

    // create new events class
    this._lock = {
      'redis' : util.promisify (redisLock (client)),
      'local' : new lock ({
        'maxPending' : config.get ('lock.maxPending')
      })
    };
  }

  /**
   * create cache
   */
  _caches () {
    // create cache
    this._cache = new cacheman (config.get ('redis'));
  }

  /**
   * registers eden event emitter
   *
   * @private
   */
  _events () {
    // get connection
    let conn = config.get ('redis');

    // set prefix
    conn.prefix = config.get ('domain') + '.event';

    // create events redis instance
    this.pubsub = redisEE (conn);

    // create new events class
    this.events = new events ();

    // on function
    if (this.main) {
      // only on this thread
      this.pubsub.on ('main', (channel, data) => {
        // emit to this thread
        this.emit (data.type, data.data);
      });
    }
  }

  /**
   * registers mongodb database
   *
   * @private
   */
  async _database () {
    // connects to mongo database
    let lock = await this.lock ('database.register', true);
    let plug = new edenModel.plugs[config.get ('database.plug')] (config.get ('database.config'));

    // log registering
    this.logger.log ('info', 'registering database', {
      'class' : 'eden'
    });

    // construct database with plug
    this.database = new edenModel.Db (plug);

    // register models
    for (var key in models) {
      // get model
      let Model = model (key);

      // register
      await this.database.register (Model);

      // await initialize
      await Model.initialize ();
    }

    // log registered
    this.logger.log ('info', 'registered database', {
      'class' : 'eden'
    });

    // unlock
    lock ();
  }

  /**
   * builds daemons
   *
   * @private
   */
  async _daemons () {
    // loop daemons
    for (var file in daemons) {
      // check if should require
      if (!daemons[file].compute && this.compute) continue;
      if (!daemons[file].express && this.express) continue;

      // require daemon
      await this.controller (file);

      // run daemon
      try {
        // log daemon
        this.logger.log ('info', 'running daemon ' + daemons[file].name, {
          'class' : 'eden'
        });
      } catch (e) {
        // print error
        this.error (e);

        // log daemon
        this.logger.log ('error', 'daemon ' + daemons[file].name + ' failed!', {
          'class' : 'eden'
        });
      }
    }
  }
}

/**
 * export eden class
 *
 * @type {eden}
 */
exports = module.exports = new eden ();
<|endoftext|>


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

	var app = angular.module('HoldclickDirective', []);

	app.directive('holdClick', function(){
		return {
			restrict: 'A',
			controller: ['$element', function($element){
				var over = false;
				var firstPeriod = null;
				var secondPeriod = null;

				var startHandler = function(e){
					over = true;

					$element.triggerHandler('click');

					firstPeriod = setTimeout(function(){
						if(over){
							secondPeriod = setInterval(function(){
								$element.triggerHandler('click');
							}, 50);
						}
					}, 700);

					e.stopPropagation();
					e.preventDefault();
				};
				var stopHandler = function(e){
					if(firstPeriod !== null){
						clearTimeout(firstPeriod);
						firstPeriod = null;
					}
					if(secondPeriod !== null){
						clearInterval(secondPeriod);
						secondPeriod = null;
					}

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

				var moveHandler = function(e){
					over = e.target === $element[0];
				};
				var clickHandler = function(e){
					e.stopImmediatePropagation();
					e.preventDefault();
				};

				$element[0].addEventListener('mousedown', startHandler);
				$element[0].addEventListener('touchstart', startHandler);

				$element[0].addEventListener('mouseup', stopHandler);
				$element[0].addEventListener('touchend', stopHandler);

				$element[0].addEventListener('click', clickHandler);

				window.addEventListener('mousemove', moveHandler);
				window.addEventListener('touchmove', moveHandler);
			}]
		}
	})
})();<commit_msg>fixed mouseover/mouseout simulation<commit_after>(function(){
	'use strict';

	var app = angular.module('HoldclickDirective', []);

	app.directive('holdClick', function(){
		return {
			restrict: 'A',
			controller: ['$element', function($element){
				var over = false;
				var firstPeriod = null;
				var secondPeriod = null;

				var startHandler = function(e){
					over = true;

					$element.triggerHandler('click');

					firstPeriod = setTimeout(function(){
						secondPeriod = setInterval(function(){
							if(over){
								$element.triggerHandler('click');
							}
						}, 50);
					}, 700);

					e.stopPropagation();
					e.preventDefault();
				};
				var stopHandler = function(e){
					if(firstPeriod !== null){
						clearTimeout(firstPeriod);
						firstPeriod = null;
					}
					if(secondPeriod !== null){
						clearInterval(secondPeriod);
						secondPeriod = null;
					}
				};

				var moveHandler = function(e){
					over = e.target === $element[0];
				};
				var clickHandler = function(e){
					e.stopImmediatePropagation();
					e.preventDefault();
				};

				$element[0].addEventListener('mousedown', startHandler);
				$element[0].addEventListener('touchstart', startHandler);

				window.addEventListener('mouseup', stopHandler);
				window.addEventListener('touchend', stopHandler);

				$element[0].addEventListener('click', clickHandler);

				window.addEventListener('mousemove', moveHandler);
				window.addEventListener('touchmove', moveHandler);
			}]
		}
	})
})();<|endoftext|>


<commit_before>
// console.log("hhh")

pbc.objectFunctionD.get('value')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) {
    if (args.length !== 1 && args.length !== 0) {
        throw new Error("Incorrect number of arguments");
    }
    if(args.length == 1){
    pbc.pinType = "pins_digital";
    var pinblock = py2block.convert(func.value);
    var argblock = py2block.convert(args[0]);
    pbc.pinType = null;
    return [block("inout_digital_write", func.lineno, {}, {
        "PIN": pinblock,
        "STAT": argblock
    }, {
        "inline": "true"
    })];}
    else if(args.length == 0){
      pbc.pinType = "pins_digital";
      var pinblock = py2block.convert(func.value);
      pbc.pinType = null;
      return block("inout_digital_read", func.lineno, {}, {
          "PIN": pinblock
      }, {
          "inline": "true"
      });
    }
}

pbc.assignD.get('Pin')['check_assign'] = function(py2block, node, targets, value) {
    var funcName = py2block.identifier(value.func.id);
    if(value._astname === "Call"
        && funcName === "Pin" && (value.args.length === 2 || value.args.length === 3) )
        return true;
    return false;
}

pbc.assignD.get('Pin')['create_block'] = function(py2block, node, targets, value){

    pbc.pinType = "pins_digital_pin";
    var pinblock = py2block.convert(value.args[0]);
    pbc.pinType = null;
    if(value.args.length === 2){
    var digitalblock = py2block.Name_str(value.args[1].value) +"."+ py2block.identifier(value.args[1].attr);
    }
    else if(value.args.length === 3){
    var digitalblock = py2block.Name_str(value.args[1].value) +"."+ py2block.identifier(value.args[1].attr)+", "+py2block.Name_str(value.args[2].value) +"."+ py2block.identifier(value.args[2].attr);
    }
    pinobj = "pin"+value.args[0].n.v;
    return block("inout_digital_init", node.lineno, {"PIN_OBJ":pinobj,"MODE":digitalblock}, {
        "PIN":pinblock,

    });
}

pbc.assignD.get('DAC')['check_assign'] = function(py2block, node, targets, value) {
    var funcName = py2block.identifier(value.func.id);
    if(value._astname === "Call"
        && funcName === "DAC" && value.args.length === 1)
        return true;
    return false;
}

pbc.assignD.get('DAC')['create_block'] = function(py2block, node, targets, value){
    var astname = value.args[0]._astname;
    if(astname === "Call" && value.args[0].func._astname == "Name" && value.args[0].func.id.v === "Pin"){ //
        pbc.pinType = "pins_dac_pin";
        pinblock =  py2block.convert(value.args[0].args[0]);
        pbc.pinType = null;
    }else{
        pbc.pinType = "pins_dac_pin";
        pinblock =  py2block.convert(args[0]);
        pbc.pinType = null;
    }
    pinobj = "dac"+value.args[0].args[0].n.v;
    return block("inout_analog_write_init", node.lineno, {"PIN_OBJ":pinobj}, {
        "PIN":pinblock,

    });
}

pbc.objectFunctionD.get('write')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) {
    if (args.length !== 1) {
        throw new Error("Incorrect number of arguments");
    }
    pbc.pinType = "pins_dac";
    var pinblock = py2block.convert(func.value);
    pbc.pinType = null;
    var argblock = py2block.convert(args[0]);

    return [block("inout_analog_write", func.lineno, {}, {
        "PIN": pinblock,
        "NUM": argblock
    }, {
        "inline": "true"
    })];
}

pbc.assignD.get('PWM')['check_assign'] = function(py2block, node, targets, value) {
    var funcName = py2block.identifier(value.func.id);
    if(value._astname === "Call"
        && funcName === "PWM" && value.args.length === 1)
        return true;
    return false;
}

pbc.assignD.get('PWM')['create_block'] = function(py2block, node, targets, value){
    var astname = value.args[0]._astname;
    if(astname === "Call" && value.args[0].func._astname == "Name" && value.args[0].func.id.v === "Pin"){ //
        pbc.pinType = "pins_pwm_pin";
        pinblock =  py2block.convert(value.args[0].args[0]);
        pbc.pinType = null;
    }else{
        pbc.pinType = "pins_pwm_pin";
        pinblock =  py2block.convert(args[0]);
        pbc.pinType = null;
    }
    pinobj = "pwm"+value.args[0].args[0].n.v;
    return block("inout_pwm_analog_write_init", node.lineno, {"PIN_OBJ":pinobj}, {
        "PIN":pinblock,

    });
}

pbc.objectFunctionD.get('duty')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) {
    if (args.length !== 1) {
        throw new Error("Incorrect number of arguments");
    }
    pbc.pinType = "pins_pwm";
    var pinblock = py2block.convert(func.value);
    pbc.pinType = null;
    var argblock = py2block.convert(args[0]);

    return [block("inout_pwm_analog_write", func.lineno, {}, {
        "PIN": pinblock,
        "NUM": argblock
    }, {
        "inline": "true"
    })];
}

pbc.objectFunctionD.get('freq')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) {
    if (args.length !== 1) {
        throw new Error("Incorrect number of arguments");
    }
    pbc.pinType = "pins_pwm";
    var pinblock = py2block.convert(func.value);
    pbc.pinType = null;
    var argblock = py2block.convert(args[0]);

    return [block("inout_analog_write_set_freq", func.lineno, {}, {
        "PIN": pinblock,
        "NUM": argblock
    }, {
        "inline": "true"
    })];
}

pbc.assignD.get('ADC')['check_assign'] = function(py2block, node, targets, value) {
    var funcName = py2block.identifier(value.func.id);
    if(value._astname === "Call"
        && funcName === "ADC" && value.args.length === 1)
        return true;
    return false;
}

pbc.assignD.get('ADC')['create_block'] = function(py2block, node, targets, value){
    var astname = value.args[0]._astname;
    if(astname === "Call" && value.args[0].func._astname == "Name" && value.args[0].func.id.v === "Pin"){ //
        pbc.pinType = "pins_analog_pin";
        pinblock =  py2block.convert(value.args[0].args[0]);
        pbc.pinType = null;
    }else{
        pbc.pinType = "pins_analog_pin";
        pinblock =  py2block.convert(args[0]);
        pbc.pinType = null;
    }
    pinobj = "adc"+value.args[0].args[0].n.v;
    return block("inout_analog_read_init", node.lineno, {"PIN_OBJ":pinobj}, {
        "PIN":pinblock,

    });
}

pbc.objectFunctionD.get('read')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) {
    if (args.length !== 0) {
        throw new Error("Incorrect number of arguments");
    }
    value = func.value.id.v
    value = value.slice(0,2)
    if( value=="ad"){
    pbc.pinType = "pins_analog";
    var pinblock = py2block.convert(func.value);
    pbc.pinType = null;

    return block("inout_analog_read", func.lineno, {}, {
        "PIN": pinblock,
    }, {
        "inline": "true"
    });}
    else if(value =="tc"){
    pbc.pinType = "pins_touch";
    var pinblock = py2block.convert(func.value);
    pbc.pinType = null;

    return block("inout_pin_pressed", func.lineno, {}, {
        "pin": pinblock,
    }, {
        "inline": "true"
    });
    }
}

pbc.assignD.get('TOUCHPAD')['check_assign'] = function(py2block, node, targets, value) {
    var funcName = py2block.identifier(value.func.id);
    if(value._astname === "Call"
        && funcName === "TouchPad" && value.args.length === 1)
        return true;
    return false;
}

pbc.assignD.get('TOUCHPAD')['create_block'] = function(py2block, node, targets, value){
    var astname = value.args[0]._astname;
    if(astname === "Call" && value.args[0].func._astname == "Name" && value.args[0].func.id.v === "Pin"){ //
        pbc.pinType = "pins_touch_pin";
        pinblock =  py2block.convert(value.args[0].args[0]);
        pbc.pinType = null;
    }else{
        pbc.pinType = "pins_touch_pin";
        pinblock =  py2block.convert(args[0]);
        pbc.pinType = null;
    }
    pinobj = "tc"+value.args[0].args[0].n.v;
    return block("inout_pin_pressed_init", node.lineno, {"PIN_OBJ":pinobj}, {
        "PIN":pinblock,

    });
}<commit_msg>inout除中断 文本转图形<commit_after>

pbc.objectFunctionD.get('value')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) {
    if (args.length !== 1 && args.length !== 0) {
        throw new Error("Incorrect number of arguments");
    }
    if(args.length == 1){
    pbc.pinType = "pins_digital";
    var pinblock = py2block.convert(func.value);
    var argblock = py2block.convert(args[0]);
    pbc.pinType = null;
    return [block("inout_digital_write", func.lineno, {}, {
        "PIN": pinblock,
        "STAT": argblock
    }, {
        "inline": "true"
    })];}
    else if(args.length == 0){
      pbc.pinType = "pins_digital";
      var pinblock = py2block.convert(func.value);
      pbc.pinType = null;
      return block("inout_digital_read", func.lineno, {}, {
          "PIN": pinblock
      }, {
          "inline": "true"
      });
    }
}

//bug
pbc.assignD.get('Pin')['check_assign'] = function(py2block, node, targets, value) {
    var moduleName = py2block.Name_str(value.func.value);
    var funcName = py2block.identifier(value.func.attr);
    if(value._astname === "Call"
        && funcName === "Pin" && (value.args.length === 2 || value.args.length === 3) )
        return true;
    return false;
}

pbc.assignD.get('Pin')['create_block'] = function(py2block, node, targets, value){

    pbc.pinType = "pins_digital_pin";
    var pinblock = py2block.convert(value.args[0]);
    pbc.pinType = null;
    if(value.args.length === 2){
    var digitalblock = "machine."+py2block.identifier(value.args[1].value.attr) +"."+ py2block.identifier(value.args[1].attr);
    }
    else if(value.args.length === 3){
    var digitalblock = "machine."+py2block.identifier(value.args[1].value.attr) +"."+ py2block.identifier(value.args[1].attr)+", "+"machine."+py2block.identifier(value.args[2].value.attr) +"."+ py2block.identifier(value.args[2].attr);
    }
    pinobj = "pin"+value.args[0].n.v;
    return block("inout_digital_init", node.lineno, {"PIN_OBJ":pinobj,"MODE":digitalblock}, {
        "PIN":pinblock,

    });
}
//ok
pbc.assignD.get('DAC')['check_assign'] = function(py2block, node, targets, value) {
    var moduleName = py2block.Name_str(value.func.value);
    var funcName = py2block.identifier(value.func.attr);
    if(value._astname === "Call"
        && funcName === "DAC" && moduleName === "machine"&& value.args.length === 1)
        return true;
    return false;
}

pbc.assignD.get('DAC')['create_block'] = function(py2block, node, targets, value){
    var astname = value.args[0]._astname;
    var funcName = py2block.identifier(value.args[0].func.attr);
    if(astname === "Call" && funcName === "Pin"){ //
        pbc.pinType = "pins_dac_pin";
        pinblock =  py2block.convert(value.args[0].args[0]);
        pbc.pinType = null;
    }else{
        pbc.pinType = "pins_dac_pin";
        pinblock =  py2block.convert(args[0]);
        pbc.pinType = null;
    }
    pinobj = "dac"+value.args[0].args[0].n.v;
    return block("inout_analog_write_init", node.lineno, {"PIN_OBJ":pinobj}, {
        "PIN":pinblock,

    });
}

pbc.objectFunctionD.get('write')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) {
    if (args.length !== 1) {
        throw new Error("Incorrect number of arguments");
    }
    pbc.pinType = "pins_dac";
    var pinblock = py2block.convert(func.value);
    pbc.pinType = null;
    var argblock = py2block.convert(args[0]);

    return [block("inout_analog_write", func.lineno, {}, {
        "PIN": pinblock,
        "NUM": argblock
    }, {
        "inline": "true"
    })];
}

//ok
pbc.assignD.get('PWM')['check_assign'] = function(py2block, node, targets, value) {
    var moduleName = py2block.Name_str(value.func.value);
    var funcName = py2block.identifier(value.func.attr);
    if(value._astname === "Call"
        && funcName === "PWM" && moduleName === "machine" && value.args.length === 1)
        return true;
    return false;
}

pbc.assignD.get('PWM')['create_block'] = function(py2block, node, targets, value){
    var astname = value.args[0]._astname;
    var funcName = py2block.identifier(value.args[0].func.attr);
    if(astname === "Call" && funcName === "Pin"){ //
        pbc.pinType = "pins_pwm_pin";
        pinblock =  py2block.convert(value.args[0].args[0]);
        pbc.pinType = null;
    }else{
        pbc.pinType = "pins_pwm_pin";
        pinblock =  py2block.convert(args[0]);
        pbc.pinType = null;
    }
    pinobj = "pwm"+value.args[0].args[0].n.v;
    return block("inout_pwm_analog_write_init", node.lineno, {"PIN_OBJ":pinobj}, {
        "PIN":pinblock,

    });
}

pbc.objectFunctionD.get('duty')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) {
    if (args.length !== 1) {
        throw new Error("Incorrect number of arguments");
    }
    pbc.pinType = "pins_pwm";
    var pinblock = py2block.convert(func.value);
    pbc.pinType = null;
    var argblock = py2block.convert(args[0]);

    return [block("inout_pwm_analog_write", func.lineno, {}, {
        "PIN": pinblock,
        "NUM": argblock
    }, {
        "inline": "true"
    })];
}

pbc.objectFunctionD.get('freq')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) {
    if (args.length !== 1) {
        throw new Error("Incorrect number of arguments");
    }
    pbc.pinType = "pins_pwm";
    var pinblock = py2block.convert(func.value);
    pbc.pinType = null;
    var argblock = py2block.convert(args[0]);

    return [block("inout_analog_write_set_freq", func.lineno, {}, {
        "PIN": pinblock,
        "NUM": argblock
    }, {
        "inline": "true"
    })];
}
//ok
pbc.assignD.get('ADC')['check_assign'] = function(py2block, node, targets, value) {
    var moduleName = py2block.Name_str(value.func.value);
    var funcName = py2block.identifier(value.func.attr);
    if(value._astname === "Call"
        && funcName === "ADC" && moduleName === "machine" && value.args.length === 1)
        return true;
    return false;
}

pbc.assignD.get('ADC')['create_block'] = function(py2block, node, targets, value){
    var astname = value.args[0]._astname;
    var funcName = py2block.identifier(value.args[0].func.attr);
    if(astname === "Call" && funcName === "Pin"){ //
        pbc.pinType = "pins_analog_pin";
        pinblock =  py2block.convert(value.args[0].args[0]);
        pbc.pinType = null;
    }else{
        pbc.pinType = "pins_analog_pin";
        pinblock =  py2block.convert(args[0]);
        pbc.pinType = null;
    }
    pinobj = "adc"+value.args[0].args[0].n.v;
    return block("inout_analog_read_init", node.lineno, {"PIN_OBJ":pinobj}, {
        "PIN":pinblock,

    });
}

pbc.objectFunctionD.get('read')['Pin'] = function (py2block, func, args, keywords, starargs, kwargs, node) {
    if (args.length !== 0) {
        throw new Error("Incorrect number of arguments");
    }
    value = func.value.id.v
    value = value.slice(0,2)
    if( value=="ad"){
    pbc.pinType = "pins_analog";
    var pinblock = py2block.convert(func.value);
    pbc.pinType = null;

    return block("inout_analog_read", func.lineno, {}, {
        "PIN": pinblock,
    }, {
        "inline": "true"
    });}
    else if(value =="tc"){
    pbc.pinType = "pins_touch";
    var pinblock = py2block.convert(func.value);
    pbc.pinType = null;

    return block("inout_pin_pressed", func.lineno, {}, {
        "pin": pinblock,
    }, {
        "inline": "true"
    });
    }
}
//ok
pbc.assignD.get('TOUCHPAD')['check_assign'] = function(py2block, node, targets, value) {
    var moduleName = py2block.Name_str(value.func.value);
    var funcName = py2block.identifier(value.func.attr);
    if(value._astname === "Call"
        && funcName === "TouchPad" && moduleName === "machine" && value.args.length === 1)
        return true;
    return false;
}

pbc.assignD.get('TOUCHPAD')['create_block'] = function(py2block, node, targets, value){
    var astname = value.args[0]._astname;
    var funcName = py2block.identifier(value.args[0].func.attr);
    if(astname === "Call" &&  funcName === "Pin"){ //
        pbc.pinType = "pins_touch_pin";
        pinblock =  py2block.convert(value.args[0].args[0]);
        pbc.pinType = null;
    }else{
        pbc.pinType = "pins_touch_pin";
        pinblock =  py2block.convert(args[0]);
        pbc.pinType = null;
    }
    pinobj = "tc"+value.args[0].args[0].n.v;
    return block("inout_pin_pressed_init", node.lineno, {"PIN_OBJ":pinobj}, {
        "PIN":pinblock,

    });
}<|endoftext|>


<commit_before>var _ = require('./lib/underscore'),
    config = require('./config'),
    deps = require('./deps'),
    fs = require('fs'),
    child_process = require('child_process');

if (config.DAEMON)
	throw "Can't run dev server in daemon mode.";

var server;
var start_server = _.debounce(function () {
	if (server)
		server.kill('SIGTERM');
	server = child_process.spawn('node', ['server/server.js']);
	server.stdout.pipe(process.stdout);
	server.stderr.pipe(process.stderr);
}, 500);

var reload_state = _.debounce(function () {
	if (server)
		server.kill('SIGHUP');
}, 500);

var build_client = _.debounce(function () {
	var make = child_process.execFile('make', ['-s', '-q', 'client']);
	make.once('exit', function (code) {
		if (!code)
			return;
		console.log('make client');
		var make = child_process.execFile('make', ['-s', 'client']);
		make.stdout.pipe(process.stdout);
		make.stderr.pipe(process.stderr);
	});
}, 500);

deps.SERVER_DEPS.forEach(monitor.bind(null, start_server));
deps.SERVER_STATE.forEach(monitor.bind(null, reload_state));
deps.CLIENT_DEPS.forEach(monitor.bind(null, build_client));

function monitor(func, dep) {
	var mtime = new Date;
	fs.watchFile(dep, {interval: 500, persistent: true}, function (event) {
		if (event.mtime > mtime) {
			func();
			mtime = event.mtime;
		}
	});
}

start_server();
build_client();
<commit_msg>Altering config causes builder to remake client<commit_after>var _ = require('./lib/underscore'),
    config = require('./config'),
    deps = require('./deps'),
    fs = require('fs'),
    child_process = require('child_process');

if (config.DAEMON)
	throw "Can't run dev server in daemon mode.";

var server;
var start_server = _.debounce(function () {
	if (server)
		server.kill('SIGTERM');
	server = child_process.spawn('node', ['server/server.js']);
	server.stdout.pipe(process.stdout);
	server.stderr.pipe(process.stderr);
}, 500);

var reload_state = _.debounce(function () {
	if (server)
		server.kill('SIGHUP');
}, 500);

var build_client = _.debounce(function () {
	var make = child_process.execFile('make', ['-s', '-q', 'client']);
	make.once('exit', function (code) {
		if (!code)
			return;
		console.log('make client');
		var make = child_process.execFile('make', ['-s', 'client']);
		make.stdout.pipe(process.stdout);
		make.stderr.pipe(process.stderr);
	});
}, 500);

deps.SERVER_DEPS.forEach(monitor.bind(null, start_server));
deps.SERVER_STATE.forEach(monitor.bind(null, reload_state));
deps.CLIENT_DEPS.forEach(monitor.bind(null, build_client));
monitor(build_client, 'config.js');

function monitor(func, dep) {
	var mtime = new Date;
	fs.watchFile(dep, {interval: 500, persistent: true}, function (event) {
		if (event.mtime > mtime) {
			func();
			mtime = event.mtime;
		}
	});
}

start_server();
build_client();
<|endoftext|>


<commit_before>var async = require('async');
var events = require('events');
var fs = require('fs');
var glob = require('glob');
var mkdirp = require('mkdirp');
var path = require('path');
var temp = require('temp');

var config = require('./config');
var decider = require('./decider');
var log = require('./logger').cat('builder');

var ant = require('./ant');
var git = require('./git');

function buildId(spec) {
  return [ 'build', config.student.semester, spec.kind, spec.proj, spec.users.join('-'), spec.rev.substring(0, 7) ].join('-');
}

function buildJSONable(spec) {
  return { kind: spec.kind, proj: spec.proj, users: spec.users, rev: spec.rev.substring(0, 7) };
}

function buildResultDir(spec, staffrev) {
  return path.join(
    config.build.results, config.student.semester,
    spec.kind, spec.proj, spec.users.join('-'), spec.rev, staffrev
  );
}

function buildResultFile(spec) {
  return path.join(buildResultDir(spec), 'result.json');
}

function buildOutputBase(spec, staffrev, target) {
  return path.join(buildResultDir(spec, staffrev), target);
}

// find all projects
exports.findProjectsSync = function() {
  return glob.sync(path.join(config.student.semester, '*', '*'), {
    cwd: config.build.results
  }).map(function(dir) {
    var parts = dir.split(path.sep);
    return { kind: parts[1], proj: parts[2] };
  });
}

// find all the repos matching a kind, project, and/or users
exports.findRepos = function(spec, callback) {
  var kind = spec.kind || '*';
  var proj = spec.proj || '*';
  var users = spec.users ? '?(*-)' + spec.users.join('-') + '?(-*)' : '*';
  log.info('findRepos', kind, proj, users);
  glob(path.join(config.student.semester, kind, proj, users), {
    cwd: config.build.results
  }, function(err, files) {
    callback(err, files.map(function(file) {
      var parts = file.split(path.sep);
      return { kind: parts[1], proj: parts[2], users: parts[3].split('-') }
    }));
  });
};

// find all builds of a repo by kind, project, and users
exports.findBuilds = function(spec, callback) {
  log.info({ spec: spec }, 'findBuilds');
  var dir = path.join(config.build.results, config.student.semester, spec.kind, spec.proj, spec.users.join('-'));
  glob('*/result.json', {
    cwd: dir
  }, function(err, files) {
    log.info('findBuilds', 'found', files);
    var revs = files.map(function(file) {
      return { rev: file.split(path.sep)[0], ctime: fs.statSync(path.join(dir, file)).ctime.getTime() };
    }).sort(function(a, b) {
      return b.ctime - a.ctime;
    }).map(function(data) {
      return { kind: spec.kind, proj: spec.proj, users: spec.users, rev: data.rev };
    });
    callback(err, revs);
  });
};

// find a build of a repo by kind, project, users, and revision
exports.findBuild = function(spec, callback) {
  log.info({ spec: spec }, 'findBuild');
  fs.readFile(buildResultFile(spec), function(err, data) {
    if (err) {
      err.dmesg = err.dmesg || 'error reading build result file';
      callback(err, null);
      return;
    }
    var result = JSON.parse(data);
    result.spec = buildJSONable(spec);
    result.txt = {};
    result.json = {};
    var dir = buildResultDir(spec, result.builder);
    glob('*.*', {
      cwd: dir
    }, function(err, files) {
      async.forEach(files, function(file, next) {
        fs.readFile(path.join(dir, file), function(err, data) {
          var targtype = file.split('.');
          result[targtype[1]][targtype[0]] = targtype[1] == 'json' ? JSON.parse(data) : data.toString();
          next(err);
        });
      }, function(err) {
        callback(err, result);
      })
    })
  });
};

// start the build of a repo by kind, project, users, and revision
// callback returns a build id
exports.startBuild = function(spec, callback) {
  var path = [
    config.student.repos, config.student.semester, spec.kind, spec.proj, spec.users.join('-')
  ].join('/') + '.git';
  if ( ! fs.existsSync(path)) {
    log.error({ spec: spec }, 'startBuild no such repository');
    callback({ dmesg: 'no such repository' });
    return;
  }

  var id = buildId(spec);
  decider.startWorkflow(id, buildJSONable(spec), function(err) {
    if (err) {
      log.error(err, 'startBuild error');
      err.dmesg = err.dmesg || 'failed to start workflow';
    }
    callback(err, id);
  });
};

// obtain a build progress listener
exports.monitor = function(id) {
  var mon = new events.EventEmitter();
  function report(event, data) {
    log.info('monitor', id, event, data);
    mon.emit(event, data);
  }
  decider.on(id, report);
  mon.cancel = function() {
    log.info('monitor', id, 'cancelling')
    decider.removeListener(id, report);
  };
  return mon;
};

// run the build
// stores results and returns them in the callback
exports.build = function(spec, progressCallback, resultCallback) {
  log.info({ spec: spec }, 'build');
  var started = +new Date();
  async.auto({
    builddir: async.apply(temp.mkdir, 'didit-'),
    revdir: async.apply(mkdirp, buildResultDir(spec)),
    source: [ 'builddir', 'revdir', function(next, results) {
      git.cloneStudentSource(spec, results.builddir, next);
    } ],
    builder: [ 'source', function(next, results) {
      git.fetchBuilder(spec, results.builddir, next);
    } ],
    builderProgress: [ 'builder', function(next, results) {
      progressCallback('Checked out rev ' + results.source.rev);
      next();
    } ],
    resultdir: [ 'builder', function(next, results) {
      mkdirp(buildResultDir(spec, results.builder), next);
    } ],
    compile: [ 'resultdir', function(next, results) {
      ant.compile(spec, results.builddir, 'compile', buildOutputBase(spec, results.builder, 'compile'), next);
    } ],
    compileProgress: [ 'compile', function(next, results) {
      if ( ! results.compile) {
        progressCallback('Compilation error');
      }
      next();
    } ],
    public: [ 'compile', function(next, results) {
      ant.test(spec, results.builddir, 'public', buildOutputBase(spec, results.builder, 'public'), next);
    } ],
    hidden: [ 'public', function(next, results) {
      ant.test(spec, results.builddir, 'hidden', buildOutputBase(spec, results.builder, 'hidden'), next);
    } ]
  }, function(err, results) {
    log.info('build complete');
    results = results || {};
    if (err) {
      log.error(err, 'build error');
      err.dmesg = err.dmesg || 'unknown build error';
      results.err = err;
    }
    results.started = started;
    results.finished = +new Date();
    fs.writeFile(buildResultFile(spec), JSON.stringify(results), function(fserr) {
      if (fserr) { log.error({ err: fserr, results: results }, 'error writing results'); }
      resultCallback(err || fserr, results);
    });
  });
}

// command-line build
if (require.main === module) {
  var args = process.argv.slice(2);
  log.info('manual build', args);
  if ( ! args.join(' ').match(/^\w+ \w+ [\w-]+ \w+$/)) {
    log.error('expected arguments: <kind> <proj> <users> <rev>');
    return;
  }
  exports.build({
    kind: args[0], proj: args[1], users: args[2].split('-'), rev: args[3]
  }, function(progress) {
    log.info({ progress: progress }, 'progress');
  }, function(err, result) {
    if (err) { log.error(err, 'error'); }
    log.info(result, 'result');
  });
}
<commit_msg>Handle JSON errors in build result files<commit_after>var async = require('async');
var events = require('events');
var fs = require('fs');
var glob = require('glob');
var mkdirp = require('mkdirp');
var path = require('path');
var temp = require('temp');

var config = require('./config');
var decider = require('./decider');
var log = require('./logger').cat('builder');

var ant = require('./ant');
var git = require('./git');

function buildId(spec) {
  return [ 'build', config.student.semester, spec.kind, spec.proj, spec.users.join('-'), spec.rev.substring(0, 7) ].join('-');
}

function buildJSONable(spec) {
  return { kind: spec.kind, proj: spec.proj, users: spec.users, rev: spec.rev.substring(0, 7) };
}

function buildResultDir(spec, staffrev) {
  return path.join(
    config.build.results, config.student.semester,
    spec.kind, spec.proj, spec.users.join('-'), spec.rev, staffrev
  );
}

function buildResultFile(spec) {
  return path.join(buildResultDir(spec), 'result.json');
}

function buildOutputBase(spec, staffrev, target) {
  return path.join(buildResultDir(spec, staffrev), target);
}

// find all projects
exports.findProjectsSync = function() {
  return glob.sync(path.join(config.student.semester, '*', '*'), {
    cwd: config.build.results
  }).map(function(dir) {
    var parts = dir.split(path.sep);
    return { kind: parts[1], proj: parts[2] };
  });
}

// find all the repos matching a kind, project, and/or users
exports.findRepos = function(spec, callback) {
  var kind = spec.kind || '*';
  var proj = spec.proj || '*';
  var users = spec.users ? '?(*-)' + spec.users.join('-') + '?(-*)' : '*';
  log.info('findRepos', kind, proj, users);
  glob(path.join(config.student.semester, kind, proj, users), {
    cwd: config.build.results
  }, function(err, files) {
    callback(err, files.map(function(file) {
      var parts = file.split(path.sep);
      return { kind: parts[1], proj: parts[2], users: parts[3].split('-') }
    }));
  });
};

// find all builds of a repo by kind, project, and users
exports.findBuilds = function(spec, callback) {
  log.info({ spec: spec }, 'findBuilds');
  var dir = path.join(config.build.results, config.student.semester, spec.kind, spec.proj, spec.users.join('-'));
  glob('*/result.json', {
    cwd: dir
  }, function(err, files) {
    log.info('findBuilds', 'found', files);
    var revs = files.map(function(file) {
      return { rev: file.split(path.sep)[0], ctime: fs.statSync(path.join(dir, file)).ctime.getTime() };
    }).sort(function(a, b) {
      return b.ctime - a.ctime;
    }).map(function(data) {
      return { kind: spec.kind, proj: spec.proj, users: spec.users, rev: data.rev };
    });
    callback(err, revs);
  });
};

// find a build of a repo by kind, project, users, and revision
exports.findBuild = function(spec, callback) {
  log.info({ spec: spec }, 'findBuild');
  fs.readFile(buildResultFile(spec), function(err, data) {
    if (err) {
      err.dmesg = err.dmesg || 'error reading build result file';
      callback(err, null);
      return;
    }
    try {
      var result = JSON.parse(data);
    } catch (err) {
      log.error(err, { spec: spec, file: 'result' });
      callback(err);
      return;
    }
    result.spec = buildJSONable(spec);
    result.txt = {};
    result.json = {};
    var dir = buildResultDir(spec, result.builder);
    glob('*.*', {
      cwd: dir
    }, function(err, files) {
      async.forEach(files, function(file, next) {
        fs.readFile(path.join(dir, file), function(err, data) {
          var targtype = file.split('.');
          try {
            result[targtype[1]][targtype[0]] = targtype[1] == 'json' ? JSON.parse(data) : data.toString();
          } catch (err) {
            log.error(err, { spec: spec, file: file });
            next(err);
            return;
          }
          next(err);
        });
      }, function(err) {
        callback(err, result);
      })
    })
  });
};

// start the build of a repo by kind, project, users, and revision
// callback returns a build id
exports.startBuild = function(spec, callback) {
  var path = [
    config.student.repos, config.student.semester, spec.kind, spec.proj, spec.users.join('-')
  ].join('/') + '.git';
  if ( ! fs.existsSync(path)) {
    log.error({ spec: spec }, 'startBuild no such repository');
    callback({ dmesg: 'no such repository' });
    return;
  }

  var id = buildId(spec);
  decider.startWorkflow(id, buildJSONable(spec), function(err) {
    if (err) {
      log.error(err, 'startBuild error');
      err.dmesg = err.dmesg || 'failed to start workflow';
    }
    callback(err, id);
  });
};

// obtain a build progress listener
exports.monitor = function(id) {
  var mon = new events.EventEmitter();
  function report(event, data) {
    log.info('monitor', id, event, data);
    mon.emit(event, data);
  }
  decider.on(id, report);
  mon.cancel = function() {
    log.info('monitor', id, 'cancelling')
    decider.removeListener(id, report);
  };
  return mon;
};

// run the build
// stores results and returns them in the callback
exports.build = function(spec, progressCallback, resultCallback) {
  log.info({ spec: spec }, 'build');
  var started = +new Date();
  async.auto({
    builddir: async.apply(temp.mkdir, 'didit-'),
    revdir: async.apply(mkdirp, buildResultDir(spec)),
    source: [ 'builddir', 'revdir', function(next, results) {
      git.cloneStudentSource(spec, results.builddir, next);
    } ],
    builder: [ 'source', function(next, results) {
      git.fetchBuilder(spec, results.builddir, next);
    } ],
    builderProgress: [ 'builder', function(next, results) {
      progressCallback('Checked out rev ' + results.source.rev);
      next();
    } ],
    resultdir: [ 'builder', function(next, results) {
      mkdirp(buildResultDir(spec, results.builder), next);
    } ],
    compile: [ 'resultdir', function(next, results) {
      ant.compile(spec, results.builddir, 'compile', buildOutputBase(spec, results.builder, 'compile'), next);
    } ],
    compileProgress: [ 'compile', function(next, results) {
      if ( ! results.compile) {
        progressCallback('Compilation error');
      }
      next();
    } ],
    public: [ 'compile', function(next, results) {
      ant.test(spec, results.builddir, 'public', buildOutputBase(spec, results.builder, 'public'), next);
    } ],
    hidden: [ 'public', function(next, results) {
      ant.test(spec, results.builddir, 'hidden', buildOutputBase(spec, results.builder, 'hidden'), next);
    } ]
  }, function(err, results) {
    log.info('build complete');
    results = results || {};
    if (err) {
      log.error(err, 'build error');
      err.dmesg = err.dmesg || 'unknown build error';
      results.err = err;
    }
    results.started = started;
    results.finished = +new Date();
    fs.writeFile(buildResultFile(spec), JSON.stringify(results), function(fserr) {
      if (fserr) { log.error({ err: fserr, results: results }, 'error writing results'); }
      resultCallback(err || fserr, results);
    });
  });
}

// command-line build
if (require.main === module) {
  var args = process.argv.slice(2);
  log.info('manual build', args);
  if ( ! args.join(' ').match(/^\w+ \w+ [\w-]+ \w+$/)) {
    log.error('expected arguments: <kind> <proj> <users> <rev>');
    return;
  }
  exports.build({
    kind: args[0], proj: args[1], users: args[2].split('-'), rev: args[3]
  }, function(progress) {
    log.info({ progress: progress }, 'progress');
  }, function(err, result) {
    if (err) { log.error(err, 'error'); }
    log.info(result, 'result');
  });
}
<|endoftext|>


<commit_before>import { loadAsync } from './helpers/async-component';

const getMyCourses = function() {
  const { default: MyCourses } = require('./components/my-courses');
  return MyCourses;
};

const getDashboard = function() {
  const ConditionalHandlers = require('./helpers/conditional-handlers');
  return ConditionalHandlers.dashboard;
};

const getTeacherTaskPlans = function() {
  const { default: TeacherTaskPlans } = require('./components/course-calendar');
  return TeacherTaskPlans;
};

const getTaskShell = function() {
  const { TaskShell } = require('./components/task');
  return TaskShell;
};

const getReferenceBookShell = function() {
  const { default: ReferenceBookShell } = require('./components/reference-book');
  return ReferenceBookShell;
};

const getReferenceBookPageShell = function() {
  const { default: ReferenceBookPageShell } = require('./components/reference-book');
  return ReferenceBookPageShell;
};

const getReadingShell = function() {
  const { ReadingShell } = require('./components/task-plan');
  return ReadingShell;
};

const getHomeworkShell = function() {
  const { HomeworkShell } = require('./components/task-plan');
  return HomeworkShell;
};

const getExternalShell = function() {
  const { ExternalShell } = require('./components/task-plan');
  return ExternalShell;
};

const getPaymentsShell = function() {
  const { default: Payments } = require('./components/payments/manage');
  return Payments;
};

const getEventShell = function() {
  const { EventShell } = require('./components/task-plan');
  return EventShell;
};

const getScoresShell = function() {
  const { default: StudentScores } = require('./components/scores');
  return StudentScores;
};

const getPerformanceForecastGuide = function() {
  const PerformanceForecast = require('./components/performance-forecast');
  return PerformanceForecast.Guide;
};

const getCourseSettings = function() {
  const { default: CourseSettings } = require('./components/course-settings');
  return CourseSettings;
};

const getCourseRoster = function() {
  const { default: CourseRoster } = require('./components/course-roster');
  return CourseRoster;
};

const getPractice = () => require('./components/task/practice');

const getQuestionsLibrary = () => require('./components/questions');

const getChangeStudentId = function() {
  const { default: StudentId } = require('./components/change-student-id');
  return StudentId;
};

const getQADashboard = () => require('./components/qa/index');

const getQABook = () => require('./components/qa/view-book');

const getCreateCourse = function() {
  const { default: Wizard } =  require('./components/new-course');
  return Wizard;
};

const getTeacherReview = function() {
  const { default: TaskTeacherReview } = require('./components/task-teacher-review');
  return TaskTeacherReview;
};

const getCCHelp = () => require('./components/cc-dashboard/help');

const getCreateEnrollmentChange = function() {
  const { default: CourseEnroll } = require('./components/enroll');
  return CourseEnroll;
};

const getAccessibilityStatement = function() {
  const { default: AccessibilityStatement } = require('./components/accessibility-statement');
  return AccessibilityStatement;
};

const getStudentPreview = function() {
  const { default: StudentPreview } = require('./components/student-preview');
  return StudentPreview;
};

const ROUTES = [
  { path: '/dashboard', name: 'myCourses', renderer: getMyCourses },
  { path: '/enroll/start/:enrollmentCode', name: 'createEnrollmentChange', renderer: getCreateEnrollmentChange },
  { path: '/new-course/:sourceId?', name: 'createNewCourse', renderer: getCreateCourse },
  {
    path: '/qa', name: 'QADashboard', renderer: () => loadAsync(() => System.import('./screens/qa/index.jsx')),

    // routes: [
    //   {
    //     path: ':ecosystemId', name: 'QAViewBook', renderer: getQABook,
    //     routes: [{
    //       path: 'section/:section', name: 'QAViewBookSection', renderer: getQABook,
    //     }],
    //   },
    // ],
  },
  {
    path: '/course/:courseId', name: 'dashboard', renderer: getDashboard,
    routes: [
      { path: 'scores', name: 'viewScores', renderer: getScoresShell },
      { path: 'cc/help', name: 'ccDashboardHelp', renderer: getCCHelp },
      { path: 'guide/:roleId?', name: 'viewPerformanceGuide', renderer: getPerformanceForecastGuide },
      {
        path: 't', name: 'viewTeacherDashboard', renderer: getTeacherTaskPlans,
        routes: [
          {
            path: 'month/:date', name: 'calendarByDate', renderer: getTeacherTaskPlans,
            routes: [{
              path: 'plan/:planId', name: 'calendarViewPlanStats', renderer: getTeacherTaskPlans,
            }],
          },
        ],
      },
      { path: 'metrics/:id', name: 'reviewTask', renderer: getTeacherReview },
      {
        path: 'task/:id', name: 'viewTask', renderer: getTaskShell,
        routes: [
          {
            path: 'step/:stepIndex', name: 'viewTaskStep', renderer: getTaskShell,
            routes: [{
              path: ':milestones', name: 'viewTaskStepMilestones', renderer: getTaskShell,
            }],
          },
        ],
      },
      { path: 'practice/:taskId?', name: 'practiceTopics', renderer: getPractice },
      { path: 'homework/new', name: 'createHomework' },
      { path: 'homework/:id', name: 'editHomework', renderer: getHomeworkShell },
      { path: 'reading/new', name: 'createReading' },
      { path: 'reading/:id', name: 'editReading', renderer: getReadingShell },
      { path: 'external/new', name: 'createExternal' },
      { path: 'external/:id', name: 'editExternal', renderer: getExternalShell },
      { path: 'event/new', name: 'createEvent' },
      { path: 'event/:id', name: 'editEvent', renderer: getEventShell },
      { path: 'settings', name: 'courseSettings', renderer: getCourseSettings },
      { path: 'roster', name: 'courseRoster', renderer: getCourseRoster },
      { path: 'questions', name: 'viewQuestionsLibrary', renderer: getQuestionsLibrary },
      { path: 'change-student-id', name: 'changeStudentId', renderer: getChangeStudentId },
    ],

  }, {
    path: '/accessibility-statement/:courseId?', name: 'accessibilityStatement', renderer: getAccessibilityStatement,
  }, {
    path: '/student-preview/:courseId?', name: 'studentPreview', renderer: getStudentPreview,
  },
  { path: '/payments', name: 'managePayments', renderer: getPaymentsShell },
  {
    path: '/books/:courseId', name: 'viewReferenceBook', renderer: getReferenceBookShell, settings: { navBar: 'ReferenceBook' },
    routes: [
      { path: 'section/:section', name: 'viewReferenceBookSection', renderer: getReferenceBookShell, settings: { navBar: 'ReferenceBook' } },
      { path: 'page/:cnxId', name: 'viewReferenceBookPage', renderer: getReferenceBookPageShell, settings: { navBar: 'ReferenceBook' } },
    ],
  },
];

export default ROUTES;

//# Below is pre router upgrade config

// {Route, Redirect, NotFoundRoute} = Router

// async = require './helpers/webpack-async-loader'

// {App, Root, Dashboard, SingleTask, SinglePractice, Invalid} = require './components'
// {CourseListing} = require './components/course-listing'
// {AssignmentLinks} = require './components/assignment-links'
// QuestionsLibrary = require './components/questions'
// ChangeStudentId = require './components/change-student-id'
// PerformanceForecastShell = require './components/performance-forecast'
// {ScoresShell} = require './components/scores'
// {ReadingShell, HomeworkShell, ExternalShell, EventShell} = require './components/task-plan'
// {StudentDashboardShell} = require './components/student-dashboard'
// CCStudentRedirect = require './components/cc-student-redirect'
// TeacherTaskPlans = require './components/task-plan/teacher-task-plans-listing'
// {TaskTeacherReviewShell} = require './components/task-teacher-review'
// {ReferenceBookShell, ReferenceBookPageShell, ReferenceBookFirstPage} =
//   require './components/reference-book'
// {StatsShell} = require './components/plan-stats'
// CCDashboard = require './components/cc-dashboard'
// CCDashboardHelp = require './components/cc-dashboard/help'

// CourseSettings = require './components/course-settings'
// Sandbox = require './sandbox'
// CourseHandler = require './helpers/conditional-rendering'

// QALoader = require 'promise?global!./qa'

// routes = (
//   <Route handler={Root} name='root'>
//     <Route path='/' handler={App} name='app'>
//       <Redirect from='/' to='dashboard' />
//       <Route path='dashboard/?' name='dashboard' handler={CourseListing} />

//       <Route path='courses/:courseId/?'>
//         <Route path='change-student-id' name='changeStudentId' handler={ChangeStudentId} />
//         <Router.DefaultRoute handler={TeacherTaskPlans}/>
//         <Route path='cc-student-redirect/?' name='viewStudentCCRedirect' handler={CCStudentRedirect} />

//         <Route path='assignment-links/?' name='viewAssignmentLinks' handler={AssignmentLinks} />
//         <Route path='list/?' name='viewStudentDashboard' handler={StudentDashboardShell} />
//         <Route path='tasks/:id/?' name='viewTask' handler={SingleTask} ignoreScrollBehavior>
//           <Route path='steps/:stepIndex/?'
//             name='viewTaskStep'
//             handler={SingleTask}
//             ignoreScrollBehavior>
//             <Route
//               path=':milestones/?'
//               name='viewTaskStepMilestones'
//               ignoreScrollBehavior/>
//           </Route>
//         </Route>

//         <Route path='practice/?' name='viewPractice' handler={SinglePractice} />
//         <Route
//           path='guide/?'
//           name='viewPerformanceForecast'
//           handler={PerformanceForecastShell.Student}/>

//         <Route path='t/' name='viewTeacherDashBoard'>
//           <Router.DefaultRoute handler={TeacherTaskPlans} />
//           <Route path='scores/?' name='viewScores'
//             handler={CourseHandler(ScoresShell, requireRole: 'teacher', requirePeriods: true)} />
//           <Route path='guide' name='viewTeacherPerformanceForecast'
//             handler={CourseHandler(PerformanceForecastShell.Teacher, requireRole: 'teacher', requirePeriods: true)} />
//           <Route path='guide/student/:roleId?' name='viewStudentTeacherPerformanceForecast'
//             handler={CourseHandler(PerformanceForecastShell.TeacherStudent, requireRole: 'teacher', requirePeriods: true)}/>

//           <Route path='calendar/?' name='taskplans'>
//             <Router.DefaultRoute handler={TeacherTaskPlans} />
//             <Route
//               path='months/:date/?'
//               name='calendarByDate'
//               handler={TeacherTaskPlans}
//               ignoreScrollBehavior>
//               <Route
//                 path='plans/:planId/?'
//                 name='calendarViewPlanStats'
//                 ignoreScrollBehavior/>
//             </Route>
//           </Route>
//           <Route path='questions' name='viewQuestionsLibrary' handler={QuestionsLibrary} />

//           <Route path='cc-dashboard/?' name='cc-dashboard'>
//             <Router.DefaultRoute handler={CCDashboard} />
//             <Route path='help/?' name='ccDashboardHelp' handler={CCDashboardHelp} />
//             <Route path='guide/?' name='ccDashboardGuide' handler={CCDashboard} />
//           </Route>

//           <Route path='homeworks/new/?' name='createHomework' handler={HomeworkShell} />
//           <Route path='homeworks/:id/?' name='editHomework' handler={HomeworkShell} />
//           <Route path='readings/new/?' name='createReading' handler={ReadingShell} />
//           <Route path='readings/:id/?' name='editReading' handler={ReadingShell} />
//           <Route path='externals/new/?' name='createExternal' handler={ExternalShell} />
//           <Route path='externals/:id/?' name='editExternal' handler={ExternalShell} />
//           <Route path='events/new/?' name='createEvent' handler={EventShell} />
//           <Route path='events/:id/?' name='editEvent' handler={EventShell} />
//           <Route path='settings' name='courseSettings' handler={CourseSettings} />
//           <Route path='plans/:id/?'>
//             <Router.DefaultRoute handler={StatsShell}/>
//             <Route path='stats/?' name='viewStats' handler={StatsShell} />
//             <Route path='summary/?' name='reviewTask' handler={TaskTeacherReviewShell}>
//               <Route
//                 path='sections/:sectionIndex/?'
//                 name='reviewTaskStep'
//                 ignoreScrollBehavior />
//             </Route>
//           </Route>
//         </Route>
//       </Route>
//       <Route path='sandbox/?' name='sandbox' handler={Sandbox} />
//     </Route> # end of routes handled by App

//     <Route path='/books/:courseId/?' name='viewReferenceBook' handler={ReferenceBookShell}>
//       <Router.DefaultRoute name="viewReferenceBookFirstPage" handler={ReferenceBookPageShell}/>
//       <Route path='section/:section' name='viewReferenceBookSection' handler={ReferenceBookShell} />
//       <Route path='page/:cnxId' name='viewReferenceBookPage' handler={ReferenceBookPageShell}/>
//     </Route> # end of /books route

//     <Route path='/qa' name='QADashboard' handler={async(QALoader, 'QADashboard')} >
//       <Router.DefaultRoute name="QAViewFirstBook" handler={async(QALoader, 'QABook')}/>

//       <Route path=':ecosystemId' name='QAViewBook'
//         handler={async(QALoader, 'QABook')} />
//       <Route path=':ecosystemId/section/:section' name='QAViewBookSection'
//         handler={async(QALoader, 'QABook')} />

//     </Route> # end of qa route

//     <NotFoundRoute handler={Invalid} />
//   </Route>
// )

// # Remember the router for unit testing
// router = Router.create
//   routes: routes
//   location: Router.HistoryLocation

// start = (mountPoint) ->
//   router.run (Handler) ->
//     React.render(<Handler/>, mountPoint)

// module.exports = {start, router, routes}
<commit_msg>remove old routes<commit_after>import { loadAsync } from './helpers/async-component';

const getMyCourses = function() {
  const { default: MyCourses } = require('./components/my-courses');
  return MyCourses;
};

const getDashboard = function() {
  const ConditionalHandlers = require('./helpers/conditional-handlers');
  return ConditionalHandlers.dashboard;
};

const getTeacherTaskPlans = function() {
  const { default: TeacherTaskPlans } = require('./components/course-calendar');
  return TeacherTaskPlans;
};

const getTaskShell = function() {
  const { TaskShell } = require('./components/task');
  return TaskShell;
};

const getReferenceBookShell = function() {
  const { default: ReferenceBookShell } = require('./components/reference-book');
  return ReferenceBookShell;
};

const getReferenceBookPageShell = function() {
  const { default: ReferenceBookPageShell } = require('./components/reference-book');
  return ReferenceBookPageShell;
};

const getReadingShell = function() {
  const { ReadingShell } = require('./components/task-plan');
  return ReadingShell;
};

const getHomeworkShell = function() {
  const { HomeworkShell } = require('./components/task-plan');
  return HomeworkShell;
};

const getExternalShell = function() {
  const { ExternalShell } = require('./components/task-plan');
  return ExternalShell;
};

const getPaymentsShell = function() {
  const { default: Payments } = require('./components/payments/manage');
  return Payments;
};

const getEventShell = function() {
  const { EventShell } = require('./components/task-plan');
  return EventShell;
};

const getScoresShell = function() {
  const { default: StudentScores } = require('./components/scores');
  return StudentScores;
};

const getPerformanceForecastGuide = function() {
  const PerformanceForecast = require('./components/performance-forecast');
  return PerformanceForecast.Guide;
};

const getCourseSettings = function() {
  const { default: CourseSettings } = require('./components/course-settings');
  return CourseSettings;
};

const getCourseRoster = function() {
  const { default: CourseRoster } = require('./components/course-roster');
  return CourseRoster;
};

const getPractice = () => require('./components/task/practice');

const getQuestionsLibrary = () => require('./components/questions');

const getChangeStudentId = function() {
  const { default: StudentId } = require('./components/change-student-id');
  return StudentId;
};

const getQADashboard = () => require('./components/qa/index');

const getQABook = () => require('./components/qa/view-book');

const getCreateCourse = function() {
  const { default: Wizard } =  require('./components/new-course');
  return Wizard;
};

const getTeacherReview = function() {
  const { default: TaskTeacherReview } = require('./components/task-teacher-review');
  return TaskTeacherReview;
};

const getCCHelp = () => require('./components/cc-dashboard/help');

const getCreateEnrollmentChange = function() {
  const { default: CourseEnroll } = require('./components/enroll');
  return CourseEnroll;
};

const getAccessibilityStatement = function() {
  const { default: AccessibilityStatement } = require('./components/accessibility-statement');
  return AccessibilityStatement;
};

const getStudentPreview = function() {
  const { default: StudentPreview } = require('./components/student-preview');
  return StudentPreview;
};

const ROUTES = [
  { path: '/dashboard', name: 'myCourses', renderer: getMyCourses },
  { path: '/enroll/start/:enrollmentCode', name: 'createEnrollmentChange', renderer: getCreateEnrollmentChange },
  { path: '/new-course/:sourceId?', name: 'createNewCourse', renderer: getCreateCourse },
  {
    path: '/qa', name: 'QADashboard', renderer: () => loadAsync(() => System.import('./screens/qa/index.jsx')),

    // routes: [
    //   {
    //     path: ':ecosystemId', name: 'QAViewBook', renderer: getQABook,
    //     routes: [{
    //       path: 'section/:section', name: 'QAViewBookSection', renderer: getQABook,
    //     }],
    //   },
    // ],
  },
  {
    path: '/course/:courseId', name: 'dashboard', renderer: getDashboard,
    routes: [
      { path: 'scores', name: 'viewScores', renderer: getScoresShell },
      { path: 'cc/help', name: 'ccDashboardHelp', renderer: getCCHelp },
      { path: 'guide/:roleId?', name: 'viewPerformanceGuide', renderer: getPerformanceForecastGuide },
      {
        path: 't', name: 'viewTeacherDashboard', renderer: getTeacherTaskPlans,
        routes: [
          {
            path: 'month/:date', name: 'calendarByDate', renderer: getTeacherTaskPlans,
            routes: [{
              path: 'plan/:planId', name: 'calendarViewPlanStats', renderer: getTeacherTaskPlans,
            }],
          },
        ],
      },
      { path: 'metrics/:id', name: 'reviewTask', renderer: getTeacherReview },
      {
        path: 'task/:id', name: 'viewTask', renderer: getTaskShell,
        routes: [
          {
            path: 'step/:stepIndex', name: 'viewTaskStep', renderer: getTaskShell,
            routes: [{
              path: ':milestones', name: 'viewTaskStepMilestones', renderer: getTaskShell,
            }],
          },
        ],
      },
      { path: 'practice/:taskId?', name: 'practiceTopics', renderer: getPractice },
      { path: 'homework/new', name: 'createHomework' },
      { path: 'homework/:id', name: 'editHomework', renderer: getHomeworkShell },
      { path: 'reading/new', name: 'createReading' },
      { path: 'reading/:id', name: 'editReading', renderer: getReadingShell },
      { path: 'external/new', name: 'createExternal' },
      { path: 'external/:id', name: 'editExternal', renderer: getExternalShell },
      { path: 'event/new', name: 'createEvent' },
      { path: 'event/:id', name: 'editEvent', renderer: getEventShell },
      { path: 'settings', name: 'courseSettings', renderer: getCourseSettings },
      { path: 'roster', name: 'courseRoster', renderer: getCourseRoster },
      { path: 'questions', name: 'viewQuestionsLibrary', renderer: getQuestionsLibrary },
      { path: 'change-student-id', name: 'changeStudentId', renderer: getChangeStudentId },
    ],

  }, {
    path: '/accessibility-statement/:courseId?', name: 'accessibilityStatement', renderer: getAccessibilityStatement,
  }, {
    path: '/student-preview/:courseId?', name: 'studentPreview', renderer: getStudentPreview,
  },
  { path: '/payments', name: 'managePayments', renderer: getPaymentsShell },
  {
    path: '/books/:courseId', name: 'viewReferenceBook', renderer: getReferenceBookShell, settings: { navBar: 'ReferenceBook' },
    routes: [
      { path: 'section/:section', name: 'viewReferenceBookSection', renderer: getReferenceBookShell, settings: { navBar: 'ReferenceBook' } },
      { path: 'page/:cnxId', name: 'viewReferenceBookPage', renderer: getReferenceBookPageShell, settings: { navBar: 'ReferenceBook' } },
    ],
  },
];

export default ROUTES;
<|endoftext|>