<commit_before>function arrayExists(array, x) {
    for (var i = 0; i < array.length; i++) {
        if (array[i] == x) return true;
    }
    return false;
}

Date.prototype.formatDate = function (input,time) {
    // formatDate :
    // a PHP date like function, for formatting date strings
    // See: http://www.php.net/date
    //
    // input : format string
    // time : epoch time (seconds, and optional)
    //
    // if time is not passed, formatting is based on
    // the current "this" date object's set time.
    //
    // supported:
    // a, A, B, d, D, F, g, G, h, H, i, j, l (lowercase L), L,
    // m, M, n, O, r, s, S, t, U, w, W, y, Y, z
    //
    // unsupported:
    // I (capital i), T, Z

    var switches =    ["a", "A", "B", "d", "D", "F", "g", "G", "h", "H",
                       "i", "j", "l", "L", "m", "M", "n", "O", "r", "s",
                       "S", "t", "U", "w", "W", "y", "Y", "z"];
    var daysLong =    ["Sunday", "Monday", "Tuesday", "Wednesday",
                       "Thursday", "Friday", "Saturday"];
    var daysShort =   ["Sun", "Mon", "Tue", "Wed",
                       "Thu", "Fri", "Sat"];
    var monthsShort = ["Jan", "Feb", "Mar", "Apr",
                       "May", "Jun", "Jul", "Aug", "Sep",
                       "Oct", "Nov", "Dec"];
    var monthsLong =  ["January", "February", "March", "April",
                       "May", "June", "July", "August", "September",
                       "October", "November", "December"];
    var daysSuffix = ["st", "nd", "rd", "th", "th", "th", "th", // 1st - 7th
                      "th", "th", "th", "th", "th", "th", "th", // 8th - 14th
                      "th", "th", "th", "th", "th", "th", "st", // 15th - 21st
                      "nd", "rd", "th", "th", "th", "th", "th", // 22nd - 28th
                      "th", "th", "st"];                        // 29th - 31st

    function a() {
        // Lowercase Ante meridiem and Post meridiem
        return self.getHours() > 11? "pm" : "am";
    }
    function A() {
        // Uppercase Ante meridiem and Post meridiem
        return self.getHours() > 11? "PM" : "AM";
    }

    function B(){
        // Swatch internet time. code simply grabbed from ppk,
        // since I was feeling lazy:
        // http://www.xs4all.nl/~ppk/js/beat.html
        var off = (self.getTimezoneOffset() + 60)*60;
        var theSeconds = (self.getHours() * 3600) +
                         (self.getMinutes() * 60) +
                          self.getSeconds() + off;
        var beat = Math.floor(theSeconds/86.4);
        if (beat > 1000) beat -= 1000;
        if (beat < 0) beat += 1000;
        if ((""+beat).length == 1) beat = "00"+beat;
        if ((""+beat).length == 2) beat = "0"+beat;
        return beat;
    }

    function d() {
        // Day of the month, 2 digits with leading zeros
        return new String(self.getDate()).length == 1?
        "0"+self.getDate() : self.getDate();
    }
    function D() {
        // A textual representation of a day, three letters
        return daysShort[self.getDay()];
    }
    function F() {
        // A full textual representation of a month
        return monthsLong[self.getMonth()];
    }
    function g() {
        // 12-hour format of an hour without leading zeros
        return self.getHours() > 12? self.getHours()-12 : self.getHours();
    }
    function G() {
        // 24-hour format of an hour without leading zeros
        return self.getHours();
    }
    function h() {
        // 12-hour format of an hour with leading zeros
        if (self.getHours() > 12) {
          var s = new String(self.getHours()-12);
          return s.length == 1?
          "0"+ (self.getHours()-12) : self.getHours()-12;
        } else {
          var s = new String(self.getHours());
          return s.length == 1?
          "0"+self.getHours() : self.getHours();
        }
    }
    function H() {
        // 24-hour format of an hour with leading zeros
        return new String(self.getHours()).length == 1?
        "0"+self.getHours() : self.getHours();
    }
    function i() {
        // Minutes with leading zeros
        return new String(self.getMinutes()).length == 1?
        "0"+self.getMinutes() : self.getMinutes();
    }
    function j() {
        // Day of the month without leading zeros
        return self.getDate();
    }
    function l() {
        // A full textual representation of the day of the week
        return daysLong[self.getDay()];
    }
    function L() {
        // leap year or not. 1 if leap year, 0 if not.
        // the logic should match iso's 8601 standard.
        var y_ = Y();
        if (
            (y_ % 4 == 0 && y_ % 100 != 0) ||
            (y_ % 4 == 0 && y_ % 100 == 0 && y_ % 400 == 0)
            ) {
            return 1;
        } else {
            return 0;
        }
    }
    function m() {
        // Numeric representation of a month, with leading zeros
        return self.getMonth() < 9?
        "0"+(self.getMonth()+1) :
        self.getMonth()+1;
    }
    function M() {
        // A short textual representation of a month, three letters
        return monthsShort[self.getMonth()];
    }
    function n() {
        // Numeric representation of a month, without leading zeros
        return self.getMonth()+1;
    }
    function O() {
        // Difference to Greenwich time (GMT) in hours
        var os = Math.abs(self.getTimezoneOffset());
        var h = ""+Math.floor(os/60);
        var m = ""+(os%60);
        h.length == 1? h = "0"+h:1;
        m.length == 1? m = "0"+m:1;
        return self.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
    }
    function r() {
        // RFC 822 formatted date
        var r; // result
        //  Thu    ,     21          Dec         2000
        r = D() + ", " + j() + " " + M() + " " + Y() +
        //        16     :    01     :    07          +0200
            " " + H() + ":" + i() + ":" + s() + " " + O();
        return r;
    }
    function S() {
        // English ordinal suffix for the day of the month, 2 characters
        return daysSuffix[self.getDate()-1];
    }
    function s() {
        // Seconds, with leading zeros
        return new String(self.getSeconds()).length == 1?
        "0"+self.getSeconds() : self.getSeconds();
    }
    function t() {

        // thanks to Matt Bannon for some much needed code-fixes here!
        var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31];
        if (L()==1 && n()==2) return 29; // leap day
        return daysinmonths[n()];
    }
    function U() {
        // Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
        return Math.round(self.getTime()/1000);
    }
    function W() {
        // Weeknumber, as per ISO specification:
        // http://www.cl.cam.ac.uk/~mgk25/iso-time.html

        // if the day is three days before newyears eve,
        // there's a chance it's "week 1" of next year.
        // here we check for that.
        var beforeNY = 364+L() - z();
        var afterNY  = z();
        var weekday = w()!=0?w()-1:6; // makes sunday (0), into 6.
        if (beforeNY <= 2 && weekday <= 2-beforeNY) {
            return 1;
        }
        // similarly, if the day is within threedays of newyears
        // there's a chance it belongs in the old year.
        var ny = new Date("January 1 " + Y() + " 00:00:00");
        var nyDay = ny.getDay()!=0?ny.getDay()-1:6;
        if (
            (afterNY <= 2) &&
            (nyDay >=4)  &&
            (afterNY >= (6-nyDay))
            ) {
            // Since I'm not sure we can just always return 53,
            // i call the function here again, using the last day
            // of the previous year, as the date, and then just
            // return that week.
            var prevNY = new Date("December 31 " + (Y()-1) + " 00:00:00");
            return prevNY.formatDate("W");
        }

        // week 1, is the week that has the first thursday in it.
        // note that this value is not zero index.
        if (nyDay <= 3) {
            // first day of the year fell on a thursday, or earlier.
            return 1 + Math.floor( ( z() + nyDay ) / 7 );
        } else {
            // first day of the year fell on a friday, or later.
            return 1 + Math.floor( ( z() - ( 7 - nyDay ) ) / 7 );
        }
    }
    function w() {
        // Numeric representation of the day of the week
        return self.getDay();
    }

    function Y() {
        // A full numeric representation of a year, 4 digits

        // we first check, if getFullYear is supported. if it
        // is, we just use that. ppks code is nice, but wont
        // work with dates outside 1900-2038, or something like that
        if (self.getFullYear) {
            var newDate = new Date("January 1 2001 00:00:00 +0000");
            var x = newDate .getFullYear();
            if (x == 2001) {
                // i trust the method now
                return self.getFullYear();
            }
        }
        // else, do this:
        // codes thanks to ppk:
        // http://www.xs4all.nl/~ppk/js/introdate.html
        var x = self.getYear();
        var y = x % 100;
        y += (y < 38) ? 2000 : 1900;
        return y;
    }
    function y() {
        // A two-digit representation of a year
        var y = Y()+"";
        return y.substring(y.length-2,y.length);
    }
    function z() {
        // The day of the year, zero indexed! 0 through 366
        var t = new Date("January 1 " + Y() + " 00:00:00");
        var diff = self.getTime() - t.getTime();
        return Math.floor(diff/1000/60/60/24);
    }

    var self = this;
    if (time) {
        // save time
        var prevTime = self.getTime();
        self.setTime(time);
    }

    var ia = input.split("");
    var ij = 0;
    while (ia[ij]) {
        if (ia[ij] == "\\") {
            // this is our way of allowing users to escape stuff
            ia.splice(ij,1);
        } else {
            if (arrayExists(switches,ia[ij])) {
                ia[ij] = eval(ia[ij] + "()");
            }
        }
        ij++;
    }
    // reset time, back to what it was
    if (prevTime) {
        self.setTime(prevTime);
    }
    return ia.join("");
}

var date = new Date("1/1/2007 1:11:11");

startTest("sunspider-date-format-tofte");

test("Format Date", function(){
	for (i = 0; i < 50; ++i) {
    		var shortFormat = date.formatDate("Y-m-d");
    		var longFormat = date.formatDate("l, F d, Y g:i:s A");
    		date.setTime(date.getTime() + 84266956);
	}
});

endTest();
<commit_msg>Fixed problem with tofte test.<commit_after>function arrayExists(array, x) {
    for (var i = 0; i < array.length; i++) {
        if (array[i] == x) return true;
    }
    return false;
}

