<commit_before>// https://github.com/ksvan/node-red-contrib-verisure/wiki/Detailed-setup---automated-nodered-test
/*
mosquitto_sub -v -t home/test/switchTimer | awk '{ print strftime("%F_%T.%s"), "" $0; fflush(); }' | tee ${file} # ^Z
bg

mosquitto_pub -t 'home/test/switchTimer' -m '{ "payload": "junk", "timeout" : 4, "warning": 2 }'

2021-01-13_02:26:07.1610522767 home/test/switchTimer { "payload": "junk", "timer" : 4, "warning": 2 }
2021-01-13_02:26:07.1610522767 home/test/switchTimer on
2021-01-13_02:26:35.1610522795 home/test/switchTimer warning
2021-01-13_02:26:37.1610522797 home/test/switchTimer off

You have new mail in /var/mail/njc
(pts/27) njc@mozart:~/dev/git/mytimeout/t/dev-test$ fg
mosquitto_sub -v -t home/test/switchTimer | awk '{ print strftime("%F_%T.%s"), "" $0; fflush(); }' | tee ${file}
^C

*/
"use strict";

const should = require("should");
var   helper = require('node-red-node-test-helper');
var   myNode = require('../mytimeout.js');

helper.init(require.resolve('node-red'));

var nom =  'MyTimeout';

describe('mytimeout Node', function () {

  beforeEach(function (done) {
    helper.startServer(done);
  });

  afterEach(function (done) {
    /* */
    helper.unload();
    helper.stopServer(done);
    /* */
  });

  it('should be loaded', function (done) {
    // select in node-red editor the node to test, then hamburger, then export, then copy to clipboard, then paste here:
    /* */
    var flow1 = [{
      "id":         'n1', // was"abf332d4.4e",
      "type":       "mytimeout",
      "z":          "b431bcd1.51942",
      "name":       nom,
      "outtopic":   "",
      "outsafe":    'on',
      "outwarning": "Warning",
      "outunsafe":  "off",
      "warning":    "5",        // ??? shouldn't this be warning
      "timer":      "30",
      "debug":      false,
      "ndebug":     false,
      "ignoreCase": false,
      "repeat":     false,
      "again":      false,
      "x":          600,
      "y":          840,
      "wires":[
        ["ba562635.2144c8","6b9eec06.608274"],
        ["2b13443d.b2b27c","e1f06422.544ee8"]
      ]
    }];
    /* */
    /*
    Node 1: {
      "id": "n1",
      "type": "mytimeout",
      "z": "b431bcd1.51942",
      "_closeCallbacks": [
        null
      ],
      "_inputCallbacks": null,
      "name": "MyTimeout",
      "wires": [
        [
          "ba562635.2144c8",
          "6b9eec06.608274"
        ],
        [
          "2b13443d.b2b27c",
          "e1f06422.544ee8"
        ]
      ],
      "_wireCount": 4,
      "timer": 30,
      "state": "stop",
      "warning": 5,
      "topic": "",
      "outsafe": "on",
      "outwarn": "Warning",
      "outunsafe": "off",
      "repeat": false,
      "again": false,
      "_events": null,
      "_eventsCount": 1
    }
    */
    var flow = [{ id: "n1", type: "mytimeout", name: nom }];
    // Node 1: {
    //   "id":"n1",
    //   "type":"mytimeout",
    //   "_closeCallbacks":[null],
    //   "_inputCallbacks":null,
    //   "name":"MyTimeout",
    //   "wires":[],
    //   "_wireCount":0,
    //   "timer":30,
    //   "state":"stop",
    //   "warning":5,
    //   "outunsafe":"off",
    //   "_events":{},
    //   "_eventsCount":1
    // }
    helper.load(myNode, flow, function () {
      var n1 = helper.getNode("n1");
      //console.log ("Node 1:" + JSON.stringify(n1));
      n1.should.have.properties({
        'name':    nom,
        "outunsafe": 'off',
        'timer':   30,   // Defaults
        'warning':   5     // Defaults
      });
      //n1.should.not.have.property('outsafe'); // This eventually needs to get there
      done();
    });
  });

  it('Should turn off Tx 0', function (done) {
    var flow = [
      { id: "n1", type: "mytimeout", name: nom, wires:[["n2"]] },
      { id: "n2", type: "helper" }
    ];
    helper.load(myNode, flow, function () {
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");
      n2.on("input", function (msg) {
        msg.should.have.property('payload', 'off');
        done();
      });
      n1.receive({ payload: '0' });
    });
  });
  /* * /
  /* */

  it('Should turn off 2 Tx 0', function (done) { // Passes
    var flow = [
      { id: "n1", type: "mytimeout", name: nom, output: 2, wires:[["n2"], ["n3"]] },
      { id: "n2", type: "helper" },
      { id: "n3", type: "helper" }
    ];
    helper.load(myNode, flow, function () {
      var fini = 0;

      var n3 = helper.getNode("n3");
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");

      // Okay the fini++ seems like a good idea but if I get 2 n2 or 2 n3 I might gets a false done
      n2.on("input", function (msg) {
        msg.should.have.property('payload', 'off');
        fini++;
        if(fini > 1) {
          done();
        }
      });

      n3.on("input", function (msg) {
        msg.should.have.property('payload', 0);
        fini++;
        if(fini > 1) {
          done();
        }
      });

      n1.receive({ payload: '0' });
    });
  });
  /* */

  it('Should turn on with junk, simple Tx junk', function (done) { // Fails
    var flow = [
      { id: "n1", type: "mytimeout", name: nom,
        outsafe:    "on",
        outwarning: "warning",
        outunsafe:  "off",
        warning:    "5",
        timer:      "30",
        debug:      "0",
        wires:[["n2"]] },
      { id: "n2", type: "helper" }
    ];
    helper.load(myNode, flow, function () {
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");

      n2.on("input", function (msg) {
        msg.should.have.property("payload", "on");
        //console.log('Msg: ' + JSON.stringify(msg));
        done();
      });
      n1.receive({ payload: "junk" });
    });
  });
  /* */

  /*
  ** Main output
  ** n2: {"_msgid":"65d8f152.8e917","payload":"on","topic":"","timeout":30}
  ** Ticks output
  ** n3: {"payload":30,"state":1,"flag":"ticks > 0","_msgid":"5e5dd4bf.1be32c"}
  */
  it('Should turn on Tx on', function (done) {
    var flow = [
      { id: "n1", type: "mytimeout", name: nom,
        outsafe: "on",
        outwarning: "warning",
        outunsafe: "off",
        warning: "5",
        timer: "30",
        debug: "0",
        wires:[["n2"]] },
      { id: "n2", type: "helper" }
    ];
    helper.load(myNode, flow, function () {
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");

      n2.on("input", function (msg) {
        msg.should.have.property('payload', 'on');
        done();
      });
      n1.receive({ payload: 'on' });
    });
  });
  /* */

  it('Should turn on 2 Tx 1', function (done) { // ???
    var cmnds = [];
    var ticks = [];

    var t = 0;
    var c = 0;

    var flow = [
      { id: "n1", type: "mytimeout", name: nom,
        outsafe:    "on",
        outwarning: "warning",
        outunsafe:  "off",
        warning:    "5",
        timer:      "10",
        debug:      "0",
        output:     2,
        wires:[["n2"], ["n3"]] },
      { id: "n2", type: "helper" },
      { id: "n3", type: "helper" }
    ];
    helper.load(myNode, flow, function () {
      var fini = 0;

      var n3 = helper.getNode("n3");
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");

      // Okay the fini++ seems like a good idea but if I get 2 n2 or 2 n3 I might gets a false done
      n2.on("input", function (msg) {
        msg.should.have.property('payload', 'on');
        fini++;
        if(fini > 1) {
          done();
        }
      });

      n3.on("input", function (msg) {
        msg.should.have.property('payload', 10);
        fini++;
        if(fini > 1) {
          done();
        }
      });

      n1.receive({ payload: '1' });
    });
  });
  /* */

  it('Should turn on 2, complex Tx 1', function (done) { // ???
    var cmnds = [];
    var ticks = [];

    var t = 0;
    var c = 0;

    this.timeout(32000); // run timer for 30 plus 2 seconds overrun

    // Node 1:{"id":"n1","type":"mytimeout","_closeCallbacks":[null],"_inputCallbacks":null,"name":"MyTimeout","wires":[["n2"],["n3"]],"_wireCount":2,"timer":5,"state":"stop","warning":2,"outsafe":"on","outwarn":"warning","outunsafe":"off","_events":{},"_eventsCount":1}
    const On  = 'oN';
    const Off = 'oFF';

    var flow = [
      { id: "n1", type: "mytimeout", name: nom,
        outsafe: On, /* If blank we should get no on msg */
        outwarning: "warning",
        outunsafe: Off,
        timer: 5,
        warning: 2,
        debug: "0",
        /* output: 2, */
        wires:[["n2"], ["n3"]] },
      { id: "n2", type: "helper" }, /* Output commands */
      { id: "n3", type: "helper" }  /* Output state of ticks */
    ];

    helper.load(myNode, flow, function () {
      var fini = 0;

      var n2 = helper.getNode("n2");
      var n3 = helper.getNode("n3");
      var n1 = helper.getNode("n1");

      console.log ("Node 1:" + JSON.stringify(n1) +'\n');

      /* * /
      n1.should.have.properties({
        'name':    nom,
        "outunsafe": 'off',
        'timer':   10,   // Defaults
        'warning':   2     // Defaults
      });
      /* */

      // Need to run the n2 & n3 until I get the last command (off) and the last tick.
      n2.on("input", function (msg) {
        console.log("Msg #" + c + ": " + JSON.stringify(msg));
        cmnds[c] = msg;
        console.log("Cmnds[" + c + "]: " + JSON.stringify(cmnds[(c)]) );
        c++;
        // do until payload = 'off'
        if(msg.payload == Off) {
          console.log('\nCmnds: ' + JSON.stringify(cmnds));
          msg.should.have.property('payload', Off);
          //done();
        }
      });

      n3.on("input", function (msg) {
        ticks[t++] = msg;
        //console.log("Tick:  " + JSON.stringify(msg));
        // do until payload = 0
        if(msg.payload == 0) {
          console.log('Ticks: ' + JSON.stringify(ticks));
          msg.should.have.property('payload', 0); // Count down to 0
          done();
        }
      });

      n1.receive({ payload: '1' });
    });
  });
});
<commit_msg>Fixed the complex cmds/ticks test case<commit_after>// https://github.com/ksvan/node-red-contrib-verisure/wiki/Detailed-setup---automated-nodered-test
/*
mosquitto_sub -v -t home/test/switchTimer | awk '{ print strftime("%F_%T.%s"), "" $0; fflush(); }' | tee ${file} # ^Z
bg

mosquitto_pub -t 'home/test/switchTimer' -m '{ "payload": "junk", "timeout" : 4, "warning": 2 }'

2021-01-13_02:26:07.1610522767 home/test/switchTimer { "payload": "junk", "timer" : 4, "warning": 2 }
2021-01-13_02:26:07.1610522767 home/test/switchTimer on
2021-01-13_02:26:35.1610522795 home/test/switchTimer warning
2021-01-13_02:26:37.1610522797 home/test/switchTimer off

You have new mail in /var/mail/njc
(pts/27) njc@mozart:~/dev/git/mytimeout/t/dev-test$ fg
mosquitto_sub -v -t home/test/switchTimer | awk '{ print strftime("%F_%T.%s"), "" $0; fflush(); }' | tee ${file}
^C

*/
"use strict";