Date.prototype.formatDate = function (input,time) {
    // formatDate :
    // a PHP date like function, for formatting date strings
    // See: http://www.php.net/date
    //
    // input : format string
    // time : epoch time (seconds, and optional)
    //
    // if time is not passed, formatting is based on
    // the current "this" date object's set time.
    //
    // supported:
    // a, A, B, d, D, F, g, G, h, H, i, j, l (lowercase L), L,
    // m, M, n, O, r, s, S, t, U, w, W, y, Y, z
    //
    // unsupported:
    // I (capital i), T, Z

    var switches =    ["a", "A", "B", "d", "D", "F", "g", "G", "h", "H",
                       "i", "j", "l", "L", "m", "M", "n", "O", "r", "s",
                       "S", "t", "U", "w", "W", "y", "Y", "z"];
    var daysLong =    ["Sunday", "Monday", "Tuesday", "Wednesday",
                       "Thursday", "Friday", "Saturday"];
    var daysShort =   ["Sun", "Mon", "Tue", "Wed",
                       "Thu", "Fri", "Sat"];
    var monthsShort = ["Jan", "Feb", "Mar", "Apr",
                       "May", "Jun", "Jul", "Aug", "Sep",
                       "Oct", "Nov", "Dec"];
    var monthsLong =  ["January", "February", "March", "April",
                       "May", "June", "July", "August", "September",
                       "October", "November", "December"];
    var daysSuffix = ["st", "nd", "rd", "th", "th", "th", "th", // 1st - 7th
                      "th", "th", "th", "th", "th", "th", "th", // 8th - 14th
                      "th", "th", "th", "th", "th", "th", "st", // 15th - 21st
                      "nd", "rd", "th", "th", "th", "th", "th", // 22nd - 28th
                      "th", "th", "st"];                        // 29th - 31st

    function a() {
        // Lowercase Ante meridiem and Post meridiem
        return self.getHours() > 11? "pm" : "am";
    }
    function A() {
        // Uppercase Ante meridiem and Post meridiem
        return self.getHours() > 11? "PM" : "AM";
    }

    function B(){
        // Swatch internet time. code simply grabbed from ppk,
        // since I was feeling lazy:
        // http://www.xs4all.nl/~ppk/js/beat.html
        var off = (self.getTimezoneOffset() + 60)*60;
        var theSeconds = (self.getHours() * 3600) +
                         (self.getMinutes() * 60) +
                          self.getSeconds() + off;
        var beat = Math.floor(theSeconds/86.4);
        if (beat > 1000) beat -= 1000;
        if (beat < 0) beat += 1000;
        if ((""+beat).length == 1) beat = "00"+beat;
        if ((""+beat).length == 2) beat = "0"+beat;
        return beat;
    }

    function d() {
        // Day of the month, 2 digits with leading zeros
        return new String(self.getDate()).length == 1?
        "0"+self.getDate() : self.getDate();
    }
    function D() {
        // A textual representation of a day, three letters
        return daysShort[self.getDay()];
    }
    function F() {
        // A full textual representation of a month
        return monthsLong[self.getMonth()];
    }
    function g() {
        // 12-hour format of an hour without leading zeros
        return self.getHours() > 12? self.getHours()-12 : self.getHours();
    }
    function G() {
        // 24-hour format of an hour without leading zeros
        return self.getHours();
    }
    function h() {
        // 12-hour format of an hour with leading zeros
        if (self.getHours() > 12) {
          var s = new String(self.getHours()-12);
          return s.length == 1?
          "0"+ (self.getHours()-12) : self.getHours()-12;
        } else {
          var s = new String(self.getHours());
          return s.length == 1?
          "0"+self.getHours() : self.getHours();
        }
    }
    function H() {
        // 24-hour format of an hour with leading zeros
        return new String(self.getHours()).length == 1?
        "0"+self.getHours() : self.getHours();
    }
    function i() {
        // Minutes with leading zeros
        return new String(self.getMinutes()).length == 1?
        "0"+self.getMinutes() : self.getMinutes();
    }
    function j() {
        // Day of the month without leading zeros
        return self.getDate();
    }
    function l() {
        // A full textual representation of the day of the week
        return daysLong[self.getDay()];
    }
    function L() {
        // leap year or not. 1 if leap year, 0 if not.
        // the logic should match iso's 8601 standard.
        var y_ = Y();
        if (
            (y_ % 4 == 0 && y_ % 100 != 0) ||
            (y_ % 4 == 0 && y_ % 100 == 0 && y_ % 400 == 0)
            ) {
            return 1;
        } else {
            return 0;
        }
    }
    function m() {
        // Numeric representation of a month, with leading zeros
        return self.getMonth() < 9?
        "0"+(self.getMonth()+1) :
        self.getMonth()+1;
    }
    function M() {
        // A short textual representation of a month, three letters
        return monthsShort[self.getMonth()];
    }
    function n() {
        // Numeric representation of a month, without leading zeros
        return self.getMonth()+1;
    }
    function O() {
        // Difference to Greenwich time (GMT) in hours
        var os = Math.abs(self.getTimezoneOffset());
        var h = ""+Math.floor(os/60);
        var m = ""+(os%60);
        h.length == 1? h = "0"+h:1;
        m.length == 1? m = "0"+m:1;
        return self.getTimezoneOffset() < 0 ? "+"+h+m : "-"+h+m;
    }
    function r() {
        // RFC 822 formatted date
        var r; // result
        //  Thu    ,     21          Dec         2000
        r = D() + ", " + j() + " " + M() + " " + Y() +
        //        16     :    01     :    07          +0200
            " " + H() + ":" + i() + ":" + s() + " " + O();
        return r;
    }
    function S() {
        // English ordinal suffix for the day of the month, 2 characters
        return daysSuffix[self.getDate()-1];
    }
    function s() {
        // Seconds, with leading zeros
        return new String(self.getSeconds()).length == 1?
        "0"+self.getSeconds() : self.getSeconds();
    }
    function t() {

        // thanks to Matt Bannon for some much needed code-fixes here!
        var daysinmonths = [null,31,28,31,30,31,30,31,31,30,31,30,31];
        if (L()==1 && n()==2) return 29; // leap day
        return daysinmonths[n()];
    }
    function U() {
        // Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
        return Math.round(self.getTime()/1000);
    }
    function W() {
        // Weeknumber, as per ISO specification:
        // http://www.cl.cam.ac.uk/~mgk25/iso-time.html

        // if the day is three days before newyears eve,
        // there's a chance it's "week 1" of next year.
        // here we check for that.
        var beforeNY = 364+L() - z();
        var afterNY  = z();
        var weekday = w()!=0?w()-1:6; // makes sunday (0), into 6.
        if (beforeNY <= 2 && weekday <= 2-beforeNY) {
            return 1;
        }
        // similarly, if the day is within threedays of newyears
        // there's a chance it belongs in the old year.
        var ny = new Date("January 1 " + Y() + " 00:00:00");
        var nyDay = ny.getDay()!=0?ny.getDay()-1:6;
        if (
            (afterNY <= 2) &&
            (nyDay >=4)  &&
            (afterNY >= (6-nyDay))
            ) {
            // Since I'm not sure we can just always return 53,
            // i call the function here again, using the last day
            // of the previous year, as the date, and then just
            // return that week.
            var prevNY = new Date("December 31 " + (Y()-1) + " 00:00:00");
            return prevNY.formatDate("W");
        }

        // week 1, is the week that has the first thursday in it.
        // note that this value is not zero index.
        if (nyDay <= 3) {
            // first day of the year fell on a thursday, or earlier.
            return 1 + Math.floor( ( z() + nyDay ) / 7 );
        } else {
            // first day of the year fell on a friday, or later.
            return 1 + Math.floor( ( z() - ( 7 - nyDay ) ) / 7 );
        }
    }
    function w() {
        // Numeric representation of the day of the week
        return self.getDay();
    }

    function Y() {
        // A full numeric representation of a year, 4 digits

        // we first check, if getFullYear is supported. if it
        // is, we just use that. ppks code is nice, but wont
        // work with dates outside 1900-2038, or something like that
        if (self.getFullYear) {
            var newDate = new Date("January 1 2001 00:00:00 +0000");
            var x = newDate .getFullYear();
            if (x == 2001) {
                // i trust the method now
                return self.getFullYear();
            }
        }
        // else, do this:
        // codes thanks to ppk:
        // http://www.xs4all.nl/~ppk/js/introdate.html
        var x = self.getYear();
        var y = x % 100;
        y += (y < 38) ? 2000 : 1900;
        return y;
    }
    function y() {
        // A two-digit representation of a year
        var y = Y()+"";
        return y.substring(y.length-2,y.length);
    }
    function z() {
        // The day of the year, zero indexed! 0 through 366
        var t = new Date("January 1 " + Y() + " 00:00:00");
        var diff = self.getTime() - t.getTime();
        return Math.floor(diff/1000/60/60/24);
    }

    var self = this;
    if (time) {
        // save time
        var prevTime = self.getTime();
        self.setTime(time);
    }

    var ia = input.split("");
    var ij = 0;
    while (ia[ij]) {
        if (ia[ij] == "\\") {
            // this is our way of allowing users to escape stuff
            ia.splice(ij,1);
        } else {
            if (arrayExists(switches,ia[ij])) {
                ia[ij] = eval(ia[ij] + "()");
            }
        }
        ij++;
    }
    // reset time, back to what it was
    if (prevTime) {
        self.setTime(prevTime);
    }
    return ia.join("");
}

var date = new Date("1/1/2007 1:11:11");

startTest("sunspider-date-format-tofte");

test("Format Date", function(){
	for (var i = 0; i < 50; ++i) {
    		var shortFormat = date.formatDate("Y-m-d");
    		var longFormat = date.formatDate("l, F d, Y g:i:s A");
    		date.setTime(date.getTime() + 84266956);
	}
});

endTest();
<|endoftext|>


<commit_before>import { DocumentNode, Document } from 'substance'

export class Book extends DocumentNode {}

Book.schema = {
  type: 'book',
  authors: { type: ['person', 'organisation'], default: [] },
  editors: { type: ['person'], default: [] },
  chapterTitle: { type: 'text', optional: true },
  source: { type: 'string', optional: true },
  edition: { type: 'string', optional: true },
  publisherLoc: { type: 'string', optional: true },
  publisherName: { type: 'string', optional: true },
  year: { type: 'string', optional: true },
  month: { type: 'string', optional: true },
  day: { type: 'string', optional: true },
  fpage: { type: 'string', optional: true },
  lpage: { type: 'string', optional: true },
  pageRange: { type: 'string', optional: true },
  elocationId: { type: 'string', optional: true },
  doi: { type: 'string', optional: true},
  isbn: { type: 'string', optional: true},
  pmid: { type: 'string', optional: true}
}

export class JournalArticle extends DocumentNode {}

JournalArticle.schema = {
  type: 'journal-article',
  authors: { type: ['person', 'organisation'], default: [] },
  editors: { type: ['person'], default: [] },
  articleTitle: { type: 'text', optional: true },
  source: { type: 'string', optional: true },
  volume: { type: 'string', optional: true },
  year: { type: 'string', optional: true },
  month: { type: 'string', optional: true },
  day: { type: 'string', optional: true },
  fpage: { type: 'string', optional: true },
  lpage: { type: 'string', optional: true },
  pageRange: { type: 'string', optional: true },
  elocationId: { type: 'string', optional: true },
  doi: { type: 'string', optional: true },
  references: { type: ['journal-article', 'book'], default: [] },
}

export class Person extends DocumentNode {}

Person.schema = {
  type: 'person',
  orcid: { type: 'string', optional: true },
  givenNames: { type: 'string', optional: true },
  surname: { type: 'string', optional: true },
  prefix: { type: 'string', optional: true },
  suffix: { type: 'string', optional: true },
  affiliations: { type: ['organisation'], default: [] },
}

export class Organisation extends DocumentNode {}

Organisation.schema = {
  type: 'organisation',
  name: { type: 'string', optional: true },
}

export default class EntityDatabase extends Document {
  /*
    Simple API to find records in the entity database.
  */
  find(qry) {
    let nodesByType = this.getIndex('type')
    let nodeIds = Object.keys(nodesByType.get(qry.type))
    return nodeIds
  }
}
<commit_msg>Schema for organisations.<commit_after>import { DocumentNode, Document } from 'substance'

export class Book extends DocumentNode {}

Book.schema = {
  type: 'book',
  authors: { type: ['person', 'organisation'], default: [] },
  editors: { type: ['person'], default: [] },
  chapterTitle: { type: 'text', optional: true },
  source: { type: 'string', optional: true },
  edition: { type: 'string', optional: true },
  publisherLoc: { type: 'string', optional: true },
  publisherName: { type: 'string', optional: true },
  year: { type: 'string', optional: true },
  month: { type: 'string', optional: true },
  day: { type: 'string', optional: true },
  fpage: { type: 'string', optional: true },
  lpage: { type: 'string', optional: true },
  pageRange: { type: 'string', optional: true },
  elocationId: { type: 'string', optional: true },
  doi: { type: 'string', optional: true},
  isbn: { type: 'string', optional: true},
  pmid: { type: 'string', optional: true}
}

export class JournalArticle extends DocumentNode {}

JournalArticle.schema = {
  type: 'journal-article',
  authors: { type: ['person', 'organisation'], default: [] },
  editors: { type: ['person'], default: [] },
  articleTitle: { type: 'text', optional: true },
  source: { type: 'string', optional: true },
  volume: { type: 'string', optional: true },
  year: { type: 'string', optional: true },
  month: { type: 'string', optional: true },
  day: { type: 'string', optional: true },
  fpage: { type: 'string', optional: true },
  lpage: { type: 'string', optional: true },
  pageRange: { type: 'string', optional: true },
  elocationId: { type: 'string', optional: true },
  doi: { type: 'string', optional: true },
  references: { type: ['journal-article', 'book'], default: [] },
}

export class Person extends DocumentNode {}

Person.schema = {
  type: 'person',
  orcid: { type: 'string', optional: true },
  givenNames: { type: 'string', optional: true },
  surname: { type: 'string', optional: true },
  prefix: { type: 'string', optional: true },
  suffix: { type: 'string', optional: true },
  affiliations: { type: ['organisation'], default: [] },
}

export class Organisation extends DocumentNode {}

Organisation.schema = {
  type: 'organisation',
  name: { type: 'string', optional: true },
  division1: { type: 'string', optional: true },
  division2: { type: 'string', optional: true },
  division3: { type: 'string', optional: true },
  // Consider switching to address-line1,2,3
  street: { type: 'string', optional: true },
  addressComplements: { type: 'string', optional: true },
  city: { type: 'string', optional: true },
  state: { type: 'string', optional: true },
  postalCode: { type: 'string', optional: true },
  country: { type: 'string', optional: true },
  phone: { type: 'string', optional: true },
  fax: { type: 'string', optional: true },
  email: { type: 'string', optional: true },
  uri: { type: 'string', optional: true },
}

export default class EntityDatabase extends Document {
  /*
    Simple API to find records in the entity database.
  */
  find(qry) {
    let nodesByType = this.getIndex('type')
    let nodeIds = Object.keys(nodesByType.get(qry.type))
    return nodeIds
  }
}
<|endoftext|>


<commit_before>var Client = require(__dirname + '/../lib/client').Client;
var EventEmitter = require('events').EventEmitter;
var xml2js = require('xml2js');

var statusCodeTable = {
  500: 'Inetnal Server Error',
  404: 'Not Found',
  409: 'Conflict',
  400: 'Bad Request',
  200: 'OK'
};

function ScenariosRunner(options) {
  this.options = options;
}

ScenariosRunner.prototype = new EventEmitter();

ScenariosRunner.prototype.run = function(scenarios) {
  var params = { scenarios: expandScenarios(scenarios) };
  this._process(params);
};

function cloneArray(array) {
  return array.map(function(aElement) {
    if (Array.isArray(aElement))
      return cloneArray(aElement);
    else
      return Object.create(aElement);
  });
};

function expandScenarios(scenarios) {
  if (!Array.isArray(scenarios))
    scenarios = [scenarios];

  var expanded = [];
  scenarios.forEach(function(scenario) {
    expanded = expanded.concat(expandScenario(scenario));
  });
  return expanded;
};
ScenariosRunner.expandScenarios =
  ScenarioRunner.expandScenarios = expandScenarios;

function expandScenario(scenario) {
  if (!scenario.requests)
    scenario = { requests: scenario };

  if (scenario.setup) {
    if (!Array.isArray(scenario.setup))
      scenario.setup = [scenario.setup];
  } else {
    scenario.setup = [];
  }

  if (scenario.teardown) {
    if (!Array.isArray(scenario.teardown))
      scenario.teardown = [scenario.teardown];
  } else {
    scenario.teardown = [];
  }

  var scenarios = [];
  scenario.requests.forEach(function(requests) {
    if (!Array.isArray(requests))
      requests = [requests];

    var expanded = Object.create(scenario);
    expanded.name = requests[0].name;
    expanded.requests = cloneArray(scenario.setup)
                          .concat(requests)
                          .concat(cloneArray(scenario.setup));
    scenarios.push(expanded);
  });

  // make request names unique
  var names = {};
  scenarios.forEach(function(scenario) {
    scenario.requests.forEach(function(request) {
      request.name = scenario.name + ': ' + request.name;

      var count = 1;
      var name = request.name;
      while (name in names) {
        name = request.name + '-' + count++;
      }
      request.name = name;
      names[name] = true;
    });
  });

  return scenarios;
};
ScenariosRunner.expandScenario =
  ScenarioRunner.expandScenario = expandScenario;

ScenariosRunner.prototype._process = function(params) {
  if (!params.start) params.start = Date.now();
  var scenario = params.scenarios.shift();
  var self = this;

  var runner = new ScenarioRunner(this.options);

  runner.on('error:fatal', function(event) {
    self.emit('error:fatal', event);
  });

  runner.on('start', function(event) {
    self.emit('scenario', { runner: runner,
                            scenario: event.scenario });

    runner.on('end', function(event) {
      if (params.scenarios.length) {
        if (self.options.interval)
          setTimeout(function() { self._process(params); },
                     self.options.interval);
        else
          self._process(params);
      } else {
        var elapsedTime = Date.now() - params.start;
        self.emit('end', { elapsedTime: elapsedTime });
      }
    });
  });

  runner.run(scenario);
};

function ScenarioRunner(options) {
  this.client = new Client(options);
  this.options = options;
  if (options.documentEndpoint)
    this.client.docEndpoint = options.documentEndpoint;
}

ScenarioRunner.prototype = new EventEmitter();

ScenarioRunner.prototype.run = function(scenario) {
  var self = this;
  this.client.assertNoDomain(function(error) {
    if (error)
      self.emit('error:fatal', { error: error });
    else
      self._process(scenario);
  });
};

ScenarioRunner.prototype.assertNoDomain = function(callback) {
  this.client.assertNoDomain(function(error) {
    callback();
  });
};

ScenarioRunner.prototype.initializeScenario = function(scenario) {
  if (!scenario.requests)
    scenario = { requests: scenario };

  scenario.toBeProcessedRequests = scenario.requests.slice(0);
  scenario.start = Date.now();
  scenario.processed = {};

  return scenario;
};

ScenarioRunner.prototype._process = function(scenario, callback) {
  if (!scenario.toBeProcessedRequests) {
    scenario = this.initializeScenario(scenario);
    this.emit('start', { scenario: scenario });
  }

  var request = scenario.toBeProcessedRequests.shift();
  var self = this;
  function processNext() {
    if (scenario.toBeProcessedRequests.length) {
      self._process(scenario, callback);
    } else {
      var elapsedTime = Date.now() - scenario.start;
      var event = {
        elapsedTime: elapsedTime,
        scenario: scenario
      };
      self.emit('end', event);
    }
  }

  var name = request.name;
  var count = 1;
  while (name in scenario.processed) {
    name = request.name + count++;
  }

  this.emit('request:start', { scenario: scenario, request: request });

  this.client.rawConfigurationRequest(request.params.Action, request.params, function(error, response) {
    if (error) response = error;

    var statusCode = response.StatusCode;
    if (statusCode == 400) {
      var parser = new xml2js.Parser({ explicitRoot: true });
      parser.parseString(response.Body, function(error, result) {
        var errorCode = result.ErrorResponse.Error.Code;
        if (errorCode === 'Throttling') {
          self.emit('error:throttling');
        }
      });
    }
    if (!statusCodeTable[statusCode]) {
      self.emit('error:status_unknown', { statusCode: statusCode });
      if (callback)
        callback(statusCode, null);
      return;
    }

    var output = '';
    output += 'HTTP/1.1 ' + statusCode + ' ' + statusCodeTable[statusCode] + '\r\n';
    for (var key in response.Headers) {
      output += key + ': ' + response.Headers[key] + '\r\n';
    };
    output += '\r\n';
    output += response.Body.toString();

    request.response = output;
    self.emit('request:end', { scenario: scenario, request: request });
    if (self.options.interval)
      setTimeout(processNext, self.options.interval);
    else
      processNext();
  });
};

function toSafeName(name) {
  return name
           .replace(/[^a-zA-Z0-9]+/g, '-')
           .replace(/-$/, '');
};
ScenariosRunner.toSafeName =
  ScenarioRunner.toSafeName = toSafeName;