const should = require("should");
var   helper = require('node-red-node-test-helper');
var   myNode = require('../mytimeout.js');

helper.init(require.resolve('node-red'));

var nom =  'MyTimeout';

describe('mytimeout Node', function () {

  beforeEach(function (done) {
    helper.startServer(done);
  });

  afterEach(function (done) {
    /* */
    helper.unload();
    helper.stopServer(done);
    /* */
  });

  it('should be loaded', function (done) {
    // select in node-red editor the node to test, then hamburger, then export, then copy to clipboard, then paste here:
    /* */
    var flow1 = [{
      "id":         'n1', // was"abf332d4.4e",
      "type":       "mytimeout",
      "z":          "b431bcd1.51942",
      "name":       nom,
      "outtopic":   "",
      "outsafe":    'on',
      "outwarning": "Warning",
      "outunsafe":  "off",
      "warning":    "5",        // ??? shouldn't this be warning
      "timer":      "30",
      "debug":      false,
      "ndebug":     false,
      "ignoreCase": false,
      "repeat":     false,
      "again":      false,
      "x":          600,
      "y":          840,
      "wires":[
        ["ba562635.2144c8","6b9eec06.608274"],
        ["2b13443d.b2b27c","e1f06422.544ee8"]
      ]
    }];
    /* */
    /*
    Node 1: {
      "id": "n1",
      "type": "mytimeout",
      "z": "b431bcd1.51942",
      "_closeCallbacks": [
        null
      ],
      "_inputCallbacks": null,
      "name": "MyTimeout",
      "wires": [
        [
          "ba562635.2144c8",
          "6b9eec06.608274"
        ],
        [
          "2b13443d.b2b27c",
          "e1f06422.544ee8"
        ]
      ],
      "_wireCount": 4,
      "timer": 30,
      "state": "stop",
      "warning": 5,
      "topic": "",
      "outsafe": "on",
      "outwarn": "Warning",
      "outunsafe": "off",
      "repeat": false,
      "again": false,
      "_events": null,
      "_eventsCount": 1
    }
    */
    var flow = [{ id: "n1", type: "mytimeout", name: nom }];
    // Node 1: {
    //   "id":"n1",
    //   "type":"mytimeout",
    //   "_closeCallbacks":[null],
    //   "_inputCallbacks":null,
    //   "name":"MyTimeout",
    //   "wires":[],
    //   "_wireCount":0,
    //   "timer":30,
    //   "state":"stop",
    //   "warning":5,
    //   "outunsafe":"off",
    //   "_events":{},
    //   "_eventsCount":1
    // }
    helper.load(myNode, flow, function () {
      var n1 = helper.getNode("n1");
      //console.log ("Node 1:" + JSON.stringify(n1));
      n1.should.have.properties({
        'name':    nom,
        "outunsafe": 'off',
        'timer':   30,   // Defaults
        'warning':   5     // Defaults
      });
      //n1.should.not.have.property('outsafe'); // This eventually needs to get there
      done();
    });
  });

  it('Should turn off Tx 0', function (done) {
    var flow = [
      { id: "n1", type: "mytimeout", name: nom, wires:[["n2"]] },
      { id: "n2", type: "helper" }
    ];
    helper.load(myNode, flow, function () {
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");
      n2.on("input", function (msg) {
        msg.should.have.property('payload', 'off');
        done();
      });
      n1.receive({ payload: '0' });
    });
  });
  /* * /
  /* */

  it('Should turn off 2 Tx 0', function (done) { // Passes
    var flow = [
      { id: "n1", type: "mytimeout", name: nom, output: 2, wires:[["n2"], ["n3"]] },
      { id: "n2", type: "helper" },
      { id: "n3", type: "helper" }
    ];
    helper.load(myNode, flow, function () {
      var fini = 0;

      var n3 = helper.getNode("n3");
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");

      // Okay the fini++ seems like a good idea but if I get 2 n2 or 2 n3 I might gets a false done
      n2.on("input", function (msg) {
        msg.should.have.property('payload', 'off');
        fini++;
        if(fini > 1) {
          done();
        }
      });

      n3.on("input", function (msg) {
        msg.should.have.property('payload', 0);
        fini++;
        if(fini > 1) {
          done();
        }
      });

      n1.receive({ payload: '0' });
    });
  });
  /* */

  it('Should turn on with junk, simple Tx junk', function (done) { // Fails
    var flow = [
      { id: "n1", type: "mytimeout", name: nom,
        outsafe:    "on",
        outwarning: "warning",
        outunsafe:  "off",
        warning:    "5",
        timer:      "30",
        debug:      "0",
        wires:[["n2"]] },
      { id: "n2", type: "helper" }
    ];
    helper.load(myNode, flow, function () {
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");

      n2.on("input", function (msg) {
        msg.should.have.property("payload", "on");
        //console.log('Msg: ' + JSON.stringify(msg));
        done();
      });
      n1.receive({ payload: "junk" });
    });
  });
  /* */

  /*
  ** Main output
  ** n2: {"_msgid":"65d8f152.8e917","payload":"on","topic":"","timeout":30}
  ** Ticks output
  ** n3: {"payload":30,"state":1,"flag":"ticks > 0","_msgid":"5e5dd4bf.1be32c"}
  */
  it('Should turn on Tx on', function (done) {
    var flow = [
      { id: "n1", type: "mytimeout", name: nom,
        outsafe: "on",
        outwarning: "warning",
        outunsafe: "off",
        warning: "5",
        timer: "30",
        debug: "0",
        wires:[["n2"]] },
      { id: "n2", type: "helper" }
    ];
    helper.load(myNode, flow, function () {
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");

      n2.on("input", function (msg) {
        msg.should.have.property('payload', 'on');
        done();
      });
      n1.receive({ payload: 'on' });
    });
  });
  /* */

  it('Should turn on 2 Tx 1', function (done) { // ???
    var cmnds = [];
    var ticks = [];

    var t = 0;
    var c = 0;

    var flow = [
      { id: "n1", type: "mytimeout", name: nom,
        outsafe:    "on",
        outwarning: "warning",
        outunsafe:  "off",
        warning:    "5",
        timer:      "10",
        debug:      "0",
        output:     2,
        wires:[["n2"], ["n3"]] },
      { id: "n2", type: "helper" },
      { id: "n3", type: "helper" }
    ];
    helper.load(myNode, flow, function () {
      var fini = 0;

      var n3 = helper.getNode("n3");
      var n2 = helper.getNode("n2");
      var n1 = helper.getNode("n1");

      // Okay the fini++ seems like a good idea but if I get 2 n2 or 2 n3 I might gets a false done
      n2.on("input", function (msg) {
        msg.should.have.property('payload', 'on');
        fini++;
        if(fini > 1) {
          done();
        }
      });

      n3.on("input", function (msg) {
        msg.should.have.property('payload', 10);
        fini++;
        if(fini > 1) {
          done();
        }
      });

      n1.receive({ payload: '1' });
    });
  });
  /* */

  it('Should turn on 2, complex Tx 1', function (done) { // ???
    var cmnds = [];
    var ticks = [];

    var t = 0;
    var c = 0;

    this.timeout(32000); // run timer for 30 plus 2 seconds overrun

    // Node 1:{"id":"n1","type":"mytimeout","_closeCallbacks":[null],"_inputCallbacks":null,"name":"MyTimeout","wires":[["n2"],["n3"]],"_wireCount":2,"timer":5,"state":"stop","warning":2,"outsafe":"on","outwarn":"warning","outunsafe":"off","_events":{},"_eventsCount":1}
    const On  = 'oN';
    const Off = 'oFF';

    var flow = [
      { id: "n1", type: "mytimeout", name: nom,
        outsafe: On, /* If blank we should get no on msg */
        outwarning: "warning",
        outunsafe: Off,
        timer: 5,
        warning: 2,
        debug: "0",
        /* output: 2, */
        wires:[["n2"], ["n3"]] },
      { id: "n2", type: "helper" }, /* Output commands */
      { id: "n3", type: "helper" }  /* Output state of ticks */
    ];

    helper.load(myNode, flow, function () {
      var fini = 0;

      var n2 = helper.getNode("n2");
      var n3 = helper.getNode("n3");
      var n1 = helper.getNode("n1");

      //console.log ("Node 1:" + JSON.stringify(n1) +'\n');

      /* * /
      n1.should.have.properties({
        'name':    nom,
        "outunsafe": 'off',
        'timer':   10,   // Defaults
        'warning':   2     // Defaults
      });
      /* */

      // Need to run the n2 & n3 until I get the last command (off) and the last tick.
      n2.on("input", function (msg) {
        cmnds[c++] = JSON.parse(JSON.stringify(msg)); // Can't just to cmnds[c++] = msg (not a new copy, just a pointer)

        // do until payload = 'off'
        try {
          if(msg.payload == Off) {
            //console.log('\nCmnds: ' + JSON.stringify(cmnds));
            cmnds[0].should.have.property('payload', On);
            cmnds[1].should.have.property('payload', 'warning');
            cmnds[2].should.have.property('payload', Off);
            //done();
          }
        } catch(err) {
          done("Cmnds Err:"  + err);
        }
      });

      n3.on("input", function (msg) {
        ticks[t++] = JSON.parse(JSON.stringify(msg)); // Can't just to ticks[t++] = msg (not a new copy, just a pointer)

        // do until payload = 0
        if(msg.payload == 0) {
          try {
            //console.log('Ticks: ' + JSON.stringify(ticks) + '\nn1.timer: ' + n1.timer);
            var j = 5;
            for(let i = 0; i <= n1.timer ; i++) {
              // These 3 actually don't work ???
              //ticks[i].should.have.property('payload', j--); // Count down to 0
              //ticks[i].should.have.value('payload', j--); // Count down to 0
              ticks[i].payload.should.be.exactly(j--); // Count down to 0
            }
            done();
          } catch(err) {
            console.log("Ticks Err: " + err);
            done(err);
          }
        }
      });

      n1.receive({ payload: '1' });
    });
  });
});
<|endoftext|>


<commit_before>import AuthenticatedRoute from 'kowa/routes/authenticated';

var SitesRoute = AuthenticatedRoute.extend({
  model: function() {
    return this.session.get('currentUser').then(function(currentUser){
      return currentUser.get('sites');
    });
  },

  afterModel: function(sites /* , transition */) {
    this.transitionTo('site', sites.get('firstObject'));
  }
});

export default SitesRoute;
<commit_msg>Fixes redirect when accessing / endpoint<commit_after>import AuthenticatedRoute from 'kowa/routes/authenticated';

var SitesRoute = AuthenticatedRoute.extend({
  model: function() {
    return this.session.get('currentUser').then(function(currentUser){
      return currentUser.get('sites');
    });
  },

  afterModel: function(sites, transition, queryParams) {
    // catch when accessing "/" endpoint
    if (!transition.params.site) {
      // redirects to first site
      // @todo Handle case when user have no site yet !
      this.transitionTo('site', sites.get('firstObject'));
    }
  }
});

export default SitesRoute;
<|endoftext|>


<commit_before>// NODE ENVIRONMENT

var websocketStream = require('websocket-stream')
var ws = require('ws').Server

var readdir = require('fs').readdir
var http = require('http')
var filed = require('filed')

var Map = require('./_map')
var Compiler = require('./_cmp')
var level = require('level')

var Bricoleur = require('./_brico')

module.exports = Environment

function Environment (opts, running) {
  if (opts.path_data[(opts.path_data.length-1)] !== '/') opts.path_data += '/'
  if (opts.path_static[(opts.path_static.length-1)] !== '/') opts.path_static += '/'
  if (opts.path_wilds[(opts.path_wilds.length-1)] !== '/') opts.path_wilds += '/'

  var Self = this
  var StaticFiles = {}
  var Data

  var _ = {} // brico scope container

  // CONFIGURATION

  var CompileOpts = {
    path_wilds:opts.path_wilds,
    path_styl:opts.path_styl,
    path_css:opts.path_css,
    path_bundle:opts.path_bundle,
    path_env:opts.path_js,
    compress:false
  }
  var MapOpts = {
    path_wilds:opts.path_wilds
  }

  // HTTP SERVER FOR STATIC FILES

  readdir(opts.path_static, function GetStaticFiles (e, files) {
    if (e) console.error(e)
    files.forEach(function findStaticFiles (file) {
      StaticFiles[file] = opts.path_static+file
    })
  })

  var Server = http.createServer(HandleRequests)

  function HandleRequests (req, res) {
    var url = req.url
    if (url === '/') url = '/index.html'
    var file = url.replace('/','')
    if (StaticFiles[file]) filed(StaticFiles[file]).pipe(res)
    if (!StaticFiles[file]) res.end() // todo: somekindof 404
  }

  Server.listen(opts.port, function () {
    var uid = parseInt(process.env.SUDO_UID)
    if (uid) process.setuid(uid) // switch to user permissions
    Data = level(opts.path_data+'env') // wait until user permissions are active
    running()
  })

  // WEBSOCKET CONNECTIONS

  var WebSocket = new ws({server:Server})

  WebSocket.on('connection', HandleSoc)

  function HandleSoc (soc) { // fix this thing!
    var ws = websocketStream(soc)
    var headers = soc.upgradeReq.headers
    var key = headers['sec-websocket-key']
    if (headers['sec-websocket-key1']) key = headers['sec-websocket-key1'].replace(/\s/g,'-')
    var host = headers.host

    _[host].addSocket(key)

    ws.pipe(_[host][key]).pipe(ws)
  }

  // API LAYERS

  this.loadEnvironment = function (loaded) {
    var bricoStream = Data.createValueStream()
    bricoStream.on('data', function (d) {
      var brico = JSON.parse(d)
      _[brico.host] = new Bricoleur()
      _[brico.host]['data'] = level(opts.path_data+brico.host)
    })
    bricoStream.on('end', function () {
      loaded()
    })

    var _cmp = new Compiler(CompileOpts)

    var _map = new Map(MapOpts, function (s) {// map wilds
      // add map to bricos stored in env db
      s.end = false
      s.pipe(_cmp.s)
      for (brico in _) {
        _cmp.s.pipe(_[brico].metaStream)
      }
      s.on('end', function () {
        console.log('map of '+opts.path_wilds+' complete!')
      })
    })
  }

  this.createBrico = function (user, cb) {
    // crete and attach a data instance per brico
    Data.put(user.host, JSON.stringify(user), function (e) {
      if (e) console.error(e)
      cb()
    })
  }
}
<commit_msg>experimental api impelementation<commit_after>// NODE ENVIRONMENT

var websocketStream = require('websocket-stream')
var ws = require('ws').Server

var readdir = require('fs').readdir
var http = require('http')
var filed = require('filed')

var map = require('./_map')
var cmp = require('./_cmp')
var level = require('level')

var Bricoleur = require('./_brico')

module.exports = Environment

function Environment (opts, running) {
  if (opts.path_data[(opts.path_data.length-1)] !== '/') opts.path_data += '/'
  if (opts.path_static[(opts.path_static.length-1)] !== '/') opts.path_static += '/'
  if (opts.path_wilds[(opts.path_wilds.length-1)] !== '/') opts.path_wilds += '/'

  var Self = this
  var StaticFiles = {}
  var Data

  var _ = {} // brico scope container

  // CONFIGURATION

  var CompileOpts = {
    path_wilds:opts.path_wilds,
    path_styl:opts.path_styl,
    path_css:opts.path_css,
    path_bundle:opts.path_bundle,
    path_env:opts.path_js,
    compress:false
  }
  var MapOpts = {
    path_wilds:opts.path_wilds
  }
  var Map = new map(MapOpts, function (s) {// map wilds
    var compiler = new cmp(CompileOpts)
    s.pipe(compiler.s)
    s.on('end', function () {
      console.log('map of '+opts.path_wilds+' complete!')
    })
  })

  // HTTP SERVER FOR STATIC FILES

  readdir(opts.path_static, function GetStaticFiles (e, files) {
    if (e) console.error(e)
    files.forEach(function findStaticFiles (file) {
      StaticFiles[file] = opts.path_static+file
    })
  })

  var Server = http.createServer(HandleRequests)

  function HandleRequests (req, res) {
    var url = req.url
    if (url === '/') url = '/index.html'
    var file = url.replace('/','')
    if (StaticFiles[file]) filed(StaticFiles[file]).pipe(res)
    if (!StaticFiles[file]) res.end() // todo: somekindof 404
  }

  Server.listen(opts.port, function () {
    var uid = parseInt(process.env.SUDO_UID)
    if (uid) process.setuid(uid) // switch to user permissions
    Data = level(opts.path_data+'env') // wait until user permissions are active
    running()
  })

  // WEBSOCKET CONNECTIONS

  var WebSocket = new ws({server:Server})

  WebSocket.on('connection', HandleSoc)

  function HandleSoc (soc) { // fix this thing!
    var ws = websocketStream(soc)
    var headers = soc.upgradeReq.headers
    var key = headers['sec-websocket-key']
    if (headers['sec-websocket-key1']) key = headers['sec-websocket-key1'].replace(/\s/g,'-')
    var host = headers.host

    _[host].addSocket(key)

    ws.pipe(_[host][key]).pipe(ws)
  }

  // API LAYERS

  this.api = through(APIwrite, APIend, {autoDestroy:false})

  function APIwrite (chunk) {
    console.log(chunk)
    var cmd = chunk[0]
    var params = chunk[2]

    API[cmd](params)
  }

  function APIend () {}

  var API = {
    load: function (loaded) {
      var streamBricos = Data.createValueStream()
      streamBricos.on('data', function (d) {
        _[brico.host] = new Bricoleur()
        _[brico.host].data = level(opts.path_data+brico.host)
      })
      streamBricos.on('end', loaded)
    },
    createBrico: function (brico, created) {
      Data.put(brico.host, brico, created)
    }
  }
}
<|endoftext|>


<commit_before>var locastyle = locastyle || {};