function Response(source) {
  source = source.split('\r\n\r\n');
  this.rawHeaders = source[0];
  this.rawBody = source.slice(1).join('\r\n\r\n');
}
Response.prototype = {
  get body() {
    if (!this._body) {
      if (/^\s*</.test(this.rawBody)) {
        this._body = this._XMLStringToJSON(this.rawBody);
      } else {
        try {
          this._body = JSON.parse(this.rawBody);
        } catch(error) {
          this._body = this.rawBody;
        }
      }
    }
    return this._body;
  },
  _XMLStringToJSON: function(xml) {
    var parser = new xml2js.Parser({
                   explicitRoot: true
                 });
    var json;
    parser.addListener('end', function(result) {
      json = result;
    });
    try {
      parser.parseString(xml);
    } catch (e) {
      console.log(xml);
      throw e;
    }
    return json;
  },

  get sortedBody() {
    if (!this._sortedBody) {
      if (this.body && typeof this.body == 'object')
        this._sortedBody = this._toSortedJSON(this.body, true);
      else
        this._sortedBody = this.body;
    }
    return this._sortedBody;
  },
  _toSortedJSON: function(fragment, doSort) {
    switch (typeof fragment) {
      default:
        return fragment;
      case 'object':
        var format = {};
        var keys = Object.keys(fragment);
        if (doSort) keys.sort();
        keys.forEach(function(key) {
          if (!fragment.hasOwnProperty(key))
            return;
          var doSort = this._orderedContainers.indexOf(key) < 0;
          format[key] = this._toSortedJSON(fragment[key], doSort);
        }, this);
        return format;
    }
  },
  _orderedContainers: [
    'DomainStatusList',
    'IndexFields',
    'FieldNames'
  ],

  get normalizedBody() {
    if (!this._normalizedBody)
      this._normalizedBody = this._normalize(this.sortedBody);
    return this._normalizedBody;
  },
  _normalize: function(fragment) {
    switch (typeof fragment) {
      default:
        return fragment;
      case 'object':
        var format = {};
        Object.keys(fragment).forEach(function(key) {
          if (!fragment.hasOwnProperty(key))
            return;

          var value = fragment[key];
          var normalized;
          switch (key) {
            case 'RequestId':
              normalized = '%REQUEST_ID%';
              break;

            case 'DomainId':
              normalized = value.replace(/^.+\//, '%DOMAIN_ID%/');
              break;

            case 'Endpoint':
              return; // this doesn't appear in ACS's response!

            case 'Arn':
              normalized = value.replace(/^(arn:aws:cs:us-east-1:)[^:]+(:[^\/]+\/[^\/]+)$/, '$1%DOMAIN_ID%$2');
              break;

            default:
              normalized = this._normalize(value);
              break;
          }
          format[key] = normalized;
        }, this);
        return format;
    }
  },

  equals: function(anotherResponse) {
    if (!anotherResponse) return false;
    var normalizedSelf = JSON.stringify(this.normalizedBody);
    var normalizedAnother = JSON.stringify(anotherResponse.normalizedBody);
    return normalizedSelf == normalizedAnother;
  }
};

exports.ScenariosRunner = ScenariosRunner;
exports.ScenarioRunner = ScenarioRunner;
exports.Response = Response;
<commit_msg>Call teardown requests correctly<commit_after>var Client = require(__dirname + '/../lib/client').Client;
var EventEmitter = require('events').EventEmitter;
var xml2js = require('xml2js');

var statusCodeTable = {
  500: 'Inetnal Server Error',
  404: 'Not Found',
  409: 'Conflict',
  400: 'Bad Request',
  200: 'OK'
};

function ScenariosRunner(options) {
  this.options = options;
}

ScenariosRunner.prototype = new EventEmitter();

ScenariosRunner.prototype.run = function(scenarios) {
  var params = { scenarios: expandScenarios(scenarios) };
  this._process(params);
};

function cloneArray(array) {
  return array.map(function(aElement) {
    if (Array.isArray(aElement))
      return cloneArray(aElement);
    else
      return Object.create(aElement);
  });
};

function expandScenarios(scenarios) {
  if (!Array.isArray(scenarios))
    scenarios = [scenarios];

  var expanded = [];
  scenarios.forEach(function(scenario) {
    expanded = expanded.concat(expandScenario(scenario));
  });
  return expanded;
};
ScenariosRunner.expandScenarios =
  ScenarioRunner.expandScenarios = expandScenarios;

function expandScenario(scenario) {
  if (!scenario.requests)
    scenario = { requests: scenario };

  if (scenario.setup) {
    if (!Array.isArray(scenario.setup))
      scenario.setup = [scenario.setup];
  } else {
    scenario.setup = [];
  }

  if (scenario.teardown) {
    if (!Array.isArray(scenario.teardown))
      scenario.teardown = [scenario.teardown];
  } else {
    scenario.teardown = [];
  }

  var scenarios = [];
  scenario.requests.forEach(function(requests) {
    if (!Array.isArray(requests))
      requests = [requests];

    var expanded = Object.create(scenario);
    expanded.name = requests[0].name;
    expanded.requests = cloneArray(scenario.setup)
                          .concat(requests)
                          .concat(cloneArray(scenario.teardown));
    scenarios.push(expanded);
  });

  // make request names unique
  var names = {};
  scenarios.forEach(function(scenario) {
    scenario.requests.forEach(function(request) {
      request.name = scenario.name + ': ' + request.name;

      var count = 1;
      var name = request.name;
      while (name in names) {
        name = request.name + '-' + count++;
      }
      request.name = name;
      names[name] = true;
    });
  });

  return scenarios;
};
ScenariosRunner.expandScenario =
  ScenarioRunner.expandScenario = expandScenario;

ScenariosRunner.prototype._process = function(params) {
  if (!params.start) params.start = Date.now();
  var scenario = params.scenarios.shift();
  var self = this;

  var runner = new ScenarioRunner(this.options);

  runner.on('error:fatal', function(event) {
    self.emit('error:fatal', event);
  });

  runner.on('start', function(event) {
    self.emit('scenario', { runner: runner,
                            scenario: event.scenario });

    runner.on('end', function(event) {
      if (params.scenarios.length) {
        if (self.options.interval)
          setTimeout(function() { self._process(params); },
                     self.options.interval);
        else
          self._process(params);
      } else {
        var elapsedTime = Date.now() - params.start;
        self.emit('end', { elapsedTime: elapsedTime });
      }
    });
  });

  runner.run(scenario);
};

function ScenarioRunner(options) {
  this.client = new Client(options);
  this.options = options;
  if (options.documentEndpoint)
    this.client.docEndpoint = options.documentEndpoint;
}

ScenarioRunner.prototype = new EventEmitter();

ScenarioRunner.prototype.run = function(scenario) {
  var self = this;
  this.client.assertNoDomain(function(error) {
    if (error)
      self.emit('error:fatal', { error: error });
    else
      self._process(scenario);
  });
};

ScenarioRunner.prototype.assertNoDomain = function(callback) {
  this.client.assertNoDomain(function(error) {
    callback();
  });
};

ScenarioRunner.prototype.initializeScenario = function(scenario) {
  if (!scenario.requests)
    scenario = { requests: scenario };

  scenario.toBeProcessedRequests = scenario.requests.slice(0);
  scenario.start = Date.now();
  scenario.processed = {};

  return scenario;
};

ScenarioRunner.prototype._process = function(scenario, callback) {
  if (!scenario.toBeProcessedRequests) {
    scenario = this.initializeScenario(scenario);
    this.emit('start', { scenario: scenario });
  }

  var request = scenario.toBeProcessedRequests.shift();
  var self = this;
  function processNext() {
    if (scenario.toBeProcessedRequests.length) {
      self._process(scenario, callback);
    } else {
      var elapsedTime = Date.now() - scenario.start;
      var event = {
        elapsedTime: elapsedTime,
        scenario: scenario
      };
      self.emit('end', event);
    }
  }

  var name = request.name;
  var count = 1;
  while (name in scenario.processed) {
    name = request.name + count++;
  }

  this.emit('request:start', { scenario: scenario, request: request });

  this.client.rawConfigurationRequest(request.params.Action, request.params, function(error, response) {
    if (error) response = error;

    var statusCode = response.StatusCode;
    if (statusCode == 400) {
      var parser = new xml2js.Parser({ explicitRoot: true });
      parser.parseString(response.Body, function(error, result) {
        var errorCode = result.ErrorResponse.Error.Code;
        if (errorCode === 'Throttling') {
          self.emit('error:throttling');
        }
      });
    }
    if (!statusCodeTable[statusCode]) {
      self.emit('error:status_unknown', { statusCode: statusCode });
      if (callback)
        callback(statusCode, null);
      return;
    }

    var output = '';
    output += 'HTTP/1.1 ' + statusCode + ' ' + statusCodeTable[statusCode] + '\r\n';
    for (var key in response.Headers) {
      output += key + ': ' + response.Headers[key] + '\r\n';
    };
    output += '\r\n';
    output += response.Body.toString();

    request.response = output;
    self.emit('request:end', { scenario: scenario, request: request });
    if (self.options.interval)
      setTimeout(processNext, self.options.interval);
    else
      processNext();
  });
};

function toSafeName(name) {
  return name
           .replace(/[^a-zA-Z0-9]+/g, '-')
           .replace(/-$/, '');
};
ScenariosRunner.toSafeName =
  ScenarioRunner.toSafeName = toSafeName;

function Response(source) {
  source = source.split('\r\n\r\n');
  this.rawHeaders = source[0];
  this.rawBody = source.slice(1).join('\r\n\r\n');
}
Response.prototype = {
  get body() {
    if (!this._body) {
      if (/^\s*</.test(this.rawBody)) {
        this._body = this._XMLStringToJSON(this.rawBody);
      } else {
        try {
          this._body = JSON.parse(this.rawBody);
        } catch(error) {
          this._body = this.rawBody;
        }
      }
    }
    return this._body;
  },
  _XMLStringToJSON: function(xml) {
    var parser = new xml2js.Parser({
                   explicitRoot: true
                 });
    var json;
    parser.addListener('end', function(result) {
      json = result;
    });
    try {
      parser.parseString(xml);
    } catch (e) {
      console.log(xml);
      throw e;
    }
    return json;
  },

  get sortedBody() {
    if (!this._sortedBody) {
      if (this.body && typeof this.body == 'object')
        this._sortedBody = this._toSortedJSON(this.body, true);
      else
        this._sortedBody = this.body;
    }
    return this._sortedBody;
  },
  _toSortedJSON: function(fragment, doSort) {
    switch (typeof fragment) {
      default:
        return fragment;
      case 'object':
        var format = {};
        var keys = Object.keys(fragment);
        if (doSort) keys.sort();
        keys.forEach(function(key) {
          if (!fragment.hasOwnProperty(key))
            return;
          var doSort = this._orderedContainers.indexOf(key) < 0;
          format[key] = this._toSortedJSON(fragment[key], doSort);
        }, this);
        return format;
    }
  },
  _orderedContainers: [
    'DomainStatusList',
    'IndexFields',
    'FieldNames'
  ],

  get normalizedBody() {
    if (!this._normalizedBody)
      this._normalizedBody = this._normalize(this.sortedBody);
    return this._normalizedBody;
  },
  _normalize: function(fragment) {
    switch (typeof fragment) {
      default:
        return fragment;
      case 'object':
        var format = {};
        Object.keys(fragment).forEach(function(key) {
          if (!fragment.hasOwnProperty(key))
            return;

          var value = fragment[key];
          var normalized;
          switch (key) {
            case 'RequestId':
              normalized = '%REQUEST_ID%';
              break;

            case 'DomainId':
              normalized = value.replace(/^.+\//, '%DOMAIN_ID%/');
              break;

            case 'Endpoint':
              return; // this doesn't appear in ACS's response!

            case 'Arn':
              normalized = value.replace(/^(arn:aws:cs:us-east-1:)[^:]+(:[^\/]+\/[^\/]+)$/, '$1%DOMAIN_ID%$2');
              break;

            default:
              normalized = this._normalize(value);
              break;
          }
          format[key] = normalized;
        }, this);
        return format;
    }
  },

  equals: function(anotherResponse) {
    if (!anotherResponse) return false;
    var normalizedSelf = JSON.stringify(this.normalizedBody);
    var normalizedAnother = JSON.stringify(anotherResponse.normalizedBody);
    return normalizedSelf == normalizedAnother;
  }
};

exports.ScenariosRunner = ScenariosRunner;
exports.ScenarioRunner = ScenarioRunner;
exports.Response = Response;
<|endoftext|>


<commit_before>"use strict";

const inquirer  = require("inquirer");
const yaml = require("node-yaml");
const utils = require("../utils");
const fs = require("fs-promise");
const path = require("path");

const ServiceCollection = require("./service_collection");

const requiredConfig = {
  env_name: (str) => str.match(/^[a-z]+$/),
};

let containers;

function getContainerTypes() {
  if (!containers) {
    containers = utils.collectAnnotated(__dirname + "/containers", "id");
  }

  return containers;
}

class Environment {

  constructor(envConfig, root) {
    if (!root) {
      throw new Error("Environment root parameter is required.");
    }

    this._servicesInitialized = false;

    this._services = envConfig.services;
    this.config = envConfig.config;
    this.root = root;

    this._listeners = {};
  }

  static create(envConfigurator, config, root) {
    for (const [name, validate] of Object.entries(requiredConfig)) {
      if (!config.hasOwnProperty(name)) {
        throw Error(`'${name}' configuration value is required for environment.`);
      }

      if (!validate(config[name])) {
        throw Error(`'${name}' configuration value is invalid: '${config[name]}'`);
      }
    }

    return envConfigurator.configure().then((services) => {
      return new Environment({
        config: config,
        services: services,
      }, root);
    });
  }

  static load(root) {
    let configPath = root;

    return this.readConfig(configPath)
      .catch((err) => {
        configPath = path.join(root, Environment.DIRECTORIES.PROJECT);
        return this.readConfig(configPath);
      })
      .then((envConfig) => {
        let env = new Environment(envConfig, root);
        env.configFile = path.join(configPath, Environment.FILENAME);

        return env;
      })
      .catch((err) => {
        throw new Error(`Failed instantiating environment from config.\n` + err);
      });
  }

  static readConfig(root) {
    root = path.join(root, Environment.FILENAME);

    return yaml.read(root)
      .catch((err) => {
        throw new Error(`Failed reading environment config:\nPATH: ${root}\n` + err);
      });
  }

  get services() {
    if (this._servicesInitialized) {
      return this._services;
    }
    else {
      this._servicesInitialized = true;
    }

    if (!(this._services instanceof ServiceCollection)) {
      const availableServices = ServiceCollection.collect();
      const services = new ServiceCollection();

      for (let [id, serviceConfig] of Object.entries(this._services)) {
        const Service = availableServices.get(id);
        const service = new Service(serviceConfig);

        services.addService(service);
      }
      this._services = services;
    }

    this._services.each((service) => service.bindEnvironment(this));

    this._fireEvent("servicesInitialized", this._services);
    return this._services;
  }

  static hasEnvironment(directory) {
    return fs.exists(path.join(directory, Environment.FILENAME));
  }

  getServiceOperations() {
    let opNames = {};
    let operations = [];

    this.services.each((service) => {
      service.getOperations().forEach((operation) => {
        if (opNames.hasOwnProperty(operation.name)) {
          throw new Error(`Duplicate service operation name detected: '${operation.name}'.\nDefined by: '${service.ann("id")}' and '${opNames[operation.name]}'.`)
        }

        opNames[operation.name] = service.ann("id");
        operation.push(operation);
      })
    });

    return operations;
  }

  save(includeInProject = true) {
    includeInProject = includeInProject ? Environment.DIRECTORIES.PROJECT : "";
    const saveTo = path.join(this.root, includeInProject, Environment.FILENAME);

    let environment = {
      config: this.config,
      services: {},
    };

    this.services.each((service, id) => {
      environment.services[id] = service.config;
    });

    let promise = Promise.resolve();
    if (this.configFile && this.configFile !== saveTo) {
      promise = fs.unlink(this.configFile)
        .catch((err) => {
          throw new Error("Failed removing old environment config file:\n" + err);
        });
    }
    else if(!this.configFile) {
      promise = this._createStructure();
    }

    return promise.then(() => {
        return yaml.write(saveTo, environment);
      })
      .then(() => {
        return this;
      })
      .catch((err) => {
        throw new Error("Failed to save environment configuration.\n" + err);
      });
  }

  composeContainer(containerType) {
    if (containerType == "*") {
      let promises = [];

      for (let [, Container] of Object.entries(getContainerTypes())) {
        let cont = new Container(this);
        promises.push(cont.writeComposition());
      }

      return Promise.all(promises);
    }

    let container = this.getContainer(containerType);
    let promise = container.writeComposition();

    return promise.then(() => {
        return container;
      }).catch((err) => {
        throw new Error(`Failed writing ${container.ann("id")} container composition: ` + err);
      });
  }

  getContainer(containerType) {
    let containers = getContainerTypes();

    if (!containers[containerType]) {
      throw new Error("Unknown container type: " + containerType);
    }

    return new containers[containerType](this);
  }

  writeServiceConfigFiles() {
    let promises = [];

    this.services.each((service) => {
      promises.push(service.writeConfigFiles(this.root));
    });

    return Promise.all(promises)
      .catch((err) => {
        throw new Error(`Failed creating configuration files for services.\n` + err);
      });
  }

  _createStructure() {
    return fs.ensureDir(this.root).then(() => {
      return Promise.all(
        Object.keys(Environment.DIRECTORIES).map((dirKey) => {
          return fs.ensureDir(path.join(this.root, Environment.DIRECTORIES[dirKey]));
        })
      );
    });
  }

  _fireEvent(eventType, ...args) {
    if (this._listeners[eventType]) {
      this._listeners[eventType].forEach((callback) => callback(...args));
    }

    return this;
  }

  on(eventType, callback) {
    if (typeof callback !== "function") {
      throw new Error("Callback must be a function.");
    }

    if (!this._listeners[eventType]) {
      this._listeners[eventType] = [];
    }

    this._listeners[eventType].push(callback);
    return this;
  }

}

Environment.FILENAME = ".drup-env.yml";
Environment.DIRECTORIES = {
  CONFIG: "config",
  DATA: "data",
  LOG: "log",
  PROJECT: "project",
};

module.exports = Environment;
<commit_msg>Allows services to provide operations.<commit_after>"use strict";

const inquirer  = require("inquirer");
const yaml = require("node-yaml");
const utils = require("../utils");
const fs = require("fs-promise");
const path = require("path");

const ServiceCollection = require("./service_collection");

const requiredConfig = {
  env_name: (str) => str.match(/^[a-z]+$/),
};

let containers;

function getContainerTypes() {
  if (!containers) {
    containers = utils.collectAnnotated(__dirname + "/containers", "id");
  }

  return containers;
}

class Environment {

  constructor(envConfig, root) {
    if (!root) {
      throw new Error("Environment root parameter is required.");
    }

    this._servicesInitialized = false;

    this._services = envConfig.services;
    this.config = envConfig.config;
    this.root = root;

    this._listeners = {};
  }

  static create(envConfigurator, config, root) {
    for (const [name, validate] of Object.entries(requiredConfig)) {
      if (!config.hasOwnProperty(name)) {
        throw Error(`'${name}' configuration value is required for environment.`);
      }

      if (!validate(config[name])) {
        throw Error(`'${name}' configuration value is invalid: '${config[name]}'`);
      }
    }

    return envConfigurator.configure().then((services) => {
      return new Environment({
        config: config,
        services: services,
      }, root);
    });
  }

  static load(root) {
    let configPath = root;

    return this.readConfig(configPath)
      .catch((err) => {
        configPath = path.join(root, Environment.DIRECTORIES.PROJECT);
        return this.readConfig(configPath);
      })
      .then((envConfig) => {
        let env = new Environment(envConfig, root);
        env.configFile = path.join(configPath, Environment.FILENAME);

        return env;
      })
      .catch((err) => {
        throw new Error(`Failed instantiating environment from config.\n` + err);
      });
  }

  static readConfig(root) {
    root = path.join(root, Environment.FILENAME);

    return yaml.read(root)
      .catch((err) => {
        throw new Error(`Failed reading environment config:\nPATH: ${root}\n` + err);
      });
  }

  get services() {
    if (this._servicesInitialized) {
      return this._services;
    }
    else {
      this._servicesInitialized = true;
    }

    if (!(this._services instanceof ServiceCollection)) {
      const availableServices = ServiceCollection.collect();
      const services = new ServiceCollection();

      for (let [id, serviceConfig] of Object.entries(this._services)) {
        const Service = availableServices.get(id);
        const service = new Service(serviceConfig);

        services.addService(service);
      }
      this._services = services;
    }

    this._services.each((service) => service.bindEnvironment(this));

    this._fireEvent("servicesInitialized", this._services);
    return this._services;
  }

  static hasEnvironment(directory) {
    return fs.exists(path.join(directory, Environment.FILENAME));
  }

  getServiceOperations() {
    let opNames = {};
    let operations = [];

    this.services.each((service) => {
      service.getOperations().forEach((operation) => {
        if (opNames.hasOwnProperty(operation.name)) {
          throw new Error(`Duplicate service operation name detected: '${operation.name}'.\nDefined by: '${service.ann("id")}' and '${opNames[operation.name]}'.`)
        }

        opNames[operation.name] = service.ann("id");
        operation.service = service.ann("id");
        operation.push(operation);
      })
    });

    return operations;
  }

  runServiceOperation(op, args) {
    this.services.get(op.service).runOperation(op.name, args);
  }

  save(includeInProject = true) {
    includeInProject = includeInProject ? Environment.DIRECTORIES.PROJECT : "";
    const saveTo = path.join(this.root, includeInProject, Environment.FILENAME);

    let environment = {
      config: this.config,
      services: {},
    };

    this.services.each((service, id) => {
      environment.services[id] = service.config;
    });

    let promise = Promise.resolve();
    if (this.configFile && this.configFile !== saveTo) {
      promise = fs.unlink(this.configFile)
        .catch((err) => {
          throw new Error("Failed removing old environment config file:\n" + err);
        });
    }
    else if(!this.configFile) {
      promise = this._createStructure();
    }

    return promise.then(() => {
        return yaml.write(saveTo, environment);
      })
      .then(() => {
        return this;
      })
      .catch((err) => {
        throw new Error("Failed to save environment configuration.\n" + err);
      });
  }

  composeContainer(containerType) {
    if (containerType == "*") {
      let promises = [];

      for (let [, Container] of Object.entries(getContainerTypes())) {
        let cont = new Container(this);
        promises.push(cont.writeComposition());
      }

      return Promise.all(promises);
    }

    let container = this.getContainer(containerType);
    let promise = container.writeComposition();

    return promise.then(() => {
        return container;
      }).catch((err) => {
        throw new Error(`Failed writing ${container.ann("id")} container composition: ` + err);
      });
  }

  getContainer(containerType) {
    let containers = getContainerTypes();

    if (!containers[containerType]) {
      throw new Error("Unknown container type: " + containerType);
    }

    return new containers[containerType](this);
  }

  writeServiceConfigFiles() {
    let promises = [];

    this.services.each((service) => {
      promises.push(service.writeConfigFiles(this.root));
    });

    return Promise.all(promises)
      .catch((err) => {
        throw new Error(`Failed creating configuration files for services.\n` + err);
      });
  }

  _createStructure() {
    return fs.ensureDir(this.root).then(() => {
      return Promise.all(
        Object.keys(Environment.DIRECTORIES).map((dirKey) => {
          return fs.ensureDir(path.join(this.root, Environment.DIRECTORIES[dirKey]));
        })
      );
    });
  }

  _fireEvent(eventType, ...args) {
    if (this._listeners[eventType]) {
      this._listeners[eventType].forEach((callback) => callback(...args));
    }

    return this;
  }

  on(eventType, callback) {
    if (typeof callback !== "function") {
      throw new Error("Callback must be a function.");
    }

    if (!this._listeners[eventType]) {
      this._listeners[eventType] = [];
    }

    this._listeners[eventType].push(callback);
    return this;
  }

}

Environment.FILENAME = ".drup-env.yml";
Environment.DIRECTORIES = {
  CONFIG: "config",
  DATA: "data",
  LOG: "log",
  PROJECT: "project",
};

module.exports = Environment;
<|endoftext|>


<commit_before>var Client = require(__dirname + '/../lib/client').Client;
var EventEmitter = require('events').EventEmitter;
var xml2js = require('xml2js');

var statusCodeTable = {
  500: 'Inetnal Server Error',
  404: 'Not Found',
  409: 'Conflict',
  400: 'Bad Request',
  200: 'OK'
};

function ScenariosRunner(options) {
  this.options = options;
}

ScenariosRunner.prototype = new EventEmitter();

ScenariosRunner.prototype.run = function(scenario) {
  this._process({ scenarios: scenario });
};

ScenariosRunner.prototype._process = function(params) {
  if (!params.start) params.start = Date.now();
  var scenario = params.scenarios.shift();
  var self = this;

  var runner = new ScenarioRunner(this.options);

  runner.on('error:fatal', function(event) {
    self.emit('error:fatal', event);
  });

  runner.on('start', function(event) {
    self.emit('scenario', { runner: runner,
                            scenario: event.scenario });

    runner.on('end', function(event) {
      if (params.scenarios.length) {
        if (self.options.interval)
          setTimeout(function() { self._process(params); },
                     self.options.interval);
        else
          self._process(params);
      } else {
        var elapsedTime = Date.now() - params.start;
        self.emit('end', { elapsedTime: elapsedTime });
      }
    });
  });

  runner.run(scenario);
};

function ScenarioRunner(options) {
  this.client = new Client(options);
  this.options = options;
  if (options.documentEndpoint)
    this.client.docEndpoint = options.documentEndpoint;
}

ScenarioRunner.prototype = new EventEmitter();

ScenarioRunner.prototype.run = function(scenario) {
  var self = this;
  this.client.assertNoDomain(function(error) {
    if (error)
      self.emit('error:fatal', { error: error });
    else
      self._process(scenario);
  });
};

ScenarioRunner.prototype.assertNoDomain = function(callback) {
  this.client.assertNoDomain(function(error) {
    callback();
  });
};

ScenarioRunner.prototype._process = function(scenario, callback) {
  if (!scenario.toBeProcessedRequests) {
    scenario.toBeProcessedRequests = scenario.requests.slice(0);
    scenario.start = Date.now();
    scenario.processed = {};
    this.emit('start', { scenario: scenario });
  }

  var request = scenario.toBeProcessedRequests.shift();
  var self = this;
  function processNext() {
    if (scenario.toBeProcessedRequests.length) {
      self._process(scenario, callback);
    } else {
      var elapsedTime = Date.now() - scenario.start;
      var event = {
        elapsedTime: elapsedTime,
        scenario: scenario
      };
      self.emit('end', event);
    }
  }

  var name = request.name;
  var count = 1;
  while (name in scenario.processed) {
    name = request.name + count++;
  }

  this.emit('request:start', { scenario: scenario, request: request });

  this.client.rawConfigurationRequest(request.params.Action, request.params, function(error, response) {
    if (error) response = error;

    var statusCode = response.StatusCode;
    if (statusCode == 400) {
      var parser = new xml2js.Parser({ explicitRoot: true });
      parser.parseString(response.Body, function(error, result) {
        var errorCode = result.ErrorResponse.Error.Code;
        if (errorCode === 'Throttling') {
          self.emit('error:throttling');
        }
      });
    }
    if (!statusCodeTable[statusCode]) {
      self.emit('error:status_unknown', { statusCode: statusCode });
      if (callback)
        callback(statusCode, null);
      return;
    }

    var output = '';
    output += 'HTTP/1.1 ' + statusCode + ' ' + statusCodeTable[statusCode] + '\r\n';
    for (var key in response.Headers) {
      output += key + ': ' + response.Headers[key] + '\r\n';
    };
    output += '\r\n';
    output += response.Body.toString();

    request.response = output;
    self.emit('request:end', { scenario: scenario, request: request });
    if (self.options.interval)
      setTimeout(processNext, self.options.interval);
    else
      processNext();
  });
};

function toSafeName(name) {
  return name
           .replace(/[^a-zA-Z0-9]+/g, '-')
           .replace(/-$/, '');
};
ScenariosRunner.toSafeName =
  ScenarioRunner.toSafeName = toSafeName;

function Response(source) {
  source = source.split('\r\n\r\n');
  this.rawHeaders = source[0];
  this.rawBody = source.slice(1).join('\r\n\r\n');
}
Response.prototype = {
  get body() {
    if (!this._body) {
      if (this.rawBody.indexOf('<?xml') == 0) {
        this._body = this._XMLStringToJSON(this.rawBody);
      } else {
        try {
          this._body = JSON.parse(this.rawBody);
        } catch(error) {
          this._body = this.rawBody;
        }
      }
    }
    return this._body;
  },
  _XMLStringToJSON: function(xml) {
    var parser = new xml2js.Parser({
                   explicitRoot: true
                 });
    var json;
    parser.addListener('end', function(result) {
      json = result;
    });
    try {
      parser.parseString(xml);
    } catch (e) {
      console.log(xml);
      throw e;
    }
    return json;
  },

  get sortedBody() {
    if (!this._sortedBody) {
      if (this.body && typeof this.body == 'object')
        this._sortedBody = this._toSortedJSON(this.body, false);
      else
        this._sortedBody = this.body;
    }
    return this._sortedBody;
  },
  _toSortedJSON: function(fragment, doSort) {
    switch (typeof fragment) {
      default:
        return fragment;
      case 'object':
        var format = {};
        var keys = Object.keys(fragment);
        if (!doSort) keys.sort();
        keys.forEach(function(key) {
          if (!fragment.hasOwnProperty(key))
            return;
          var doSort = this._orderedContainers.indexOf(key) < 0;
          format[key] = this._toSortedJSON(fragment[key], doSort);
        }, this);
        return format;
    }
  },
  _orderedContainers: [
    'DomainStatusList',
    'IndexFields',
    'FieldNames'
  ],

  get normalizedBody() {
    if (!this._normalizedBody)
      this._normalizedBody = this._normalize(this.sortedBody);
    return this._normalizedBody;
  },
  _normalize: function(fragment) {
    switch (typeof fragment) {
      default:
        return fragment;
      case 'object':
        var format = {};
        Object.keys(fragment).forEach(function(key) {
          if (!fragment.hasOwnProperty(key))
            return;

          var value = fragment[key];
          var normalized;
          switch (key) {
            case 'RequestId':
              normalized = '%REQUEST_ID%';
              break;

            case 'DomainId':
              normalized = value.replace(/^.+\//, '%DOMAIN_ID%/');
              break;

            case 'Endpoint':
              return; // this doesn't appear in ACS's response!

            case 'Arn':
              normalized = value.replace(/^(arn:aws:cs:us-east-1:)[^:]+(:[^\/]+\/[^\/]+)$/, '$1%DOMAIN_ID%$2');
              break;

            default:
              normalized = this._normalize(value);
              break;
          }
          format[key] = normalized;
        }, this);
        return format;
    }
  }
};

exports.ScenariosRunner = ScenariosRunner;
exports.ScenarioRunner = ScenarioRunner;
exports.Response = Response;
<commit_msg>Detect XML without XML declaration correctly<commit_after>var Client = require(__dirname + '/../lib/client').Client;
var EventEmitter = require('events').EventEmitter;
var xml2js = require('xml2js');

var statusCodeTable = {
  500: 'Inetnal Server Error',
  404: 'Not Found',
  409: 'Conflict',
  400: 'Bad Request',
  200: 'OK'
};

function ScenariosRunner(options) {
  this.options = options;
}

ScenariosRunner.prototype = new EventEmitter();

ScenariosRunner.prototype.run = function(scenario) {
  this._process({ scenarios: scenario });
};

ScenariosRunner.prototype._process = function(params) {
  if (!params.start) params.start = Date.now();
  var scenario = params.scenarios.shift();
  var self = this;

  var runner = new ScenarioRunner(this.options);

  runner.on('error:fatal', function(event) {
    self.emit('error:fatal', event);
  });

  runner.on('start', function(event) {
    self.emit('scenario', { runner: runner,
                            scenario: event.scenario });

    runner.on('end', function(event) {
      if (params.scenarios.length) {
        if (self.options.interval)
          setTimeout(function() { self._process(params); },
                     self.options.interval);
        else
          self._process(params);
      } else {
        var elapsedTime = Date.now() - params.start;
        self.emit('end', { elapsedTime: elapsedTime });
      }
    });
  });

  runner.run(scenario);
};

function ScenarioRunner(options) {
  this.client = new Client(options);
  this.options = options;
  if (options.documentEndpoint)
    this.client.docEndpoint = options.documentEndpoint;
}

ScenarioRunner.prototype = new EventEmitter();

ScenarioRunner.prototype.run = function(scenario) {
  var self = this;
  this.client.assertNoDomain(function(error) {
    if (error)
      self.emit('error:fatal', { error: error });
    else
      self._process(scenario);
  });
};

ScenarioRunner.prototype.assertNoDomain = function(callback) {
  this.client.assertNoDomain(function(error) {
    callback();
  });
};

ScenarioRunner.prototype._process = function(scenario, callback) {
  if (!scenario.toBeProcessedRequests) {
    scenario.toBeProcessedRequests = scenario.requests.slice(0);
    scenario.start = Date.now();
    scenario.processed = {};
    this.emit('start', { scenario: scenario });
  }

  var request = scenario.toBeProcessedRequests.shift();
  var self = this;
  function processNext() {
    if (scenario.toBeProcessedRequests.length) {
      self._process(scenario, callback);
    } else {
      var elapsedTime = Date.now() - scenario.start;
      var event = {
        elapsedTime: elapsedTime,
        scenario: scenario
      };
      self.emit('end', event);
    }
  }

  var name = request.name;
  var count = 1;
  while (name in scenario.processed) {
    name = request.name + count++;
  }

  this.emit('request:start', { scenario: scenario, request: request });

  this.client.rawConfigurationRequest(request.params.Action, request.params, function(error, response) {
    if (error) response = error;

    var statusCode = response.StatusCode;
    if (statusCode == 400) {
      var parser = new xml2js.Parser({ explicitRoot: true });
      parser.parseString(response.Body, function(error, result) {
        var errorCode = result.ErrorResponse.Error.Code;
        if (errorCode === 'Throttling') {
          self.emit('error:throttling');
        }
      });
    }
    if (!statusCodeTable[statusCode]) {
      self.emit('error:status_unknown', { statusCode: statusCode });
      if (callback)
        callback(statusCode, null);
      return;
    }

    var output = '';
    output += 'HTTP/1.1 ' + statusCode + ' ' + statusCodeTable[statusCode] + '\r\n';
    for (var key in response.Headers) {
      output += key + ': ' + response.Headers[key] + '\r\n';
    };
    output += '\r\n';
    output += response.Body.toString();

    request.response = output;
    self.emit('request:end', { scenario: scenario, request: request });
    if (self.options.interval)
      setTimeout(processNext, self.options.interval);
    else
      processNext();
  });
};

function toSafeName(name) {
  return name
           .replace(/[^a-zA-Z0-9]+/g, '-')
           .replace(/-$/, '');
};
ScenariosRunner.toSafeName =
  ScenarioRunner.toSafeName = toSafeName;

function Response(source) {
  source = source.split('\r\n\r\n');
  this.rawHeaders = source[0];
  this.rawBody = source.slice(1).join('\r\n\r\n');
}
Response.prototype = {
  get body() {
    if (!this._body) {
      if (/^\s*</.test(this.rawBody)) {
        this._body = this._XMLStringToJSON(this.rawBody);
      } else {
        try {
          this._body = JSON.parse(this.rawBody);
        } catch(error) {
          this._body = this.rawBody;
        }
      }
    }
    return this._body;
  },
  _XMLStringToJSON: function(xml) {
    var parser = new xml2js.Parser({
                   explicitRoot: true
                 });
    var json;
    parser.addListener('end', function(result) {
      json = result;
    });
    try {
      parser.parseString(xml);
    } catch (e) {
      console.log(xml);
      throw e;
    }
    return json;
  },

  get sortedBody() {
    if (!this._sortedBody) {
      if (this.body && typeof this.body == 'object')
        this._sortedBody = this._toSortedJSON(this.body, false);
      else
        this._sortedBody = this.body;
    }
    return this._sortedBody;
  },
  _toSortedJSON: function(fragment, doSort) {
    switch (typeof fragment) {
      default:
        return fragment;
      case 'object':
        var format = {};
        var keys = Object.keys(fragment);
        if (!doSort) keys.sort();
        keys.forEach(function(key) {
          if (!fragment.hasOwnProperty(key))
            return;
          var doSort = this._orderedContainers.indexOf(key) < 0;
          format[key] = this._toSortedJSON(fragment[key], doSort);
        }, this);
        return format;
    }
  },
  _orderedContainers: [
    'DomainStatusList',
    'IndexFields',
    'FieldNames'
  ],

  get normalizedBody() {
    if (!this._normalizedBody)
      this._normalizedBody = this._normalize(this.sortedBody);
    return this._normalizedBody;
  },
  _normalize: function(fragment) {
    switch (typeof fragment) {
      default:
        return fragment;
      case 'object':
        var format = {};
        Object.keys(fragment).forEach(function(key) {
          if (!fragment.hasOwnProperty(key))
            return;

          var value = fragment[key];
          var normalized;
          switch (key) {
            case 'RequestId':
              normalized = '%REQUEST_ID%';
              break;

            case 'DomainId':
              normalized = value.replace(/^.+\//, '%DOMAIN_ID%/');
              break;

            case 'Endpoint':
              return; // this doesn't appear in ACS's response!

            case 'Arn':
              normalized = value.replace(/^(arn:aws:cs:us-east-1:)[^:]+(:[^\/]+\/[^\/]+)$/, '$1%DOMAIN_ID%$2');
              break;

            default:
              normalized = this._normalize(value);
              break;
          }
          format[key] = normalized;
        }, this);
        return format;
    }
  }
};

exports.ScenariosRunner = ScenariosRunner;
exports.ScenarioRunner = ScenarioRunner;
exports.Response = Response;
<|endoftext|>


<commit_before>var render = {
  roots: [],
  templates: {},
  cache: {}
}
var unloaders = [],
  cached = [],
  pendingRequests = 0

  function callView(elementClone, module, i) {
    var args = module.getArgs(i)

    var mod = module.modules[i]
    var controller = module.controllers[i]

    // var controllerConstructor = mod.controller.$original || mod.controller
    // var controller = controllerConstructor === cached.controllerConstructor ? cached.controller : new(mod.controller || function() {})

    mod.view(elementClone, controller)

    // if (controller.onunload) unloaders.push({
    //   controller: controller,
    //   handler: controller.onunload
    // })
  }
render.callConfigs = function() {
  //for (var i = 0, len = configs.length; i < len; i++) configs[i]()
}
render.redraw = function(module) {
  module = module || render.module || {}
  this.fun || (this.fun = debounce(function() {
    var prev
    for (var i = 0, root; root = render.roots[i]; i++) {
      if (module.controllers[i]) {
        var elementClone = module.elements[i]

        callView(elementClone, module, i)
        var args = module.getArgs(i)

        watch(args[0], debounce(function(ele, i, module, prop, type, newVal, oldVal) {
          console.time('Mag.JS:re-render')
          var args = module.getArgs(i)

          // check if data changed
          if (prev !== JSON.stringify(args[0])) {
            callView(ele, module, i)
            fill(ele, args[0])
            WatchJS.noMore = true
            render.callConfigs()
            prev = JSON.stringify(args[0])
          }
          console.timeEnd('Mag.JS:re-render')
        }.bind(null, elementClone, i, module)))

        fill(elementClone, args[0])
        render.callConfigs()
        prev = JSON.stringify(args[0])
      }
    }
    console.timeEnd("MagnumJS:init")
  }))
  this.fun()
}

var $cancelAnimationFrame = window.cancelAnimationFrame || window.clearTimeout;
var $requestAnimationFrame = window.requestAnimationFrame || window.setTimeout;

var debounce = function(fn, threshhold) {
  var lastRedrawCallTime, FRAME_BUDGET = threshhold || 16,
    deferTimer

  return function() {
    if (+new Date - lastRedrawCallTime > FRAME_BUDGET || $requestAnimationFrame === window.requestAnimationFrame) {
      // hold on to it
      if (deferTimer > 0) $cancelAnimationFrame(deferTimer)

      deferTimer = $requestAnimationFrame(function() {
        lastRedrawCallTime = +new Date
        fn.apply(this, arguments);
      }, FRAME_BUDGET);
    } else {
      lastRedrawCallTime = +new Date
      fn.apply(this, arguments);
    }
  }
}
<commit_msg>Update render.js<commit_after>mag = (function(mag) {

  var render = {
    roots: [],
    templates: {},
    cache: {}
  }

  var unloaders = [],
    cached = [],
    pendingRequests = 0

    function callView(elementClone, module, i) {
      var args = module.getArgs(i)

      var mod = module.modules[i]
      var controller = module.controllers[i]

      // var controllerConstructor = mod.controller.$original || mod.controller
      // var controller = controllerConstructor === cached.controllerConstructor ? cached.controller : new(mod.controller || function() {})

      mod.view(elementClone, controller)

      // if (controller.onunload) unloaders.push({
      //   controller: controller,
      //   handler: controller.onunload
      // })
    }
  render.callConfigs = function(configs) {
    //for (var i = 0, len = configs.length; i < len; i++) configs[i]()
  }
  render.redraw = function(module, fill, WatchJS) {
    module = module || render.module || {}
    console.time('Mag.JS:render')
    this.fun || (this.fun = debounce(function() {
      var prev
      for (var i = 0, root; root = render.roots[i]; i++) {
        if (module.controllers[i]) {
          var elementClone = module.elements[i]

          callView(elementClone, module, i)
          var args = module.getArgs(i)

          WatchJS.watch(args[0], debounce(function(ele, i, module, prop, type, newVal, oldVal) {
            console.time('Mag.JS:re-render')
            var args = module.getArgs(i)

            // check if data changed
            if (prev !== JSON.stringify(args[0])) {
              callView(ele, module, i)
              fill.fill(ele, args[0])
              WatchJS.noMore = true
              render.callConfigs(fill.configs)
              prev = JSON.stringify(args[0])
            }
            console.timeEnd('Mag.JS:re-render')
          }.bind(null, elementClone, i, module)))

          fill.fill(elementClone, args[0])
          render.callConfigs(fill.configs)
          prev = JSON.stringify(args[0])
        }
      }
      console.timeEnd("MagnumJS:init")
      console.timeEnd('Mag.JS:render')
    }))
    this.fun()
  }

  var $cancelAnimationFrame = window.cancelAnimationFrame || window.clearTimeout;
  var $requestAnimationFrame = window.requestAnimationFrame || window.setTimeout;

  var debounce = function(fn, threshhold) {
    var lastRedrawCallTime, FRAME_BUDGET = threshhold || 16,
      deferTimer

    return function() {
      if (+new Date - lastRedrawCallTime > FRAME_BUDGET || $requestAnimationFrame === window.requestAnimationFrame) {
        // hold on to it
        if (deferTimer > 0) $cancelAnimationFrame(deferTimer)

        deferTimer = $requestAnimationFrame(function() {
          lastRedrawCallTime = +new Date
          fn.apply(this, arguments);
        }, FRAME_BUDGET);
      } else {
        lastRedrawCallTime = +new Date
        fn.apply(this, arguments);
      }
    }
  }

  mag.render = render
  return mag

}(window.mag || {}))
<|endoftext|>


<commit_before>/*
* (C) Copyright IBM Corp. 2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

var BotSDK = require('@watson-virtual-agent/client-sdk/lib/web');
var state = require('../../state');
var events = require('../../events');
var utils = require('../../utils');
var assign = require('lodash/assign');
var templates = require('../../templates');

function _actions(data, tryIt, debug) {
  var msg = data.message;
  if (msg && msg.action && msg.action.name) {
    var action = 'action:' + msg.action.name;
    if (events.hasSubscription(action)) {
      events.publish(action, data, events.completeEvent);
      if (debug)
        console.log('Call to ' + action);
    } else {
      if (debug)
        console.warn('Nothing is subscribed to ' + action);
      if (tryIt)
        events.publish('try-it-action-subscription', action);
    }
  }
  events.publish('disable-loading');
  events.publish('focus-input');
  setTimeout(function() {
    events.publish('scroll-to-bottom');
  }, 20);
}

function _layouts(data, tryIt, debug) {
  var msg = data.message;
  if (msg && msg.layout && msg.layout.name) {
    var layout = 'layout:' + msg.layout.name;
    if (events.hasSubscription(layout)) {
      setTimeout(function() {
        events.publish(layout, data);
        if (debug)
          console.log('Call to ' + layout);
      }, 10);
    } else {
      if (debug)
        console.warn('Nothing is subscribed to ' + layout);
      if (tryIt)
        events.publish('try-it-layout-subscription', layout);
    }
  }
}

function _intents(data) {
  var msg = data.message;
  if (msg && msg.intents && msg.intents.length > 0 && msg.intents[0].intent) {
    events.publish('try-it-get-intent-data', {
      element: data.intentElement,
      intent: msg.intents[0].intent
    });
  }
}

function receive(data) {
  var parsed = (typeof data === 'string') ? { message: { text: data } } : data;
  parsed = BotSDK.parse(parsed);
  var current = state.get();
  state.set({
    messages: [].concat(current.messages || [], parsed),
    hasError: false
  });
  var msg = parsed.message;
  var msgText = (msg && msg.text) ? ((Array.isArray(msg.text) && msg.text.length > 0) ? msg.text : [msg.text]) : [''];
  var containers = [];
  var messages = [];
  var layouts = [];
  var intents = [];
  var datas = [];
  for (var i = 0; i < msgText.length; i++) {
    var holder = document.createElement('div');
    var msgData = assign({}, parsed, { uuid: utils.getUUID() });
    holder.classList.add(msgData.uuid);
    holder.innerHTML = templates.receive;
    containers.push(holder.querySelector('.IBMChat-watson-message-container'));
    messages.push(document.createElement('div'));
    layouts.push(document.createElement('div'));
    layouts[i].classList.add('IBMChat-watson-layout');
    if (current.tryIt) {
      intents.push(document.createElement('div'));
      intents[i].classList.add('IBMChat-watson-intent');
    }
    if ((msgText[i] && msgText[i].length > 0) || (msg && msg.layout && msg.layout.name && i === (msgText.length - 1))) {
      messages[i].classList.add('IBMChat-watson-message');
      messages[i].classList.add('IBMChat-watson-message-theme');
      utils.writeMessage(messages[i], msgText[i]);
      current.chatHolder.appendChild(holder);
    }
    containers[i].appendChild(messages[i]);
    if (current.tryIt)
      containers[i].appendChild(intents[i]);
    containers[i].appendChild(layouts[i]);
    msgData.element = containers[i];
    msgData.layoutElement = layouts[i];
    msgData.msgElement = messages[i];
    if (current.tryIt)
      msgData.intentElement = intents[i];
    datas.push(msgData);
    if (i === 0 && current.tryIt)
      _intents(datas[i]);
    if (msg && msg.layout && ((msg.layout.index !== undefined && msg.layout.index == i) ||(msg.layout.index === undefined && i == (msgText.length - 1))))
      _layouts(datas[i], current.tryIt, current.DEBUG);
    if (i === (msgText.length - 1))
      _actions(datas[i], current.tryIt, current.DEBUG);

  }

}

module.exports = receive;
<commit_msg>New intent link API(feat): getting info from log_data<commit_after>/*
* (C) Copyright IBM Corp. 2016. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

var BotSDK = require('@watson-virtual-agent/client-sdk/lib/web');
var state = require('../../state');
var events = require('../../events');
var utils = require('../../utils');
var assign = require('lodash/assign');
var templates = require('../../templates');

function _actions(data, tryIt, debug) {
  var msg = data.message;
  if (msg && msg.action && msg.action.name) {
    var action = 'action:' + msg.action.name;
    if (events.hasSubscription(action)) {
      events.publish(action, data, events.completeEvent);
      if (debug)
        console.log('Call to ' + action);
    } else {
      if (debug)
        console.warn('Nothing is subscribed to ' + action);
      if (tryIt)
        events.publish('try-it-action-subscription', action);
    }
  }
  events.publish('disable-loading');
  events.publish('focus-input');
  setTimeout(function() {
    events.publish('scroll-to-bottom');
  }, 20);
}

function _layouts(data, tryIt, debug) {
  var msg = data.message;
  if (msg && msg.layout && msg.layout.name) {
    var layout = 'layout:' + msg.layout.name;
    if (events.hasSubscription(layout)) {
      setTimeout(function() {
        events.publish(layout, data);
        if (debug)
          console.log('Call to ' + layout);
      }, 10);
    } else {
      if (debug)
        console.warn('Nothing is subscribed to ' + layout);
      if (tryIt)
        events.publish('try-it-layout-subscription', layout);
    }
  }
}

function _intents(data) {
  var msg = data.message;
  if (msg && msg.log_data && msg.log_data.intents && msg.log_data.intents.length > 0 && msg.log_data.intents[0].intent && msg.log_data.showIntentLink) {
    events.publish('try-it-get-intent-data', {
      element: data.intentElement,
      intent: msg.log_data.intents[0].intent
    });
  }
}

function receive(data) {
  var parsed = (typeof data === 'string') ? { message: { text: data } } : data;
  parsed = BotSDK.parse(parsed);
  var current = state.get();
  state.set({
    messages: [].concat(current.messages || [], parsed),
    hasError: false
  });
  var msg = parsed.message;
  var msgText = (msg && msg.text) ? ((Array.isArray(msg.text) && msg.text.length > 0) ? msg.text : [msg.text]) : [''];
  var containers = [];
  var messages = [];
  var layouts = [];
  var intents = [];
  var datas = [];
  for (var i = 0; i < msgText.length; i++) {
    var holder = document.createElement('div');
    var msgData = assign({}, parsed, { uuid: utils.getUUID() });
    holder.classList.add(msgData.uuid);
    holder.innerHTML = templates.receive;
    containers.push(holder.querySelector('.IBMChat-watson-message-container'));
    messages.push(document.createElement('div'));
    layouts.push(document.createElement('div'));
    layouts[i].classList.add('IBMChat-watson-layout');
    if (current.tryIt) {
      intents.push(document.createElement('div'));
      intents[i].classList.add('IBMChat-watson-intent');
    }
    if ((msgText[i] && msgText[i].length > 0) || (msg && msg.layout && msg.layout.name && i === (msgText.length - 1))) {
      messages[i].classList.add('IBMChat-watson-message');
      messages[i].classList.add('IBMChat-watson-message-theme');
      utils.writeMessage(messages[i], msgText[i]);
      current.chatHolder.appendChild(holder);
    }
    containers[i].appendChild(messages[i]);
    if (current.tryIt)
      containers[i].appendChild(intents[i]);
    containers[i].appendChild(layouts[i]);
    msgData.element = containers[i];
    msgData.layoutElement = layouts[i];
    msgData.msgElement = messages[i];
    if (current.tryIt)
      msgData.intentElement = intents[i];
    datas.push(msgData);
    if (i === 0 && current.tryIt)
      _intents(datas[i]);
    if (msg && msg.layout && ((msg.layout.index !== undefined && msg.layout.index == i) ||(msg.layout.index === undefined && i == (msgText.length - 1))))
      _layouts(datas[i], current.tryIt, current.DEBUG);
    if (i === (msgText.length - 1))
      _actions(datas[i], current.tryIt, current.DEBUG);

  }

}

module.exports = receive;
<|endoftext|>


<commit_before>
  /**
   *  Dropbox pane for import a file
   */

  cdb.admin.ImportDropboxPane = cdb.admin.ImportPane.extend({

    className: "import-pane import-pane-dropbox",

    events: {
      'click .dropbox-chooser' : '_onClickDBButton'
    },

    initialize: function() {
      this.template = this.options.template || cdb.templates.getTemplate('common/views/import_dropbox');
      this.render();
    },

    _onClickDBButton: function(e) {
      var self = this;

      this.killEvent(e);

      Dropbox.choose({
        linkType: "direct",
        multiselect: false,
        success: function(files) {
          var link = files[0].link;
          self.trigger('fileChosen', 'url', link);
        }
      });
    },

    render: function() {
      var api_key = cdb.config.get('dropbox_api_key');
      this.$el.html(this.template({ app_api_key: api_key }));
      return this;
    }
  });
<commit_msg>hotfix: dropbox chooser button class<commit_after>
  /**
   *  Dropbox pane for import a file
   */

  cdb.admin.ImportDropboxPane = cdb.admin.ImportPane.extend({

    className: "import-pane import-pane-dropbox",

    events: {
      'click .dropbox-dropin-btn' : '_onClickDBButton'
    },

    initialize: function() {
      this.template = this.options.template || cdb.templates.getTemplate('common/views/import_dropbox');
      this.render();
    },

    _onClickDBButton: function(e) {
      var self = this;

      this.killEvent(e);

      Dropbox.choose({
        linkType: "direct",
        multiselect: false,
        success: function(files) {
          var link = files[0].link;
          self.trigger('fileChosen', 'url', link);
        }
      });
    },

    render: function() {
      var api_key = cdb.config.get('dropbox_api_key');
      this.$el.html(this.template({ app_api_key: api_key }));
      return this;
    }
  });
<|endoftext|>


<commit_before>// Memory leak when defining functions #359
// https://github.com/espruino/Espruino/issues/359

function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}

var mem = process.memory().usage;
result = mem < 80;
<commit_msg>fix function decl test<commit_after>// Memory leak when defining functions #359
// https://github.com/espruino/Espruino/issues/359

function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}
function test() {console.log("rawr");}

var mem;
// use timeout to ensure that the actual source code has been freed
setTimeout(function() {
  mem = process.memory().usage;
  console.log(mem);
  result = mem < 90;
},10);
<|endoftext|>


<commit_before><commit_msg>added closeCard() to card.js<commit_after><|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { browserHistory } from 'react-router';
import memobind from 'memobind';
import * as actions from './redux/actions';
import { saveComment, fetchCommentList, dismissFetchCommentListError, dismissSaveCommentError } from '../comment/redux/actions';

import { CommentForm, CommentList } from '../comment';

export class ViewPage extends Component {
  static propTypes = {
    topic: PropTypes.object.isRequired,
    comment: PropTypes.object.isRequired,
    actions: PropTypes.object.isRequired,
    params: PropTypes.object.isRequired,
  };

  componentWillMount() {
    // this.props.actions.getTopic(this.props.params.topicId);
  }

  componentWillUnmount() {
    this.props.actions.dismissGetTopicError();
    this.props.actions.dismissSaveCommentError();
  }

  getTopicData() {
    return this.props.topic.byId[this.props.params.topicId];
  }

  handleBackBtnClick() {
    browserHistory.goBack();
  }

  renderBackBtn() {
    return (
      <button className="btn-back" onClick={memobind(this, 'handleBackBtnClick')}>Back</button>
    );
  }

  renderLoading() {
    return (

        {this.renderBackBtn()}

Loading...

    );
  }

  renderLoadingError() {
    const err = this.props.topic.getTopicError;
    return (

        {this.renderBackBtn()}

Failed to load the topic: {err.message || err.toString()}

    );
  }

  render() {
    const { getTopicPending, getTopicError } = this.props.topic;
    const topicData = this.getTopicData();

    if (getTopicError) {
      return this.renderLoadingError();
    }

    if (getTopicPending || !topicData) {
      return this.renderLoading();
    }

    return (

        {this.renderBackBtn()}

          {topicData.get('title')}

          {topicData.get('author') || 'Anonymous'}
          {topicData.createdAt.toString().replace(/\s*[\(（].*/g, '')}

          {topicData.get('content').split(/\n+/).map((p, i) =>
{p}
)}

        <CommentList
          topicId={this.props.params.topicId}
          fetchCommentList={this.props.actions.fetchCommentList}
          dismissFetchCommentListError={this.props.actions.dismissFetchCommentListError}
          commentState={this.props.comment}
        />
        <CommentForm
          topicId={this.props.params.topicId}
          saveComment={this.props.actions.saveComment}
          saveCommentPending={this.props.comment.saveCommentPending || false}
          saveCommentError={this.props.comment.saveCommentError || false}
        />

    );
  }
}

/* istanbul-ignore-next */
function mapStateToProps(state) {
  return {
    topic: state.topic,
    comment: state.comment,
  };
}

/* istanbul-ignore-next */
function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators({
      ...actions,
      saveComment,
      dismissSaveCommentError,
      fetchCommentList,
      dismissFetchCommentListError,
    }, dispatch)
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(ViewPage);
<commit_msg>Fix view page.<commit_after>import React, { Component, PropTypes } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { browserHistory } from 'react-router';
import memobind from 'memobind';
import * as actions from './redux/actions';
import { saveComment, fetchCommentList, dismissFetchCommentListError, dismissSaveCommentError } from '../comment/redux/actions';

import { CommentForm, CommentList } from '../comment';

export class ViewPage extends Component {
  static propTypes = {
    topic: PropTypes.object.isRequired,
    comment: PropTypes.object.isRequired,
    actions: PropTypes.object.isRequired,
    params: PropTypes.object.isRequired,
  };

  componentWillMount() {
    this.props.actions.getTopic(this.props.params.topicId);
  }

  componentWillUnmount() {
    this.props.actions.dismissGetTopicError();
    this.props.actions.dismissSaveCommentError();
  }

  getTopicData() {
    return this.props.topic.byId[this.props.params.topicId];
  }

  handleBackBtnClick() {
    browserHistory.goBack();
  }

  renderBackBtn() {
    return (
      <button className="btn-back" onClick={memobind(this, 'handleBackBtnClick')}>Back</button>
    );
  }

  renderLoading() {
    return (

        {this.renderBackBtn()}

Loading...

    );
  }

  renderLoadingError() {
    const err = this.props.topic.getTopicError;
    return (

        {this.renderBackBtn()}

Failed to load the topic: {err.message || err.toString()}

    );
  }

  render() {
    const { getTopicPending, getTopicError } = this.props.topic;
    const topicData = this.getTopicData();

    if (getTopicError) {
      return this.renderLoadingError();
    }

    if (getTopicPending || !topicData) {
      return this.renderLoading();
    }

    return (

        {this.renderBackBtn()}

          {topicData.get('title')}

          {topicData.get('author') || 'Anonymous'}
          {topicData.createdAt.toString().replace(/\s*[\(（].*/g, '')}

          {topicData.get('content').split(/\n+/).map((p, i) =>
{p}
)}

        <CommentList
          topicId={this.props.params.topicId}
          fetchCommentList={this.props.actions.fetchCommentList}
          dismissFetchCommentListError={this.props.actions.dismissFetchCommentListError}
          commentState={this.props.comment}
        />
        <CommentForm
          topicId={this.props.params.topicId}
          saveComment={this.props.actions.saveComment}
          saveCommentPending={this.props.comment.saveCommentPending || false}
          saveCommentError={this.props.comment.saveCommentError || false}
        />

    );
  }
}

/* istanbul-ignore-next */
function mapStateToProps(state) {
  return {
    topic: state.topic,
    comment: state.comment,
  };
}

/* istanbul-ignore-next */
function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators({
      ...actions,
      saveComment,
      dismissSaveCommentError,
      fetchCommentList,
      dismissFetchCommentListError,
    }, dispatch)
  };
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(ViewPage);
<|endoftext|>