locastyle.popover = (function() {
  'use strict';

  var config = {
    container    : 'body',
    hoverEvent   : 'mouseenter.ls.popover',
    idPopover    : '#ls-popover-',
    module       : '[data-ls-module="popover"]',
    placement    : 'top',
    trigger      : 'click.ls.popover',
    popoverClass : 'ls-popover',
    uniqueId     : 0
  }

  function init() {
    if(/sm|xs/.test(locastyle.breakpointClass)){
      $(config.module).attr('data-ls-module', 'modal').removeAttr('data-trigger');
      locastyle.modal.init();
    } else{
      $(config.module).each(function  (index, elem) {
        createPopover($(elem));
      });
    }
    updateBreakpoint();
  }

  function updateBreakpoint (argument) {
    $(window).on("breakpoint-updated", function () {
      destroy();
      init();
    });
  }

  function createPopover ($elem) {
    var elementData = $elem.data(),
        width  = $elem.outerWidth(),
        height = $elem.outerHeight();
    $elem.data('uniqueId', config.uniqueId);
    elementData.position  = elementData.container ? $elem.position() : $elem.offset() ;
    elementData.container = elementData.container || config.container;
    elementData.placement = elementData.placement || config.placement;
    setPositionData(elementData, width, height);
    elementData.uniqueId = config.uniqueId++;
    $(elementData.container).append(locastyle.templates.popover(elementData));
    bindActions($elem, elementData, width, height);
  }

  function setPositionData(elementData, width, height) {
    switch (elementData.placement) {
      case 'top':
        elementData.position.top -=  12;
        elementData.position.left +=  (width/2 + 4);
        break;
      case 'right':
        elementData.position.top +=  (height/2 -2);
        elementData.position.left += (width + 12);
        break;
      case 'bottom':
        elementData.position.top += (height + 12);
        elementData.position.left +=  (width/2 + 4);
        break;
      case 'left':
        elementData.position.top +=  (height/2 -2 );
        elementData.position.left -= 12;
    }
  }

  function updateElementPosition($popover, elementData) {
    $popover.css("top", elementData.position.top).css("left", elementData.position.left);
  }

  function bindActions ($elem, elementData, width, height) {
    var trigger = elementData.trigger == 'hover' ? config.hoverEvent : config.trigger,
        $popover = $(config.idPopover + elementData.uniqueId);
    if(trigger === config.hoverEvent){
      $elem.on({
        mouseenter: function (event) {
          event.preventDefault();
          elementData.position = $(this).offset() ;
          setPositionData(elementData, width, height);
          updateElementPosition($popover, elementData);
          $popover.stop().show();
        },
        mouseleave: function (event) {
          event.preventDefault();
          $popover.stop().hide();
        }
      });
    } else {
      $elem.on({
        click: function (event) {
          event.preventDefault();
          event.stopPropagation();
          elementData.position = $(this).offset() ;
          setPositionData(elementData, width, height);
          updateElementPosition($popover, elementData);
          $popover.stop().toggle();
        }
      });
      $(document).on('click', function (event) {
        var element = event.toElement;
        if(!$(element).parents().hasClass( config.popoverClass )){
         $('.' + config.popoverClass).hide();
        }
      });
    }
  }

  function destroy() {
    $('.' + config.popoverClass).remove();
    $(config.module).each(function  (index, elem) {
      $(elem)
        .removeData('uniqueId')
        .off(config.hoverEvent)
        .off(config.trigger);
    });
  }

  return {
    init: init,
    destroyPopover: destroy
  }

}());
<commit_msg>Missing semicolon.<commit_after>var locastyle = locastyle || {};

locastyle.popover = (function() {
  'use strict';

  var config = {
    container    : 'body',
    hoverEvent   : 'mouseenter.ls.popover',
    idPopover    : '#ls-popover-',
    module       : '[data-ls-module="popover"]',
    placement    : 'top',
    trigger      : 'click.ls.popover',
    popoverClass : 'ls-popover',
    uniqueId     : 0
  };

  function init() {
    if(/sm|xs/.test(locastyle.breakpointClass)){
      $(config.module).attr('data-ls-module', 'modal').removeAttr('data-trigger');
      locastyle.modal.init();
    } else{
      $(config.module).each(function  (index, elem) {
        createPopover($(elem));
      });
    }
    updateBreakpoint();
  }

  function updateBreakpoint (argument) {
    $(window).on("breakpoint-updated", function () {
      destroy();
      init();
    });
  }

  function createPopover ($elem) {
    var elementData = $elem.data(),
        width  = $elem.outerWidth(),
        height = $elem.outerHeight();
    $elem.data('uniqueId', config.uniqueId);
    elementData.position  = elementData.container ? $elem.position() : $elem.offset() ;
    elementData.container = elementData.container || config.container;
    elementData.placement = elementData.placement || config.placement;
    setPositionData(elementData, width, height);
    elementData.uniqueId = config.uniqueId++;
    $(elementData.container).append(locastyle.templates.popover(elementData));
    bindActions($elem, elementData, width, height);
  }

  function setPositionData(elementData, width, height) {
    switch (elementData.placement) {
      case 'top':
        elementData.position.top -=  12;
        elementData.position.left +=  (width/2 + 4);
        break;
      case 'right':
        elementData.position.top +=  (height/2 -2);
        elementData.position.left += (width + 12);
        break;
      case 'bottom':
        elementData.position.top += (height + 12);
        elementData.position.left +=  (width/2 + 4);
        break;
      case 'left':
        elementData.position.top +=  (height/2 -2 );
        elementData.position.left -= 12;
    }
  }

  function updateElementPosition($popover, elementData) {
    $popover.css("top", elementData.position.top).css("left", elementData.position.left);
  }

  function bindActions ($elem, elementData, width, height) {
    var trigger = elementData.trigger == 'hover' ? config.hoverEvent : config.trigger,
        $popover = $(config.idPopover + elementData.uniqueId);
    if(trigger === config.hoverEvent){
      $elem.on({
        mouseenter: function (event) {
          event.preventDefault();
          elementData.position = $(this).offset() ;
          setPositionData(elementData, width, height);
          updateElementPosition($popover, elementData);
          $popover.stop().show();
        },
        mouseleave: function (event) {
          event.preventDefault();
          $popover.stop().hide();
        }
      });
    } else {
      $elem.on({
        click: function (event) {
          event.preventDefault();
          event.stopPropagation();
          elementData.position = $(this).offset() ;
          setPositionData(elementData, width, height);
          updateElementPosition($popover, elementData);
          $popover.stop().toggle();
        }
      });
      $(document).on('click', function (event) {
        var element = event.toElement;
        if(!$(element).parents().hasClass( config.popoverClass )){
         $('.' + config.popoverClass).hide();
        }
      });
    }
  }

  function destroy() {
    $('.' + config.popoverClass).remove();
    $(config.module).each(function  (index, elem) {
      $(elem)
        .removeData('uniqueId')
        .off(config.hoverEvent)
        .off(config.trigger);
    });
  }

  return {
    init: init,
    destroyPopover: destroy
  };

}());
<|endoftext|>


<commit_before>const chai = require('chai');
const assert = chai.assert;

var Board = require('../lib/board')
var Square = require('../lib/square')
var Piece = require('../lib/piece')

describe('Board', function () {
  it('should instantiate a new board', function () {
    let board = new Board ();
    assert.isObject(board);
  });

  it('should know the canvas it is built on', function () {
    let board = new Board ('context', 'canvas');
    assert.equal(board.canvas, 'canvas')
  })

  it('should know the context it is built in', function () {
    let board = new Board ('context', 'canvas');
    assert.equal(board.context, 'context')
  })

  it('should know when the game is over', function () {
    let board = new Board ();
    assert.equal(board.gameOver, false)
  });

  it('should return an array of pieces that can move to a given square', function () {
    let board = new Board ();
    let square = new Square (board, 4, 4);
    let piece = new Piece (square, "black");
    square.piece = piece;
    board.squares.push(square);
    var legalPieces = board.canMoveHere(square);
    assert.include(legalPieces, piece);
  });
});
<commit_msg>Adds functionality for piece count.<commit_after>const chai = require('chai');
const assert = chai.assert;

var Board = require('../lib/board')
var Square = require('../lib/square')
var Piece = require('../lib/piece')

describe('Board', function () {
  it('should instantiate a new board', function () {
    let board = new Board ();
    assert.isObject(board);
  });

  it('should know the canvas it is built on', function () {
    let board = new Board ('context', 'canvas');
    assert.equal(board.canvas, 'canvas')
  })

  it('should know the context it is built in', function () {
    let board = new Board ('context', 'canvas');
    assert.equal(board.context, 'context')
  })

  it('should know when the game is over', function () {
    let board = new Board ();
    assert.equal(board.gameOver, false)
  });

  it('should return an array of pieces that can move to a given square', function () {
    let board = new Board ();
    let square = new Square (board, 4, 4);
    let piece = new Piece (square, "black");
    square.piece = piece;
    board.squares.push(square);
    var legalPieces = board.canMoveHere(square);
    assert.include(legalPieces, piece);
  });

  it('knows how many pieces are on the board', function () {
    let board = new Board ();
    let square = new Square (board, 4, 4);
    let piece = new Piece (square, "black");
    square.piece = piece;
    let squareTwo = new Square (board, 4, 6);
    let pieceTwo = new Piece (squareTwo, "white");
    squareTwo.piece = pieceTwo;
    board.squares.push(square);
    board.squares.push(squareTwo);

    assert.equal(board.pieceCount(), 2);
  });
});
<|endoftext|>


<commit_before>// Core Node.js modules.
var fs = require('fs');
var path = require('path');
var zlib = require('zlib');
var exec = require('child_process').exec;

// Third-party modules.
var Q = require('q');
var request = require('request');
var tar = require('tar');
var which = require('which');
var rimraf = require('rimraf');

// This will take in an object and find any matching keys in the environment
// to use as overrides.
//
// ENV variables:
//
// PKG: Location of `package.json` sans `.json`.
// LIBGIT2: Location of libgit2 source.
// BUILD: Location of nodegit build directory.
function envOverride(obj) {
  // Look through all keys.
  return Object.keys(obj).reduce(function(obj, key) {
    var normalize = key.toUpperCase();

    // Check for process environment existence.
    if (normalize in process.env) {
      obj[key] = process.env[normalize];
    }

    return obj;
  }, obj);
}

// Convert to the correct system path.
function systemPath(parts) {
  return parts.join(path.sep);
}

// Will be used near the end to configure `node-gyp`.
var python, cmake;

// Common reusable paths that can be overwritten by environment variables.
var paths = envOverride({
  pkg: __dirname + '/package',
  libgit2: __dirname + '/vendor/libgit2/',
  build: __dirname + '/vendor/libgit2/build/',
});

// Load the package.json.
var pkg = require(paths.pkg);

// Ensure all dependencies are available.
var dependencies = Q.allSettled([
  // This will prioritize `python2` over `python`, because we always want to
  // work with Python 2.* if it's available.
  Q.nfcall(which, 'python2'),
  Q.nfcall(which, 'python'),

  // Check for any version of CMake.
  Q.nfcall(which, 'cmake'),
])

// Determine if all the dependency requirements are met.
.then(function(results) {
  console.info('[nodegit] Determining dependencies.');

  // Assign to reusable variables.
  python = results[0].value || results[1].value;
  cmake = results[2].value;

  // Missing Python.
  if (!python) {
    throw new Error('Python is required to build libgit2.');
  }

  // Missing CMake.
  if (!cmake) {
    throw new Error('CMake is required to build libgit2.');
  }

  // Now lets check the Python version to ensure it's < 3.
  return Q.nfcall(exec, python + ' --version').then(function(version) {
    if (version[1].indexOf('Python 3') === 0) {
      throw new Error('Incorrect version of Python, gyp requires < 3.');
    }
  });
})

// Display a warning message about missing dependencies.
.fail(function(message) {
  console.info('[nodegit] Failed to build nodegit.');
  console.info(message);

  throw new Error(message);
})

// Successfully found all dependencies.  First step is to clean the vendor
// directory.
.then(function() {
  console.info('[nodegit] Removing vendor/libgit2.');

  return Q.ninvoke(rimraf, null, paths.libgit2);
})

// Now fetch the libgit2 source from GitHub.
.then(function() {
  console.info('[nodegit] Fetching vendor/libgit2.');

  var url = 'https://github.com/libgit2/libgit2/tarball/'+ pkg.libgit2;

  var extract = tar.Extract({
    path: paths.libgit2,
    strip: true
  });

  // First extract from Zlib and then extract from Tar.
  var expand = request.get(url).pipe(zlib.createUnzip()).pipe(extract);

  return Q.ninvoke(expand, 'on', 'end');
})

// Fetch completed successfully.
.then(function() {
  console.info('[nodegit] Creating vendor/libgit2/build.');

  return Q.ninvoke(fs, 'mkdir', paths.build);
})

// Configure libgit2.
.then(function() {
  console.info('[nodegit] Configuring libgit2.');

  var flags = '-DTHREADSAFE=1 -DBUILD_CLAR=0';

  // Windows flags.
  if (process.platform.indexOf("win") > -1) {
    flags = '-DSTDCALL=OFF -DBUILD_CLAR=OFF -DTHREADSAFE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_C_FLAGS=-fPIC -DCMAKE_BUILD_TYPE=RelWithDebInfo';
  }

  return Q.nfcall(exec, 'cmake .. ' + flags, {
    cwd: paths.build
  });
}).fail(function(err) {
  console.error(err);
})

// Build libgit2.
.then(function() {
  console.info('[nodegit] Building libgit2.');

  return Q.nfcall(exec, 'cmake --build .', {
    cwd: paths.build
  });
})

// Configure the Node native module.
.then(function() {
  console.info('[nodegit] Configuring native node module.');

  return Q.nfcall(exec, systemPath([
    '.', 'node_modules', '.bin', 'node-gyp configure --python ' + python
  ]), {
    cwd: '.'
  });
})

.then(function() {
  console.info('[nodegit] Building native node module.');

  return Q.nfcall(exec, systemPath([
    '.', 'node_modules', '.bin', 'node-gyp build'
  ]), {
    cwd: '.'
  });
})

// Display a warning message about failing to build native node module.
.fail(function(message) {
  console.info('[nodegit] Failed to build nodegit.');
  console.info(message.message);
  console.info(message.stack);

  throw new Error(message);
})

.then(function() {
  console.info('[nodegit] Completed installation successfully.');
});
<commit_msg>Improve the installation flow.<commit_after>// Core Node.js modules.
var fs = require('fs');
var path = require('path');
var zlib = require('zlib');
var exec = require('child_process').exec;

// Third-party modules.
var Q = require('q');
var request = require('request');
var tar = require('tar');
var which = require('which');
var rimraf = require('rimraf');

// This will take in an object and find any matching keys in the environment
// to use as overrides.
//
// ENV variables:
//
// PKG: Location of `package.json` sans `.json`.
// LIBGIT2: Location of libgit2 source.
// BUILD: Location of nodegit build directory.
function envOverride(obj) {
  // Look through all keys.
  return Object.keys(obj).reduce(function(obj, key) {
    var normalize = key.toUpperCase();

    // Check for process environment existence.
    if (normalize in process.env) {
      obj[key] = process.env[normalize];
    }

    return obj;
  }, obj);
}

// Convert to the correct system path.
function systemPath(parts) {
  return parts.join(path.sep);
}

// Will be used near the end to configure `node-gyp`.
var python, cmake;

// Common reusable paths that can be overwritten by environment variables.
var paths = envOverride({
  pkg: __dirname + '/package',
  libgit2: __dirname + '/vendor/libgit2/',
  build: __dirname + '/vendor/libgit2/build/',
});

// Load the package.json.
var pkg = require(paths.pkg);

// Ensure all dependencies are available.
var dependencies = Q.allSettled([
  // This will prioritize `python2` over `python`, because we always want to
  // work with Python 2.* if it's available.
  Q.nfcall(which, 'python2'),
  Q.nfcall(which, 'python'),

  // Check for any version of CMake.
  Q.nfcall(which, 'cmake'),
])

// Determine if all the dependency requirements are met.
.then(function(results) {
  console.info('[nodegit] Determining dependencies.');

  // Assign to reusable variables.
  python = results[0].value || results[1].value;
  cmake = results[2].value;

  // Missing Python.
  if (!python) {
    throw new Error('Python is required to build libgit2.');
  }

  // Missing CMake.
  if (!cmake) {
    throw new Error('CMake is required to build libgit2.');
  }

  // Now lets check the Python version to ensure it's < 3.
  return Q.nfcall(exec, python + ' --version').then(function(version) {
    if (version[1].indexOf('Python 3') === 0) {
      throw new Error('Incorrect version of Python, gyp requires < 3.');
    }
  });
})

// Successfully found all dependencies.  First step is to clean the vendor
// directory.
.then(function() {
  console.info('[nodegit] Removing vendor/libgit2.');

  return Q.ninvoke(rimraf, null, paths.libgit2);
})

// Now fetch the libgit2 source from GitHub.
.then(function() {
  console.info('[nodegit] Fetching vendor/libgit2.');

  var url = 'https://github.com/libgit2/libgit2/tarball/' + pkg.libgit2;

  var extract = tar.Extract({
    path: paths.libgit2,
    strip: true
  });

  // First extract from Zlib and then extract from Tar.
  var expand = request.get(url).pipe(zlib.createUnzip()).pipe(extract);

  return Q.ninvoke(expand, 'on', 'end');
})

// Fetch completed successfully.
.then(function() {
  console.info('[nodegit] Creating vendor/libgit2/build.');

  return Q.ninvoke(fs, 'mkdir', paths.build);
})

// Configure libgit2 using cmake.
.then(function() {
  console.info('[nodegit] Configuring libgit2.');

  // Minimum flags necessary to configure in sane environments.
  var flags = ['-DTHREADSAFE=ON', '-DBUILD_CLAR=OFF'];

  // Windows flags.
  if (process.platform.indexOf('win') > -1) {
    flags.push.apply(flags, [
      '-DSTDCALL=OFF',
      '-DBUILD_SHARED_LIBS=OFF',
      '-DCMAKE_C_FLAGS=-fPIC',
      '-DCMAKE_BUILD_TYPE=RelWithDebInfo'
    ]);
  }

  return Q.nfcall(exec, 'cmake .. ' + flags.join(' '), {
    cwd: paths.build
  });
})

// Build libgit2 using cmake.
.then(function() {
  console.info('[nodegit] Building libgit2.');

  return Q.nfcall(exec, 'cmake --build .', {
    cwd: paths.build
  });
})

// Configure the native module using node-gyp.
.then(function() {
  console.info('[nodegit] Configuring native node module.');

  return Q.nfcall(exec, systemPath([
    '.', 'node_modules', '.bin', 'node-gyp configure --python ' + python
  ]), {
    cwd: '.'
  });
})

// Build the native module using node-gyp.
.then(function() {
  console.info('[nodegit] Building native node module.');

  return Q.nfcall(exec, systemPath([
    '.', 'node_modules', '.bin', 'node-gyp build'
  ]), {
    cwd: '.'
  });
})

// Display a success message.
.then(function() {
  console.info('[nodegit] Completed installation successfully.');
})

// Display a warning message about failing to build native node module.
.fail(function(message) {
  console.info('[nodegit] Failed to build nodegit.');
  console.info(message.message);
  console.info(message.stack);
});
<|endoftext|>


<commit_before>'use strict';
/* jshint devel:true */
//console.log('\'Allo \'Allo!');
<commit_msg>Basic data for filter controls<commit_after>'use strict';
/* jshint devel:true */
//console.log('\'Allo \'Allo!');

var filter = {
    'Human Development Index':['Very high human development','High human development', 'Medium human development', 'Low human development'],
    'Population':['high population','very high population','upper medium population','lower medium population','low population','very low population'],
    'FOAI Exists':['All', 'YES' , 'NO'],
    'System of internal governance':['Unitary state','Unitary monarchy','Federal state','Regionalised unitary state','Regionalised unitary monarchy'],
    'System of governance':['Full presidential system','Parliamentary republic','Semi-presidential system','Constitutional monarchy with ceremonial monarch','Full presidential system with a prime minister','Constitutional monarchy with active monarch','Mixed republican system','Absolute monarchy','Single Party States','Transitional states','Theocracy','Directorial system','Military junta'],
    'Fragile State':['All', 'YES' , 'NO'],
    'OGP Senior leadership':['All', 'YES' , 'NO'],
    'g20 member':['All', 'YES' , 'NO'],
    'g7 member':['All', 'YES' , 'NO'],
    'World bank lending group':['High-income economies ($12,616 or more)','Upper-middle-income economies ($4,086 to $12,615)','Lower-middle-income economies ($1,036 to $4,085)','Low-income-economies ($ 1.035 or less)'],
    'Region':['Europe','North America','Middle America & Caribbean','South America','Middle East and North Africa','Sub-Saharan Africa','Central Asia','East Asia and Pacific','South Asia'],
    'Languages':['Afrikaans','Albanian','Amharic','Arabic','Armenian','Aymara','Azerbaijani','Belarusian','Bengali','Bislama','Bosnian','Bulgarian','Burmese','Cantonese','Carolinian','Catalan','Chamorro','Chewa','Chichewa','Chinese','Comorian','Coptic','Croatian','Czech','Danish','Dari','Dhiwehi','Dutch','Dzongkha','English','Estonian','Faroese','Fijian','Filipino','Finnish','French','Fula','Georgian','German','Greek','Guaraní','Guernésiais','Gujarati','HaitianCreole','Hausa','Hebrew','Hindi','HiriMoto','Hungarian','Icelandic','Igbo','Indonesian','Irish','Italian','Japanese','Jèrriais','Kalasllisut','Kannada','Kazakh','Khmer','Kinyarwanda','Kirghiz','Kiribati','Kirundi','Korean','Kosraean','Kurdish','Lao','Latin','Latvian','Lithuanian','Luxembourgish','Macedonian','Malagasy','Malay','Malayalam','Malaysian','Maltese','Mandarin','Manx','Maori','Marathi','Marshallese','Mongolian','Montenegrin','Nauruan','Nepali','Niuean','Norwegian','Orija','Oromo','Palauan','Papiamento','Pashto','Persian','Polish','Portuguese','Punjabi','Quechua','Romanian','Romansh','Russian','Samoan','Scots','Scottish Gaelic','Serbian','Shona','Sinhala','Slovak','Slovene','Somali','Sotho','Spanish','Swahili','Swazi','Swedish','Taiwanese','Tajik','Tamazight','Tamil','Tetum','Thai','Tigrinya','TokPisin','Tokelauan','Tongan','Turkish','Turkmen','Tuvaluan','Ukrainian','Urdu','Uzbek','Vietnamese','WestFrisian','Xhosa','Yoruba','Zulu']
}

// // TODO: Check validity of region and language data
// High-income economies ($12,616 or more) - 44
// Upper-middle-income economies ($4,086 to $12,615) - 32
// Lower-middle-income economies ($1,036 to $4,085) - 28
// Low-income-economies ($ 1.035 or less) - 22
<|endoftext|>


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

 For Best results use the an 'app-config.json' file. This File should be
 located in the same directory as this file. If you choose not to use it
 then your application must run out of the same directory as this file
 and you entry point must be a file named 'start.js' located in this
 directory.

 'app-config.json' allows you to configure following properties for your
 application:

"applicationName:" <name of the application>
 "applicationDirectory": <set this to the directory you application lives in>
 "appEntry": <set this to the name of the 'js' file that is your entry point>

 "pullPort": <set this to the port for a pull requests> - defaults to 8000

 // The key and cert files are only necessary if you want to listen for a pull
 // request securely. If they are omitted and HTTP server is start instead. Beware
 // as someone could be snooping and then start sending your servers pull requests
 "pullKey": <path to a ssh key file for the HTTPS Server>
 "pullCert": <path to a ssh cert file for the HTTPS Server>
 "pullCa": <array of paths to the certificate authority files> (optional)
 "pullPassphrase" : <string - phrase that the certificate was generated with> (optional if certificate was not generated with a passphrase)

 // This is a secret key that is configured here and passed in via a webhook in
 // response to a pull request. This is to prevent unauthorized requests from causing
 // pulls. If no pull secret is configure then all pull request are valid
 "pullSecret": <secret phrase>

 "pullBranch": <git branch to use for the pull>

 // In theory you can put an cloud vendor specific params in here. You just have to have support in cloud.js for them.
 // Curently AWS is the only cloud platform supported
 // Put your AWS config params in here. Example:
 "accessKeyId": "XXXXXXXXXXXXXXXXXXXX",
 "secretAccessKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
 "region": "us-east-1"

 "sudo": <Mac and Linux only, should we prefix all shell commands with sudo?> - defaults to no sudo

 // To Trigger a pull and restart

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

(function (){
    var fs = require ('fs');
    var exec = require('child_process').exec;
    var path = require('path');
    var url = require('url');
    var qs = require ('querystring');
    var config_file, config, error, pull_error = "";
    var package_json, package_copy, parsed_package, parsed_copy;
    var restart = true;
    var need_restart = false;
    var http = require('http');
    var https = require('https');
    // This an abstraction layer for different cloud services
    // all AWS specific code or other cloud vendor stuff should go in here
    var cloud = require ("./cloud.js");
    var updating_on = false;
    var sudo;
    var instance_data;

    // post a command out
    function post (url, body, port, secure, path, cb){
        var qs = require('querystring');
        body = qs.stringify (body);
        var options = {
            host: url,
            port: port,
            path: path,
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': body.length
            },
            rejectUnauthorized:false // add this so if someone uses a local certificate on the machine the post will still go through
        };

        var server = (secure) ? https : http;
        var req = server.request(options, function(res) {
            var result = "";
            //console.log('STATUS: ' + res.statusCode);
            //console.log('HEADERS: ' + JSON.stringify(res.headers) + '\n');
            res.setEncoding('utf8');
            res.on('data', function (chunk) {result += chunk;});
            res.on('end', function (){
                cb (null, result);
            });
        });
        req.on('error', function(e) {
            console.log('problem with request: ' + e.message);
            cb (e.message);
        });

        // write data to request body
        req.write(body);
        req.end();
    }

    // pull the latest source
    function pull(cb, master, req){
        pull_error = "";
        function _pull (cb){
            console.log ("\nPulling the latest code from remote repository");
            // get the latest code
            var branch = config.branch || "master"; // defaults to master
            var child = exec (sudo + "git pull origin " + branch, function (err, std, ster){
                if (err){
                    console.log ("	Error pulling reposititory. Error" + ster);
                    pull_error += "\nError pulling reposititory. Error" + ster;
                }
                else{console.log ("	" + std);}
                cb && cb ();
            });
        }
        // only pull the latest if in the cloud. For local development don't do anything. The developer must manually pull
        if (cloud.isCloud ()){
            restart = (master || master === false);
            need_restart = false;
            if (!master){
                _pull (function (){
                    if (need_restart){
                        process.exit(0);
                    }
                    cb && cb ();
                });
            }
            else { // else we are the master so find all the other AWS instances to pull from
                // get other instances that our are same type and already running
                var secure = (req.href.search ("https://") !== -1);
                var instances = cloud.getInstances (function (instances){
                    instances && instances.forEach (function (instance){
                        if (instance.dns && instance.id !== cloud.getInstanceId ()){ // don't signal ourselves
                            post (instance.dns, req,body, config.pullPort, secure, url.format (req.query));
                        }
                    });
                    // now pull and restart ourselves
                    _pull (function (){
                        if (need_restart){
                            process.exit(0);
                        }
                        cb && cb ();
                    });
                });
            }
        }
        else {cb && cb ();}
    }
    // check if any NPM dependencies changed
    function checkNodeDependencies (cb){
        // read in our files
        console.log ("\nChecking for Node version changes");
        try { package_copy = fs.readFileSync ("package.copy");}
        catch (e) { package_copy = null;}
        try {package_json = fs.readFileSync ("package.json");}
        catch (e) { package_json = null;}
        parsed_package = (package_json) ? JSON.parse (package_json) : null;
        parsed_copy = (package_copy) ? JSON.parse (package_copy) : null;
        // see if our node versions match
        if (parsed_package && parsed_package.node_version){
            var version = parsed_package.node_version.replace ('v', "");
            var node_version = process.version.replace ('v', "");
            if (version !== node_version){
                console.log ("	Upgrading Node");
                console.log ("		current version:" + node_version);
                console.log ("		requested version:" + version);
                // upgrade node using 'n'
                var child = exec (sudo + "n " + version, function (err, std, ster){
                    if (err){
                        console.log ("		Node upgrade failed. Error:" + ster);
                        pull_error += "\nNode upgrade failed. Error:" + ster;
                    }
                    else{
                        console.log ("		Node upgrade success, restarting");
                        if (restart){ process.exit (0); }// exit so we get restarted
                        else { need_restart = true;}
                    }
                    cb & cb ();
                });
            }
            else{
                console.log ("  Node is up to date");
                console.log ("      current version:" + node_version);
                cb & cb ();
            }
        }
        else{
            console.log ("	Current Node version is:" + node_version);
            cb & cb ();
        }
    }

    // check for any node module changes and reinstall the associated packages.
    // NPM doesn't do a good job of keeping track. So keep a copy of the last successful
    // update and compare it. Find ones that have changed and delete them and the
    // re-install.
    function checkNPMDependencies (cb){
        function deleteRecursiveSync(itemPath) {
            if (fs.existsSync(itemPath)){
                if (fs.existsSync(itemPath) && fs.statSync(itemPath).isDirectory()) {
                    fs.readdirSync(itemPath).forEach(function(childItemName) {
                        deleteRecursiveSync(path.join(itemPath, childItemName));
                    });
                    fs.rmdirSync(itemPath);
                } else {
                    fs.unlinkSync(itemPath);
                }
            }
        }
        console.log ("\nChecking for Node Module dependency changes");
        if (!package_json){
            console.log ("WARNING Your Application has no 'package.json' . It is highly" +
                " recommended that you use one to manage your NPM dependencies");
        }
        else{ // delete the module that have changed and re-install with new versions
            if (!package_copy || package_copy.toString() !== package_json.toString ()){
                console.log ("	NPM depency changes detected");
                if (parsed_package && parsed_package.dependencies){
                    for (var package_name in parsed_package.dependencies){
                        var copy_version = (parsed_copy && parsed_copy.dependencies) ? parsed_copy.dependencies[package_name] : "";
                        if (copy_version !== parsed_package.dependencies[package_name]){
                            deleteRecursiveSync ("node_modules/" + package_name);
                        }
                    }
                }
                if (parsed_copy && parsed_copy.dependencies){
                    for (package_name in parsed_copy.dependencies){
                        copy_version = (parsed_package && parsed_package.dependencies) ? parsed_package.dependencies[package_name] : "";
                        if (copy_version !== parsed_copy.dependencies[package_name]){
                            deleteRecursiveSync ("node_modules/" + package_name);
                        }
                    }
                }
                var child = exec (sudo + "npm install -d", function (err, std, ster){
                    if (err){
                        console.log ("	Error installing Node` modules. Error:" + ster);
                        pull_error += "\nError installing Node` modules. Error:" + ster;
                    }
                    else{
                        console.log ("	Sucessfully update Node Modules: " + std);
                        fs.writeFileSync ("package.copy", package_json);
                    }
                    cb && cb ();
                });
            }
            else{
                console.log ("  No node module changes detected");
                cb && cb ();
            }
        }
    }
    // start the application
    function startApp (){
        var appEntry = config.appEntry || "start.js";
        console.log ("\nSTARTING APPLICATION CALLING: " + appEntry);
        require ('./' + appEntry);
    }

    /////////////////// CODE EXECUTION STARTS HERE ///////////////////////////
    console.log ("********** Node-Deploy Started *********");
    var date = new Date ();
    console.log (date.toString ());

    try {config_file = fs.readFileSync (".app-config.json");}
    catch (err){ error = err;}

    if (config_file){
        try {config = JSON.parse (config_file);}
        catch (err){ error = err;}
    }

    if (!config) {
        console.log ("	'app-config.json' is missing or invalid: Error:" + error);
        console.log ("	Continuing on with defaults");
        config = {};
    }
    // if nor configured this does nothing
    sudo = (config.sudo) ? "sudo " : "";

    // init the cloud code
    cloud.init (config, function (){
        instance_data = cloud.getInstanceData ();
        console.log ("\nGetting Cloud Data")
        console.log ("  Instance ID:" + cloud.getInstanceId ());
        console.log ("  Instance Data:%j", instance_data);

        // see if updating should be on or off
        if (instance_data && instance_data.deploy === true){
            updating_on = true;
        }

        /*
        // change directory to the app working directory. Default to the current directory
        var workingDirectory = config.applicationDirectory || process.cwd();
        process.chdir (workingDirectory);
        console.log ("\nSetting Working Directory to:" + process.cwd());
        */
        // determine if we are in the could or not and set an environment variable
        // in case other code needs to know this
        console.log ("\nServer in cloud: " + cloud.isCloud ());
        process.env['CLOUD'] = cloud.isCloud ();
        process.env['INSTANCE_ID'] = cloud.getInstanceId ();
        process.env['INSTANCE_DATA'] = cloud.getInstanceData ();

        function checkAndUpdateEnvironment (master){
            if (updating_on){
                // get the latest code
                pull (function (){
                    // check for dependency changes
                    checkNodeDependencies (function (){
                        checkNPMDependencies (function (){
                            startApp ();
                        });
                    });
                }, master);
            }
        }
        checkAndUpdateEnvironment (false);

        // create a server to listen for pull requests
        function handleRequests (req, res){
            function parseURL (req){
                var url_in = url.parse(req.url,true);
                req.query = url_in.query;
                req.href = url_in.href;
            }
            function bodyParser (req, res, func){
                if (req.method == 'POST') {
                    var body = '';
                    req.on('data', function (data) {
                        body += data;
                        if (body.length > 524488) { // limit the most data someone can send to 1/2 a meg
                            request.connection.destroy();
                        }
                    });
                    req.on('end', function () {
                        req.body = qs.parse(body);
                        if (func){func (req, res);}
                    });
                }
            }
            if (req.url.search ("/pull") !== -1){ // handle a command to pull
                var valid_request = true;
                parseURL (req);
                if (config.pullSecret){
                    valid_request = (req.query.secret == config.pullSecret) ? true : false;
                }
                if (valid_request){
                    bodyParser (req, res, function (){
                        var listensTo = (instance_data && instance_data.listensTo) ? instance_data.listensTo : "";
                        if (req.body.ref.search (listensTo) !== -1){
                            pull (function (){
                                res.writeHead(200, {'Content-Type': 'text/plain'});
                                if (pull_error){ res.end("Pull Accepted. There were Errors:" + pull_error); }
                                else {res.end("Pull Accepted"); }
                                var date = new Date ();
                                console.log ("\nPull Command, master:" + req.query.master + " @" + date.toString ());
                                console.log ("	body:%j", req.body);
                                if (pull_error){
                                    console.log ("	There were Errors:%j", pull_error);
                                }
                            }, req.query.master, req);
                        }
                        else{
                            console.log ("\nIgnoring Pull Request, wrong branch. \n\tListening for: " + config.branch +
                                "\n\t Recieved:" + body.ref);
                        }
                    });
                }
                else{
                    res.res.writeHead(200, {'Content-Type': 'text/plain'});
                    res.end("Pull Not Authorized");
                    console.log ("\nPull Not Authorized @" + date.toString ());
                    console.log ("	Secret passed in:" + !!params.secret);
                    console.log ("	Secret required:" + !!config.pullSecret);
                    console.log ("	Secrets Match:" + (config.pullSecret === params.secret));
                }
            }
            else{
                res.res.writeHead(404, {'Content-Type': 'text/plain'});
                res.end("Not Found");
            }
        }
        if (updating_on){
            var http_port = (config.pullPort || 8000), key, cert, options;
            if (config.pullKey && config.pullCert){
                try {key = fs.readFileSync (config.pullKey);}
                catch (err) {key = null;}
                try {cert = fs.readFileSync (config.pullCert);}
                catch (err) {cert = null;}
                if (key && cert) {
                    options = {key:key, cert:cert,
                    ciphers: 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH',
                    honorCipherOrder: true
                    };
                }
                if (options && config.pullPassphrase){
                    options.passphrase = config.pullPassphrase;
                }
                if (options && config.pullCa && config.pullCa.length){
                    var ca = [];
                    config.pullCa.forEach (function (_ca){
                        try {__ca = fs.readFileSync (_ca, {encoding: "aascii"});}
                        catch (err) {__ca = null;}
                        if (__ca){ ca.push (__ca);}
                    });
                    if (ca.length){
                        options.ca = ca;
                    }
                }
            }
            if (key && cert){
                console.log ("\nHTTPS Pull Server Started. Listening on Port:" + http_port);
                https.createServer (options, handleRequests).listen (http_port);
            }
            else{
                console.log ("\nWARNING cert and key not specified or invalid. Falling back to HTTP");
                console.log ("HTTP Pull Server Started. Listening on Port:" + http_port);
                http.createServer (handleRequests).listen (http_port);
            }
        }
    });
 })();
<commit_msg>Initial<commit_after>/*///////////////////////////////////////////////////////////////////////////

 For Best results use the an 'app-config.json' file. This File should be
 located in the same directory as this file. If you choose not to use it
 then your application must run out of the same directory as this file
 and you entry point must be a file named 'start.js' located in this
 directory.

 'app-config.json' allows you to configure following properties for your
 application:

"applicationName:" <name of the application>
 "applicationDirectory": <set this to the directory you application lives in>
 "appEntry": <set this to the name of the 'js' file that is your entry point>

 "pullPort": <set this to the port for a pull requests> - defaults to 8000

 // The key and cert files are only necessary if you want to listen for a pull
 // request securely. If they are omitted and HTTP server is start instead. Beware
 // as someone could be snooping and then start sending your servers pull requests
 "pullKey": <path to a ssh key file for the HTTPS Server>
 "pullCert": <path to a ssh cert file for the HTTPS Server>
 "pullCa": <array of paths to the certificate authority files> (optional)
 "pullPassphrase" : <string - phrase that the certificate was generated with> (optional if certificate was not generated with a passphrase)

 // This is a secret key that is configured here and passed in via a webhook in
 // response to a pull request. This is to prevent unauthorized requests from causing
 // pulls. If no pull secret is configure then all pull request are valid
 "pullSecret": <secret phrase>

 "pullBranch": <git branch to use for the pull>

 // In theory you can put an cloud vendor specific params in here. You just have to have support in cloud.js for them.
 // Curently AWS is the only cloud platform supported
 // Put your AWS config params in here. Example:
 "accessKeyId": "XXXXXXXXXXXXXXXXXXXX",
 "secretAccessKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
 "region": "us-east-1"

 "sudo": <Mac and Linux only, should we prefix all shell commands with sudo?> - defaults to no sudo

 // To Trigger a pull and restart

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

(function (){
    var fs = require ('fs');
    var exec = require('child_process').exec;
    var path = require('path');
    var url = require('url');
    var qs = require ('querystring');
    var config_file, config, error, pull_error = "";
    var package_json, package_copy, parsed_package, parsed_copy;
    var restart = true;
    var need_restart = false;
    var http = require('http');
    var https = require('https');
    // This an abstraction layer for different cloud services
    // all AWS specific code or other cloud vendor stuff should go in here
    var cloud = require ("./cloud.js");
    var updating_on = false;
    var sudo;
    var instance_data;

    // post a command out
    function post (url, body, port, secure, path, cb){
        var qs = require('querystring');
        body = qs.stringify (body);
        var options = {
            host: url,
            port: port,
            path: path,
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': body.length
            },
            rejectUnauthorized:false // add this so if someone uses a local certificate on the machine the post will still go through
        };

        var server = (secure) ? https : http;
        var req = server.request(options, function(res) {
            var result = "";
            //console.log('STATUS: ' + res.statusCode);
            //console.log('HEADERS: ' + JSON.stringify(res.headers) + '\n');
            res.setEncoding('utf8');
            res.on('data', function (chunk) {result += chunk;});
            res.on('end', function (){
                cb (null, result);
            });
        });
        req.on('error', function(e) {
            console.log('problem with request: ' + e.message);
            cb (e.message);
        });

        // write data to request body
        req.write(body);
        req.end();
    }

    // pull the latest source
    function pull(cb, master, req){
        pull_error = "";
        function _pull (cb){
            console.log ("\nPulling the latest code from remote repository");
            // get the latest code
            var child = exec (sudo + "git pull", function (err, std, ster){
                if (err){
                    console.log ("	Error pulling reposititory. Error" + ster);
                    pull_error += "\nError pulling reposititory. Error" + ster;
                }
                else{console.log ("	" + std);}
                cb && cb ();
            });
        }
        // only pull the latest if in the cloud. For local development don't do anything. The developer must manually pull
        if (cloud.isCloud ()){
            restart = (master || master === false);
            need_restart = false;
            if (!master){
                _pull (function (){
                    if (need_restart){
                        process.exit(0);
                    }
                    cb && cb ();
                });
            }
            else { // else we are the master so find all the other AWS instances to pull from
                // get other instances that our are same type and already running
                var secure = (req.href.search ("https://") !== -1);
                var instances = cloud.getInstances (function (instances){
                    instances && instances.forEach (function (instance){
                        if (instance.dns && instance.id !== cloud.getInstanceId ()){ // don't signal ourselves
                            post (instance.dns, req,body, config.pullPort, secure, url.format (req.query));
                        }
                    });
                    // now pull and restart ourselves
                    _pull (function (){
                        if (need_restart){
                            process.exit(0);
                        }
                        cb && cb ();
                    });
                });
            }
        }
        else {cb && cb ();}
    }
    // check if any NPM dependencies changed
    function checkNodeDependencies (cb){
        // read in our files
        console.log ("\nChecking for Node version changes");
        try { package_copy = fs.readFileSync ("package.copy");}
        catch (e) { package_copy = null;}
        try {package_json = fs.readFileSync ("package.json");}
        catch (e) { package_json = null;}
        parsed_package = (package_json) ? JSON.parse (package_json) : null;
        parsed_copy = (package_copy) ? JSON.parse (package_copy) : null;
        // see if our node versions match
        if (parsed_package && parsed_package.node_version){
            var version = parsed_package.node_version.replace ('v', "");
            var node_version = process.version.replace ('v', "");
            if (version !== node_version){
                console.log ("	Upgrading Node");
                console.log ("		current version:" + node_version);
                console.log ("		requested version:" + version);
                // upgrade node using 'n'
                var child = exec (sudo + "n " + version, function (err, std, ster){
                    if (err){
                        console.log ("		Node upgrade failed. Error:" + ster);
                        pull_error += "\nNode upgrade failed. Error:" + ster;
                    }
                    else{
                        console.log ("		Node upgrade success, restarting");
                        if (restart){ process.exit (0); }// exit so we get restarted
                        else { need_restart = true;}
                    }
                    cb & cb ();
                });
            }
            else{
                console.log ("  Node is up to date");
                console.log ("      current version:" + node_version);
                cb & cb ();
            }
        }
        else{
            console.log ("	Current Node version is:" + node_version);
            cb & cb ();
        }
    }

    // check for any node module changes and reinstall the associated packages.
    // NPM doesn't do a good job of keeping track. So keep a copy of the last successful
    // update and compare it. Find ones that have changed and delete them and the
    // re-install.
    function checkNPMDependencies (cb){
        function deleteRecursiveSync(itemPath) {
            if (fs.existsSync(itemPath)){
                if (fs.existsSync(itemPath) && fs.statSync(itemPath).isDirectory()) {
                    fs.readdirSync(itemPath).forEach(function(childItemName) {
                        deleteRecursiveSync(path.join(itemPath, childItemName));
                    });
                    fs.rmdirSync(itemPath);
                } else {
                    fs.unlinkSync(itemPath);
                }
            }
        }
        console.log ("\nChecking for Node Module dependency changes");
        if (!package_json){
            console.log ("WARNING Your Application has no 'package.json' . It is highly" +
                " recommended that you use one to manage your NPM dependencies");
        }
        else{ // delete the module that have changed and re-install with new versions
            if (!package_copy || package_copy.toString() !== package_json.toString ()){
                console.log ("	NPM depency changes detected");
                if (parsed_package && parsed_package.dependencies){
                    for (var package_name in parsed_package.dependencies){
                        var copy_version = (parsed_copy && parsed_copy.dependencies) ? parsed_copy.dependencies[package_name] : "";
                        if (copy_version !== parsed_package.dependencies[package_name]){
                            deleteRecursiveSync ("node_modules/" + package_name);
                        }
                    }
                }
                if (parsed_copy && parsed_copy.dependencies){
                    for (package_name in parsed_copy.dependencies){
                        copy_version = (parsed_package && parsed_package.dependencies) ? parsed_package.dependencies[package_name] : "";
                        if (copy_version !== parsed_copy.dependencies[package_name]){
                            deleteRecursiveSync ("node_modules/" + package_name);
                        }
                    }
                }
                var child = exec (sudo + "npm install -d", function (err, std, ster){
                    if (err){
                        console.log ("	Error installing Node` modules. Error:" + ster);
                        pull_error += "\nError installing Node` modules. Error:" + ster;
                    }
                    else{
                        console.log ("	Sucessfully update Node Modules: " + std);
                        fs.writeFileSync ("package.copy", package_json);
                    }
                    cb && cb ();
                });
            }
            else{
                console.log ("  No node module changes detected");
                cb && cb ();
            }
        }
    }
    // start the application
    function startApp (){
        var appEntry = config.appEntry || "start.js";
        console.log ("\nSTARTING APPLICATION CALLING: " + appEntry);
        require ('./' + appEntry);
    }

    /////////////////// CODE EXECUTION STARTS HERE ///////////////////////////
    console.log ("********** Node-Deploy Started *********");
    var date = new Date ();
    console.log (date.toString ());

    try {config_file = fs.readFileSync (".app-config.json");}
    catch (err){ error = err;}

    if (config_file){
        try {config = JSON.parse (config_file);}
        catch (err){ error = err;}
    }

    if (!config) {
        console.log ("	'app-config.json' is missing or invalid: Error:" + error);
        console.log ("	Continuing on with defaults");
        config = {};
    }
    // if nor configured this does nothing
    sudo = (config.sudo) ? "sudo " : "";

    // init the cloud code
    cloud.init (config, function (){
        instance_data = cloud.getInstanceData ();
        console.log ("\nGetting Cloud Data")
        console.log ("  Instance ID:" + cloud.getInstanceId ());
        console.log ("  Instance Data:%j", instance_data);

        // see if updating should be on or off
        if (instance_data && instance_data.deploy === true){
            updating_on = true;
        }

        /*
        // change directory to the app working directory. Default to the current directory
        var workingDirectory = config.applicationDirectory || process.cwd();
        process.chdir (workingDirectory);
        console.log ("\nSetting Working Directory to:" + process.cwd());
        */
        // determine if we are in the could or not and set an environment variable
        // in case other code needs to know this
        console.log ("\nServer in cloud: " + cloud.isCloud ());
        process.env['CLOUD'] = cloud.isCloud ();
        process.env['INSTANCE_ID'] = cloud.getInstanceId ();
        process.env['INSTANCE_DATA'] = cloud.getInstanceData ();

        function checkAndUpdateEnvironment (master){
            if (updating_on){
                // get the latest code
                pull (function (){
                    // check for dependency changes
                    checkNodeDependencies (function (){
                        checkNPMDependencies (function (){
                            startApp ();
                        });
                    });
                }, master);
            }
        }
        checkAndUpdateEnvironment (false);

        // create a server to listen for pull requests
        function handleRequests (req, res){
            function parseURL (req){
                var url_in = url.parse(req.url,true);
                req.query = url_in.query;
                req.href = url_in.href;
            }
            function bodyParser (req, res, func){
                if (req.method == 'POST') {
                    var body = '';
                    req.on('data', function (data) {
                        body += data;
                        if (body.length > 524488) { // limit the most data someone can send to 1/2 a meg
                            request.connection.destroy();
                        }
                    });
                    req.on('end', function () {
                        req.body = qs.parse(body);
                        if (func){func (req, res);}
                    });
                }
            }
            if (req.url.search ("/pull") !== -1){ // handle a command to pull
                var valid_request = true;
                parseURL (req);
                if (config.pullSecret){
                    valid_request = (req.query.secret == config.pullSecret) ? true : false;
                }
                if (valid_request){
                    bodyParser (req, res, function (){
                        var listensTo = (instance_data && instance_data.listensTo) ? instance_data.listensTo : "";
                        if (req.body.ref.search (listensTo) !== -1){
                            pull (function (){
                                res.writeHead(200, {'Content-Type': 'text/plain'});
                                if (pull_error){ res.end("Pull Accepted. There were Errors:" + pull_error); }
                                else {res.end("Pull Accepted"); }
                                var date = new Date ();
                                console.log ("\nPull Command, master:" + req.query.master + " @" + date.toString ());
                                console.log ("	body:%j", req.body);
                                if (pull_error){
                                    console.log ("	There were Errors:%j", pull_error);
                                }
                            }, req.query.master, req);
                        }
                        else{
                            console.log ("\nIgnoring Pull Request, wrong branch. \n\tListening for: " + config.branch +
                                "\n\t Recieved:" + body.ref);
                        }
                    });
                }
                else{
                    res.res.writeHead(200, {'Content-Type': 'text/plain'});
                    res.end("Pull Not Authorized");
                    console.log ("\nPull Not Authorized @" + date.toString ());
                    console.log ("	Secret passed in:" + !!params.secret);
                    console.log ("	Secret required:" + !!config.pullSecret);
                    console.log ("	Secrets Match:" + (config.pullSecret === params.secret));
                }
            }
            else{
                res.res.writeHead(404, {'Content-Type': 'text/plain'});
                res.end("Not Found");
            }
        }
        if (updating_on){
            var http_port = (config.pullPort || 8000), key, cert, options;
            if (config.pullKey && config.pullCert){
                try {key = fs.readFileSync (config.pullKey);}
                catch (err) {key = null;}
                try {cert = fs.readFileSync (config.pullCert);}
                catch (err) {cert = null;}
                if (key && cert) {
                    options = {key:key, cert:cert,
                    ciphers: 'ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH',
                    honorCipherOrder: true
                    };
                }
                if (options && config.pullPassphrase){
                    options.passphrase = config.pullPassphrase;
                }
                if (options && config.pullCa && config.pullCa.length){
                    var ca = [];
                    config.pullCa.forEach (function (_ca){
                        try {__ca = fs.readFileSync (_ca, {encoding: "aascii"});}
                        catch (err) {__ca = null;}
                        if (__ca){ ca.push (__ca);}
                    });
                    if (ca.length){
                        options.ca = ca;
                    }
                }
            }
            if (key && cert){
                console.log ("\nHTTPS Pull Server Started. Listening on Port:" + http_port);
                https.createServer (options, handleRequests).listen (http_port);
            }
            else{
                console.log ("\nWARNING cert and key not specified or invalid. Falling back to HTTP");
                console.log ("HTTP Pull Server Started. Listening on Port:" + http_port);
                http.createServer (handleRequests).listen (http_port);
            }
        }
    });
 })();
<|endoftext|>