<commit_before>var mp4box;

var boxtree;
var boxtable;
var treeview_node;
var progressbar;
var progresslabel;
var fileinput;
var urlinput;
var fancytree;

Log.setLogLevel(Log.debug);

var chunkSize  = 1024 * 1024; // bytes

function dragenter(e) {
	e.stopPropagation();
	e.preventDefault();
}

function drop(e) {
	var file;

	if (!e) {
		file = document.getElementById('fileinput').files[0];
	}
	else {
		file = e.dataTransfer.files[0];
	}
	if (file) {
		parseFile(file);
	}
}

function httpload(url) {
	mp4box 	   = new MP4Box(false);
	var downloader = new Downloader();
	var startDate = new Date();
	downloader.setCallback(
		function (response, end, error) {
			var nextStart = 0;
			if (response) {
				progressbar.progressbar({ value: Math.ceil(100*downloader.chunkStart/downloader.totalLength) });
				nextStart = mp4box.appendBuffer(response);

			}
			if (end) {
				progressbar.progressbar({ value: 100 });
				var endRead = new Date();
	            console.log("Done reading file ("+downloader.totalLength+ " bytes) in "+(endRead - startDate)+" ms");
				createTreeView(mp4box.inputIsoFile.boxes);
	            console.log("Done constructing tree in "+(new Date() - endRead)+" ms");
				mp4box.flush();
			} else {
				downloader.setChunkStart(nextStart);
			}
			if (error) {
				console.log("Error downloading file");
			}
		}
	);
	downloader.setInterval(1000);
	downloader.setChunkSize(chunkSize);
	downloader.setUrl(url);
	downloader.start();
}

function httploadFromUrl() {
	httpload(urlinput.val());
}

function httploadFromList() {
	httpload(urlSelector.find(":selected").val());
}

function getBoxTable(box) {
	var html = '
';
	html += '
';
	html += '
';
	html += '';
	html += 'Property name';
	html += '	';
	html += '';
	html += 'Property value';
	html += '	';
	html += '
';
	html += '
';
	html += '
';
	for (var prop in box) {
		if (["hdr_size", "start", "boxes", "subBoxNames", "entries", "samples", "references", "items", "item_infos"].indexOf(prop) > -1) {
			continue;
		} else if (box[prop] instanceof BoxParser.Box) {
			continue;
		} else if (typeof box[prop] === "function") {
			continue;
		} else if (box.subBoxNames && box.subBoxNames.indexOf(prop.slice(0,4)) > -1) {
			continue;
		} else {
			html += '
';
			html += '';
			html += prop;
			html += '	';
			html += '';
			html += box[prop];
			html += '	';
			html += '
';
		}
	}
	html += '
';
	html += '';
	return html;
}

function getFancyTreeData(boxes) {
	var array = [];
	for (var i = 0; i < boxes.length; i++) {
		var box = boxes[i];
		var fancytree_node = {};
		array.push(fancytree_node);
		fancytree_node.title = box.type || i;
		fancytree_node.data = { 'box': box };
		if (box.boxes) {
			fancytree_node.children = getFancyTreeData(box.boxes);
			fancytree_node.folder = true;
		} else if (box.entries) {
			fancytree_node.children = getFancyTreeData(box.entries);
			fancytree_node.folder = true;
		} else if (box.references) {
			fancytree_node.children = getFancyTreeData(box.references);
			fancytree_node.folder = true;
		} else if (box.items) {
			fancytree_node.children = getFancyTreeData(box.items);
			fancytree_node.folder = true;
		} else if (box.item_infos) {
			fancytree_node.children = getFancyTreeData(box.item_infos);
			fancytree_node.folder = true;
		}
	}
	return array;
}

function createTreeView(boxes) {
	fancytree.reload(getFancyTreeData(boxes));
	fancytree = boxtree.fancytree('getTree');
}

function parseFile(file) {
    var fileSize   = file.size;
    var offset     = 0;
    var self       = this; // we need a reference to the current object
    var readBlock  = null;
 	var startDate  = new Date();

	mp4box 	   = new MP4Box(false);

	mp4box.onError = function(e) {
		console.log("mp4box failed to parse data.");
	};

    var onparsedbuffer = function(mp4box, buffer) {
    	console.log("Appending buffer with offset "+offset);
		buffer.fileStart = offset;
    	mp4box.appendBuffer(buffer);
	}

	var onBlockRead = function(evt) {
        if (evt.target.error == null) {
            onparsedbuffer(mp4box, evt.target.result); // callback for handling read chunk
            offset += evt.target.result.byteLength;
			progressbar.progressbar({ value: Math.ceil(100*offset/fileSize) });
        } else {
            console.log("Read error: " + evt.target.error);
            return;
        }
        if (offset >= fileSize) {
			progressbar.progressbar({ value: 100 });
        	var endRead = new Date();
            console.log("Done reading file ("+fileSize+ " bytes) in "+(endRead - startDate)+" ms");
			createTreeView(mp4box.inputIsoFile.boxes);
			buildItemTable(mp4box.inputIsoFile.getBox("meta"));
            console.log("Done constructing tree in "+(new Date() - endRead)+" ms");
            return;
        }

        readBlock(offset, chunkSize, file);
    }

    readBlock = function(_offset, length, _file) {
        var r = new FileReader();
        var blob = _file.slice(_offset, length + _offset);
        r.onload = onBlockRead;
        r.readAsArrayBuffer(blob);
    }

    readBlock(offset, chunkSize, file);
}

function flattenItemInfo(meta) {
	var items = [];
	var i, j;
	var item;
	for (i = 0; i < meta.iinf.item_infos.length; i++) {
		item = {};
		item.id = meta.iinf.item_infos[i].item_ID;
		items[item.id] = item;
		item.ref_to = [];
		item.name = meta.iinf.item_infos[i].item_name;
		if (meta.iinf.item_infos[i].protection_index > 0) {
			item.protection = meta.ipro.protections[meta.iinf.item_infos[i].protection_index-1];
		}
		if (meta.iinf.item_infos[i].item_type) {
			item.type = meta.iinf.item_infos[i].item_type;
		} else {
			item.type = "mime";
		}
		item.content_type = meta.iinf.item_infos[i].content_type;
		item.content_encoding = meta.iinf.item_infos[i].content_encoding;
	}
	if (meta.iloc) {
		for(i = 0; i < meta.iloc.items.length; i++) {
			var offset;
			var itemloc = meta.iloc.items[i];
			item = items[itemloc.item_ID];
			if (itemloc.data_reference_index !== 0) {
				Log.warn("Item storage with reference to other files: not supported");
				item.source = meta.dinf.boxes[itemloc.data_reference_index-1];
			}
			if (itemloc.construction_method !== undefined) {
				Log.warn("Item storage with construction_method : not supported");
				switch(itemloc.construction_method) {
					case 0: // offset into the file referenced by the data reference index
					break;
					case 1: // offset into the idat box of this meta box
					break;
					case 2: // offset into another item
					break;
				}
			} else {
				item.extents = []
				for (j = 0; j < itemloc.extents.length; j++) {
					item.extents[j] = {};
					item.extents[j].offset = itemloc.extents[j].extent_offset + itemloc.base_offset;
					item.extents[j].length = itemloc.extents[j].extent_length;
				}
			}
		}
	}
	if (meta.pitm) {
		items[meta.pitm.item_ID].primary = true;
	}
	if (meta.iref) {
		for (i=0; i <meta.iref.references.length; i++) {
			var ref = meta.iref.references[i];
			for (j=0; j<ref.references.length; j++) {
				items[ref.from_item_ID].ref_to.push({type: ref.type, id: ref.references[j]});
			}
		}
	}
	return items;
}

function buildItemTable(meta) {
	var html;
	var i, j;
	html = "
";
	html += "
";
	html += "
";
	html += "ID	";
	html += "Name	";
	html += "Type	";
	html += "Primary	";
	html += "Protected	";
	html += "Byte ranges	";
	html += "References [type, item ID]	";
	html += "
";
	html += "
";
	html += "
";
	var items = flattenItemInfo(meta);
	for (i in items) {
		var item = items[i];
		html += "
";
		html += ""+item.id+"	";
		html += ""+(item.name ? item.name: "")+"	";
		html += ""+(item.type === "mime" ? item.content_type : item.type)+"	";
		html += ""+(item.primary ? "Yes" : "No")+"	";
		html += ""+(item.protection ? item.protection : "No")+"	";
		html += "";
		for (j = 0; j < item.extents.length; j++) {
			html+= "["+item.extents[j].offset+"-"+(item.extents[j].offset+item.extents[j].length-1)+"] "
		}
		html += "	";
		html += "";
		if (item.ref_to) {
			for (j = 0; j < item.ref_to.length; j++) {
				html+= "["+item.ref_to[j].type+", "+item.ref_to[j].id+"] "
			}
		}
		html += "	";
		html += "
";
	}
	html += "
";
	html += "
";
	$("#itemview").html(html);
}

window.onload = function () {
	boxtree = $('#boxtree');
	boxtable = $('#boxtable');
	progressbar = $('#progressbar');
	progresslabel = $('#progress-label');
	fileinput = $('#fileinput');
	urlinput = $('#urlinput');
	urlSelector = $('#urlSelector');
	progressbar.progressbar({
		value: 0,
		change: function() {
           progresslabel.text(
              progressbar.progressbar( "value" ) + "%" );
        },
        complete: function() {
           progresslabel.text( "Loading Completed!" );
        }
    });
	fileinput.button();

	var fancytree_options = {};
	fancytree_options.autoScroll = true;
	fancytree_options.source = [];
	fancytree_options.activate = function(event, data) {
		var node = data.node;
		if( !$.isEmptyObject(node.data) ){
			boxtable.html(getBoxTable(node.data.box));
		}
	};
	boxtree.fancytree(fancytree_options);
	fancytree = boxtree.fancytree('getTree');

	boxtable.html(getBoxTable({}));

	$("#tabs").tabs();
	$("#resulttabs").tabs();

	buildUrlList(urlSelector[0], true);

	if (window.location.search) {
		httpload(window.location.search.substring(1));
	}
}<commit_msg>add item info extent display<commit_after>var mp4box;

var boxtree;
var boxtable;
var treeview_node;
var progressbar;
var progresslabel;
var fileinput;
var urlinput;
var fancytree;

Log.setLogLevel(Log.debug);

var chunkSize  = 1024 * 1024; // bytes

function dragenter(e) {
	e.stopPropagation();
	e.preventDefault();
}

function drop(e) {
	var file;

	if (!e) {
		file = document.getElementById('fileinput').files[0];
	}
	else {
		file = e.dataTransfer.files[0];
	}
	if (file) {
		parseFile(file);
	}
}

function httpload(url) {
	mp4box 	   = new MP4Box(false);
	var downloader = new Downloader();
	var startDate = new Date();
	downloader.setCallback(
		function (response, end, error) {
			var nextStart = 0;
			if (response) {
				progressbar.progressbar({ value: Math.ceil(100*downloader.chunkStart/downloader.totalLength) });
				nextStart = mp4box.appendBuffer(response);

			}
			if (end) {
				progressbar.progressbar({ value: 100 });
				var endRead = new Date();
	            console.log("Done reading file ("+downloader.totalLength+ " bytes) in "+(endRead - startDate)+" ms");
				createTreeView(mp4box.inputIsoFile.boxes);
	            console.log("Done constructing tree in "+(new Date() - endRead)+" ms");
				mp4box.flush();
			} else {
				downloader.setChunkStart(nextStart);
			}
			if (error) {
				console.log("Error downloading file");
			}
		}
	);
	downloader.setInterval(1000);
	downloader.setChunkSize(chunkSize);
	downloader.setUrl(url);
	downloader.start();
}

function httploadFromUrl() {
	httpload(urlinput.val());
}

function httploadFromList() {
	httpload(urlSelector.find(":selected").val());
}

function getBoxTable(box) {
	var html = '
';
	html += '
';
	html += '
';
	html += '';
	html += 'Property name';
	html += '	';
	html += '';
	html += 'Property value';
	html += '	';
	html += '
';
	html += '
';
	html += '
';
	for (var prop in box) {
		if (["hdr_size", "start", "boxes", "subBoxNames", "entries", "samples", "references", "items", "item_infos", "extents"].indexOf(prop) > -1) {
			continue;
		} else if (box[prop] instanceof BoxParser.Box) {
			continue;
		} else if (typeof box[prop] === "function") {
			continue;
		} else if (box.subBoxNames && box.subBoxNames.indexOf(prop.slice(0,4)) > -1) {
			continue;
		} else {
			html += '
';
			html += '';
			html += prop;
			html += '	';
			html += '';
			html += box[prop];
			html += '	';
			html += '
';
		}
	}
	html += '
';
	html += '';
	return html;
}

function getFancyTreeData(boxes) {
	var array = [];
	for (var i = 0; i < boxes.length; i++) {
		var box = boxes[i];
		var fancytree_node = {};
		array.push(fancytree_node);
		fancytree_node.title = box.type || i;
		fancytree_node.data = { 'box': box };
		if (box.boxes) {
			fancytree_node.children = getFancyTreeData(box.boxes);
			fancytree_node.folder = true;
		} else if (box.entries) {
			fancytree_node.children = getFancyTreeData(box.entries);
			fancytree_node.folder = true;
		} else if (box.references) {
			fancytree_node.children = getFancyTreeData(box.references);
			fancytree_node.folder = true;
		} else if (box.items) {
			fancytree_node.children = getFancyTreeData(box.items);
			fancytree_node.folder = true;
		} else if (box.item_infos) {
			fancytree_node.children = getFancyTreeData(box.item_infos);
			fancytree_node.folder = true;
		} else if (box.extents) {
			fancytree_node.children = getFancyTreeData(box.extents);
			fancytree_node.folder = true;
		}
	}
	return array;
}

function createTreeView(boxes) {
	fancytree.reload(getFancyTreeData(boxes));
	fancytree = boxtree.fancytree('getTree');
}

function parseFile(file) {
    var fileSize   = file.size;
    var offset     = 0;
    var self       = this; // we need a reference to the current object
    var readBlock  = null;
 	var startDate  = new Date();

	mp4box 	   = new MP4Box(false);

	mp4box.onError = function(e) {
		console.log("mp4box failed to parse data.");
	};

    var onparsedbuffer = function(mp4box, buffer) {
    	console.log("Appending buffer with offset "+offset);
		buffer.fileStart = offset;
    	mp4box.appendBuffer(buffer);
	}

	var onBlockRead = function(evt) {
        if (evt.target.error == null) {
            onparsedbuffer(mp4box, evt.target.result); // callback for handling read chunk
            offset += evt.target.result.byteLength;
			progressbar.progressbar({ value: Math.ceil(100*offset/fileSize) });
        } else {
            console.log("Read error: " + evt.target.error);
            return;
        }
        if (offset >= fileSize) {
			progressbar.progressbar({ value: 100 });
        	var endRead = new Date();
            console.log("Done reading file ("+fileSize+ " bytes) in "+(endRead - startDate)+" ms");
			createTreeView(mp4box.inputIsoFile.boxes);
			buildItemTable(mp4box.inputIsoFile.getBox("meta"));
            console.log("Done constructing tree in "+(new Date() - endRead)+" ms");
            return;
        }

        readBlock(offset, chunkSize, file);
    }

    readBlock = function(_offset, length, _file) {
        var r = new FileReader();
        var blob = _file.slice(_offset, length + _offset);
        r.onload = onBlockRead;
        r.readAsArrayBuffer(blob);
    }

    readBlock(offset, chunkSize, file);
}

function flattenItemInfo(meta) {
	var items = [];
	var i, j;
	var item;
	for (i = 0; i < meta.iinf.item_infos.length; i++) {
		item = {};
		item.id = meta.iinf.item_infos[i].item_ID;
		items[item.id] = item;
		item.ref_to = [];
		item.name = meta.iinf.item_infos[i].item_name;
		if (meta.iinf.item_infos[i].protection_index > 0) {
			item.protection = meta.ipro.protections[meta.iinf.item_infos[i].protection_index-1];
		}
		if (meta.iinf.item_infos[i].item_type) {
			item.type = meta.iinf.item_infos[i].item_type;
		} else {
			item.type = "mime";
		}
		item.content_type = meta.iinf.item_infos[i].content_type;
		item.content_encoding = meta.iinf.item_infos[i].content_encoding;
	}
	if (meta.iloc) {
		for(i = 0; i < meta.iloc.items.length; i++) {
			var offset;
			var itemloc = meta.iloc.items[i];
			item = items[itemloc.item_ID];
			if (itemloc.data_reference_index !== 0) {
				Log.warn("Item storage with reference to other files: not supported");
				item.source = meta.dinf.boxes[itemloc.data_reference_index-1];
			}
			if (itemloc.construction_method !== undefined) {
				Log.warn("Item storage with construction_method : not supported");
				switch(itemloc.construction_method) {
					case 0: // offset into the file referenced by the data reference index
					break;
					case 1: // offset into the idat box of this meta box
					break;
					case 2: // offset into another item
					break;
				}
			} else {
				item.extents = []
				for (j = 0; j < itemloc.extents.length; j++) {
					item.extents[j] = {};
					item.extents[j].offset = itemloc.extents[j].extent_offset + itemloc.base_offset;
					item.extents[j].length = itemloc.extents[j].extent_length;
				}
			}
		}
	}
	if (meta.pitm) {
		items[meta.pitm.item_ID].primary = true;
	}
	if (meta.iref) {
		for (i=0; i <meta.iref.references.length; i++) {
			var ref = meta.iref.references[i];
			for (j=0; j<ref.references.length; j++) {
				items[ref.from_item_ID].ref_to.push({type: ref.type, id: ref.references[j]});
			}
		}
	}
	return items;
}

function buildItemTable(meta) {
	var html;
	var i, j;
	html = "
";
	html += "
";
	html += "
";
	html += "ID	";
	html += "Name	";
	html += "Type	";
	html += "Primary	";
	html += "Protected	";
	html += "Byte ranges	";
	html += "References [type, item ID]	";
	html += "
";
	html += "
";
	html += "
";
	var items = flattenItemInfo(meta);
	for (i in items) {
		var item = items[i];
		html += "
";
		html += ""+item.id+"	";
		html += ""+(item.name ? item.name: "")+"	";
		html += ""+(item.type === "mime" ? item.content_type : item.type)+"	";
		html += ""+(item.primary ? "Yes" : "No")+"	";
		html += ""+(item.protection ? item.protection : "No")+"	";
		html += "";
		for (j = 0; j < item.extents.length; j++) {
			html+= "["+item.extents[j].offset+"-"+(item.extents[j].offset+item.extents[j].length-1)+"] "
		}
		html += "	";
		html += "";
		if (item.ref_to) {
			for (j = 0; j < item.ref_to.length; j++) {
				html+= "["+item.ref_to[j].type+", "+item.ref_to[j].id+"] "
			}
		}
		html += "	";
		html += "
";
	}
	html += "
";
	html += "
";
	$("#itemview").html(html);
}

window.onload = function () {
	boxtree = $('#boxtree');
	boxtable = $('#boxtable');
	progressbar = $('#progressbar');
	progresslabel = $('#progress-label');
	fileinput = $('#fileinput');
	urlinput = $('#urlinput');
	urlSelector = $('#urlSelector');
	progressbar.progressbar({
		value: 0,
		change: function() {
           progresslabel.text(
              progressbar.progressbar( "value" ) + "%" );
        },
        complete: function() {
           progresslabel.text( "Loading Completed!" );
        }
    });
	fileinput.button();

	var fancytree_options = {};
	fancytree_options.autoScroll = true;
	fancytree_options.source = [];
	fancytree_options.activate = function(event, data) {
		var node = data.node;
		if( !$.isEmptyObject(node.data) ){
			boxtable.html(getBoxTable(node.data.box));
		}
	};
	boxtree.fancytree(fancytree_options);
	fancytree = boxtree.fancytree('getTree');

	boxtable.html(getBoxTable({}));

	$("#tabs").tabs();
	$("#resulttabs").tabs();

	buildUrlList(urlSelector[0], true);

	if (window.location.search) {
		httpload(window.location.search.substring(1));
	}
}<|endoftext|>


<commit_before>import { applyFixtures } from './support/fixtures';
import assert from 'assert';
import { initRecurly, testBed } from './support/helpers';

describe('Recurly.Frame', function () {
  const path = '/frame_mock';
  const payload = { example: 'data', event: 'test-event' };

  beforeEach(function (done) {
    this.recurly = initRecurly();
    this.sandbox = sinon.createSandbox();
    this.newWindow = { close: sinon.stub() };
    this.isIE = !!document.documentMode;

    this.sandbox.stub(window, 'open').callsFake(url => {
      this.eventName = url.match(/(recurly-frame-\w+-\w+)/)[0];
      return this.newWindow;
    });

    // HACK: when we're in an IE environment, we need to stub the relay creation;
    //       however, we want to proceed as normal in all other circumstances
    this.sandbox.stub(window.document.body, 'appendChild').callsFake(function (maybeRelay) {
      if (~(maybeRelay.name || '').indexOf('recurly-relay-')) maybeRelay.onload();
      else this.appendChild.wrappedMethod.call(this, maybeRelay);
    });

    this.recurly.ready(() => {
      this.frame = this.recurly.Frame({ path });
      done();
    });

    // Returns a spy so frame.bindWindowCloseListener does not cancel the tick
    const windowStub = { close: () => { windowStub.closed = true; }, closed: false };
    window.open = sinon.spy(() => windowStub);

    sinon.stub(window.document.body, 'appendChild').callsFake(relay => relay.onload());
  });

  afterEach(function () {
    const { frame, sandbox, recurly } = this;
    sandbox.restore();
    if (frame) frame.destroy();
  });

  applyFixtures();

  this.ctx.fixture = 'empty';

  it('calls window.open', function () {
    assert(window.open.calledOnce);
  });

  it('sends Recurly.version in the url', function () {
    const { recurly } = this;
    assert(window.open.calledWithMatch(`version=${recurly.version}`));
  });

  it('sends a listener event name to the opened url', function () {
    assert(window.open.calledWithMatch(/recurly-frame-\w+-\w+/));
  });

  it('listens for the frame event', function () {
    const { sandbox, eventName, frame } = this;
    assert(frame.hasListeners(eventName));
  });

  describe('when given a path', function () {
    const examples = [
      '/paypal/start',
      'google.com',
      'bfjbkdfs'
    ];

    it('opens the url relative to recurly.config.api', function () {
      const { recurly } = this;
      examples.forEach(path => {
        const frame = recurly.Frame({ path });
        assert(window.open.calledWithMatch(recurly.config.api + path));
        frame.destroy();
      });
    });
  });

  describe('when given data', function () {
    it('encodes the data into the opener url', function () {
      this.frame = this.recurly.Frame({ path, payload });
      assert(window.open.calledWithMatch('example=data'));
    });

    it('produces a valid composite querystring of given and additional data', function () {
      this.frame = this.recurly.Frame({ path, payload });
      assert(window.open.calledWithMatch(function (url) {
        return (url.match(/\?/) || []).length;
      }));
    });
  });

  describe('when the browser is detected to be IE', function () {
    beforeEach(function () {
      const { sandbox, isIE } = this;

      if (!isIE) document.documentMode = 'test';

      // rerun this to account for IE mocking
      this.frame = this.recurly.Frame({ path });
    });

    afterEach(function () {
      if (!this.isIE) delete document.documentMode;
    });

    it('creates a relay', function () {
      const { sandbox, frame } = this;
      const { relay } = frame;
      sandbox.spy(frame, 'create');

      assert(relay instanceof HTMLIFrameElement);
      assert.strictEqual(relay.width, '0');
      assert.strictEqual(relay.height, '0');
      assert.strictEqual(!!~relay.src.indexOf('/api/relay'), true);
      assert.strictEqual(relay.name, `recurly-relay-${frame.id}`);
      assert.strictEqual(relay.style.display, 'none');
      assert(relay.onload instanceof Function);
      assert(frame.create.notCalled);
      relay.onload();
      assert(frame.create.calledOnce);
    });

    describe('destroy', function () {
      it('removes the relay', function () {
        const { sandbox, recurly } = this;
        const { body } = window.document;
        sandbox.stub(body, 'contains').returns(true);
        sandbox.stub(body, 'removeChild').returns(true);
        const frame = this.frame = recurly.Frame({ path });
        frame.destroy();
        assert(body.removeChild.calledOnce);
        assert(body.removeChild.calledWithExactly(frame.relay));
      });
    });
  });

  describe('destroy', function () {
    it('closes the window', function () {
      const { recurly, newWindow } = this;
      const frame = recurly.Frame({ path, payload });
      assert(newWindow.close.notCalled);
      frame.destroy();
      assert(newWindow.close.calledOnce);
    });
  });

  describe('when type=iframe', function () {
    it('requires a container', function () {
      const { recurly } = this;
      assert.throws(() => {
        this.frame = recurly.Frame({ path, payload, type: 'iframe' });
      }, 'Invalid container. Expected HTMLElement, got undefined');
    });

    describe('when given a container', function () {
      beforeEach(function (done) {
        const { recurly, isIE } = this;
        if (isIE) window.document.body.appendChild.restore();
        this.frame = recurly.Frame({ path, payload, type: 'iframe', container: testBed() });
        this.frame.on('done', () => done());
      });

      it('injects an iframe into the container', function () {
        assert.strictEqual(testBed().children[0], this.frame.iframe);
      });

      it('sets the url appropriately', function () {
        const { recurly } = this;
        const { src } = this.frame.iframe;
        assert(~src.indexOf('/frame_mock'));
        assert(~src.indexOf('example=data'));
        assert(~src.indexOf(`version=${recurly.version}`));
        assert(~src.indexOf('event=recurly-frame-'));
        assert(~src.indexOf('key=test'));
      });

      describe('Frame.destroy', function () {
        it('removes the iframe', function () {
          const { frame } = this;
          frame.destroy();
          assert.strictEqual(testBed().children[0], undefined);
          assert.strictEqual(frame.iframe, undefined);
        });
      });
    });
  });

  it('emits a closed event when the frame closes', function (done) {
    this.timeout(2000); // timeout with error if frame doesn't emit close event
    const frame = this.recurly.Frame({ path }).on('close', () => done());
    frame.window.close();
  });
});
<commit_msg>fixes tests for 'close' event emission<commit_after>import { applyFixtures } from './support/fixtures';
import assert from 'assert';
import { initRecurly, testBed } from './support/helpers';

describe('Recurly.Frame', function () {
  const path = '/frame_mock';
  const payload = { example: 'data', event: 'test-event' };

  beforeEach(function (done) {
    this.recurly = initRecurly();
    this.sandbox = sinon.createSandbox();
    this.newWindow = { close: sinon.stub() };
    this.isIE = !!document.documentMode;

    this.sandbox.stub(window, 'open').callsFake(url => {
      this.eventName = url.match(/(recurly-frame-\w+-\w+)/)[0];
      return this.newWindow;
    });

    // HACK: when we're in an IE environment, we need to stub the relay creation;
    //       however, we want to proceed as normal in all other circumstances
    this.sandbox.stub(window.document.body, 'appendChild').callsFake(function (maybeRelay) {
      if (~(maybeRelay.name || '').indexOf('recurly-relay-')) maybeRelay.onload();
      else this.appendChild.wrappedMethod.call(this, maybeRelay);
    });

    this.recurly.ready(() => {
      this.frame = this.recurly.Frame({ path });
      done();
    });
  });

  afterEach(function () {
    const { frame, sandbox, recurly } = this;
    sandbox.restore();
    if (frame) frame.destroy();
  });

  applyFixtures();

  this.ctx.fixture = 'empty';

  it('calls window.open', function () {
    assert(window.open.calledOnce);
  });

  it('sends Recurly.version in the url', function () {
    const { recurly } = this;
    assert(window.open.calledWithMatch(`version=${recurly.version}`));
  });

  it('sends a listener event name to the opened url', function () {
    assert(window.open.calledWithMatch(/recurly-frame-\w+-\w+/));
  });

  it('listens for the frame event', function () {
    const { sandbox, eventName, frame } = this;
    assert(frame.hasListeners(eventName));
  });

  describe('when given a path', function () {
    const examples = [
      '/paypal/start',
      'google.com',
      'bfjbkdfs'
    ];

    it('opens the url relative to recurly.config.api', function () {
      const { recurly } = this;
      examples.forEach(path => {
        const frame = recurly.Frame({ path });
        assert(window.open.calledWithMatch(recurly.config.api + path));
        frame.destroy();
      });
    });
  });

  describe('when given data', function () {
    it('encodes the data into the opener url', function () {
      this.frame = this.recurly.Frame({ path, payload });
      assert(window.open.calledWithMatch('example=data'));
    });

    it('produces a valid composite querystring of given and additional data', function () {
      this.frame = this.recurly.Frame({ path, payload });
      assert(window.open.calledWithMatch(function (url) {
        return (url.match(/\?/) || []).length;
      }));
    });
  });

  describe('when the browser is detected to be IE', function () {
    beforeEach(function () {
      const { sandbox, isIE } = this;

      if (!isIE) document.documentMode = 'test';

      // rerun this to account for IE mocking
      this.frame = this.recurly.Frame({ path });
    });

    afterEach(function () {
      if (!this.isIE) delete document.documentMode;
    });

    it('creates a relay', function () {
      const { sandbox, frame } = this;
      const { relay } = frame;
      sandbox.spy(frame, 'create');

      assert(relay instanceof HTMLIFrameElement);
      assert.strictEqual(relay.width, '0');
      assert.strictEqual(relay.height, '0');
      assert.strictEqual(!!~relay.src.indexOf('/api/relay'), true);
      assert.strictEqual(relay.name, `recurly-relay-${frame.id}`);
      assert.strictEqual(relay.style.display, 'none');
      assert(relay.onload instanceof Function);
      assert(frame.create.notCalled);
      relay.onload();
      assert(frame.create.calledOnce);
    });

    describe('destroy', function () {
      it('removes the relay', function () {
        const { sandbox, recurly } = this;
        const { body } = window.document;
        sandbox.stub(body, 'contains').returns(true);
        sandbox.stub(body, 'removeChild').returns(true);
        const frame = this.frame = recurly.Frame({ path });
        frame.destroy();
        assert(body.removeChild.calledOnce);
        assert(body.removeChild.calledWithExactly(frame.relay));
      });
    });
  });

  describe('destroy', function () {
    it('closes the window', function () {
      const { recurly, newWindow } = this;
      const frame = recurly.Frame({ path, payload });
      assert(newWindow.close.notCalled);
      frame.destroy();
      assert(newWindow.close.calledOnce);
    });
  });

  describe('when type=iframe', function () {
    it('requires a container', function () {
      const { recurly } = this;
      assert.throws(() => {
        this.frame = recurly.Frame({ path, payload, type: 'iframe' });
      }, 'Invalid container. Expected HTMLElement, got undefined');
    });

    describe('when given a container', function () {
      beforeEach(function (done) {
        const { recurly, isIE } = this;
        if (isIE) window.document.body.appendChild.restore();
        this.frame = recurly.Frame({ path, payload, type: 'iframe', container: testBed() });
        this.frame.on('done', () => done());
      });

      it('injects an iframe into the container', function () {
        assert.strictEqual(testBed().children[0], this.frame.iframe);
      });

      it('sets the url appropriately', function () {
        const { recurly } = this;
        const { src } = this.frame.iframe;
        assert(~src.indexOf('/frame_mock'));
        assert(~src.indexOf('example=data'));
        assert(~src.indexOf(`version=${recurly.version}`));
        assert(~src.indexOf('event=recurly-frame-'));
        assert(~src.indexOf('key=test'));
      });

      describe('Frame.destroy', function () {
        it('removes the iframe', function () {
          const { frame } = this;
          frame.destroy();
          assert.strictEqual(testBed().children[0], undefined);
          assert.strictEqual(frame.iframe, undefined);
        });
      });
    });
  });

  it('emits a closed event when the frame closes', function (done) {
    this.newWindow = { close: () => this.newWindow.closed = true, closed: false };
    this.timeout(2000); // timeout with error if frame doesn't emit close event
    const frame = this.recurly.Frame({ path }).on('close', () => done());
    frame.window.close();
  });
});
<|endoftext|>


<commit_before>/* @flow */
/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

import { Source } from './language/source';
import { parse } from './language/parser';
import { validateDocument } from './validator';
import { execute } from './executor/executor';
import { formatError } from './error';
import type { GraphQLFormattedError } from './error/formatError';
import type { GraphQLSchema } from './type/schema';
import { GraphQLError } from './error/GraphQLError';

/**
 * This is the primary entry point function for fulfilling GraphQL operations
 * by parsing, validating, and executing a GraphQL document along side a
 * GraphQL schema.
 *
 * More sophisticated GraphQL servers, such as those which persist queries,
 * may wish to separate the validation and execution phases to a static time
 * tooling step, and a server runtime step.
 */
export function graphql(
  schema: GraphQLSchema,
  requestString: string,
  rootValue?: ?any,
  variableValues?: ?{[key: string]: any},
  operationName?: ?string
): Promise<GraphQLResult> {
  return new Promise(resolve => {
    var source = new Source(requestString || '', 'GraphQL request');
    var documentAST = parse(source);
    var validationErrors = validateDocument(schema, documentAST);
    if (validationErrors.length > 0) {
      resolve({
        errors: validationErrors.map(formatError)
      });
    } else {
      resolve(
        execute(
          schema,
          documentAST,
          rootValue,
          variableValues,
          operationName
        ).then(result => {
          if (result.errors) {
            return {
              data: result.data,
              errors: result.errors.map(formatError)
            };
          }
          return result;
        })
      );
    }
  }).catch(error => {
    if (!(error instanceof GraphQLError)) {
      throw error;
    }
    return { errors: [ formatError(error) ] };
  });
}

/**
 * The result of a GraphQL parse, validation and execution.
 *
 * `data` is the result of a successful execution of the query.
 * `errors` is included when any errors occurred as a non-empty array.
 */
type GraphQLResult = {
  data?: ?Object;
  errors?: Array<GraphQLFormattedError>;
}
<commit_msg>Revert "Improve error handling for the graphql function. This only returns the"<commit_after>/* @flow */
/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

import { Source } from './language/source';
import { parse } from './language/parser';
import { validateDocument } from './validator';
import { execute } from './executor/executor';
import { formatError } from './error';
import type { GraphQLFormattedError } from './error/formatError';
import type { GraphQLSchema } from './type/schema';

/**
 * This is the primary entry point function for fulfilling GraphQL operations
 * by parsing, validating, and executing a GraphQL document along side a
 * GraphQL schema.
 *
 * More sophisticated GraphQL servers, such as those which persist queries,
 * may wish to separate the validation and execution phases to a static time
 * tooling step, and a server runtime step.
 */
export function graphql(
  schema: GraphQLSchema,
  requestString: string,
  rootValue?: ?any,
  variableValues?: ?{[key: string]: any},
  operationName?: ?string
): Promise<GraphQLResult> {
  return new Promise(resolve => {
    var source = new Source(requestString || '', 'GraphQL request');
    var documentAST = parse(source);
    var validationErrors = validateDocument(schema, documentAST);
    if (validationErrors.length > 0) {
      resolve({
        errors: validationErrors.map(formatError)
      });
    } else {
      resolve(
        execute(
          schema,
          documentAST,
          rootValue,
          variableValues,
          operationName
        ).then(result => {
          if (result.errors) {
            return {
              data: result.data,
              errors: result.errors.map(formatError)
            };
          }
          return result;
        })
      );
    }
  }).catch(error => {
    return { errors: [ formatError(error) ] };
  });
}

/**
 * The result of a GraphQL parse, validation and execution.
 *
 * `data` is the result of a successful execution of the query.
 * `errors` is included when any errors occurred as a non-empty array.
 */
type GraphQLResult = {
  data?: ?Object;
  errors?: Array<GraphQLFormattedError>;
}
<|endoftext|>


<commit_before><commit_msg>When switching currently playing episode, reset current time before playing<commit_after><|endoftext|>


<commit_before>//
// LCB Client
//

(function(window, $, _) {
    //
    // Base
    //
    var Client = function(options) {
        this.options = options;
        this.status = new Backbone.Model();
        this.user = new UserModel();
        this.users = new UsersCollection();
        this.rooms = new RoomsCollection();
        this.events = _.extend({}, Backbone.Events);
        return this;
    };
    //
    // Account
    //
    Client.prototype.getUser = function() {
        var that = this;
        this.socket.emit('account:whoami', function(user) {
            that.user.set(user);
        });
    };
    Client.prototype.updateProfile = function(profile) {
        var that = this;
        this.socket.emit('account:profile', profile, function(user) {
            that.user.set(user);
        });
    };

    //
    // Rooms
    //
    Client.prototype.createRoom = function(data) {
        var that = this;
        var room = {
            name: data.name,
            slug: data.slug,
            description: data.description
        };
        var callback = data.callback;
        this.socket.emit('rooms:create', room, function(room) {
            if (room && room.id) {
                that.rooms.add(room);
                that.switchRoom(room.id);
            }
            callback && callback(room);
        });
    };
    Client.prototype.getRooms = function() {
        var that = this;
        this.socket.emit('rooms:list', { users: true }, function(rooms) {
            that.rooms.set(rooms);
            // Get users for each room!
            // We do it here for the room browser
            _.each(rooms, function(room) {
                if (room.users) {
                    that.setUsers(room.id, room.users);
                }
            });
        });
    };
    Client.prototype.switchRoom = function(id) {
        // Make sure we have a last known room ID
        this.rooms.last.set('id', this.rooms.current.get('id'));
        if (!id || id === 'list') {
            this.rooms.current.set('id', 'list');
            this.router.navigate('!/', {
                replace: true
            });
            return;
        }
        var room = this.rooms.get(id);
        if (room && room.get('joined')) {
            this.rooms.current.set('id', id);
            this.router.navigate('!/room/' + room.id, {
                replace: true
            });
            return;
        } else {
            this.joinRoom(id, true);
        }
    };
    Client.prototype.updateRoom = function(room) {
        this.socket.emit('rooms:update', room);
    };
    Client.prototype.roomUpdate = function(resRoom) {
        var room = this.rooms.get(resRoom.id);
        if (!room) {
            // Nothing to do
            return;
        }
        room.set(resRoom);
    };
    Client.prototype.addRoom = function(room) {
        this.rooms.add(room);
    };
    Client.prototype.archiveRoom = function(id) {
        this.socket.emit('rooms:archive', id, function(room) {
            if (!room.id) {
                swal('Unable to Archive!',
                     'Unable to archive this room!',
                     'error');
            }
        });
    }
    Client.prototype.roomArchive = function(room) {
        this.leaveRoom(room.id);
        this.rooms.remove(room.id);
    };
    Client.prototype.joinRoom = function(id, switchRoom) {
        var that = this;
        // We need an id and unlocked joining
        if (!id || _.contains(this.joining, id)) {
            // Nothing to do
            return;
        }
        //
        // Setup joining lock
        //
        this.joining = this.joining || [];
        this.joining.push(id);
        this.socket.emit('rooms:join', id, function(resRoom) {
            // Room was likely archived if this returns
            if (!resRoom) {
                return;
            }
            var room = that.rooms.get(id);
            room = that.rooms.add(resRoom);
            room.set('joined', true);
            // Get room history
            that.getMessages({
                room: room.id,
                since_id: room.lastMessage.get('id'),
                take: 200,
                expand: 'owner',
                reverse: true
            }, function(messages) {
                messages.reverse();
                that.addMessages(messages, !room.get('loaded'));
                room.set('loaded', true);
            });
            if (that.options.filesEnabled) {
                that.getFiles({
                    room: room.id,
                    take: 15
                }, function(files) {
                    files.reverse();
                    that.setFiles(room.id, files);
                });
            }
            // Do we want to switch?
            if (switchRoom) {
                that.switchRoom(id);
            }
            //
            // Add room id to localstorage so we can reopen it on refresh
            //
            var openRooms = store.get('openrooms');
            if (openRooms instanceof Array) {
                // Check for duplicates
                if (!_.contains(openRooms, id)) {
                    openRooms.push(id);
                }
                store.set('openrooms', openRooms);
            } else {
                store.set('openrooms', [id]);
            }
        });
        // Remove joining lock
        _.defer(function() {
            that.joining = _.without(that.joining, id);
        });
    };
    Client.prototype.leaveRoom = function(id) {
        var room = this.rooms.get(id);
        if (room) {
            room.set('joined', false);
            room.lastMessage.clear();
        }
        this.socket.emit('rooms:leave', id);
        if (id === this.rooms.current.get('id')) {
            var room = this.rooms.get(this.rooms.last.get('id'));
            this.switchRoom(room && room.get('joined') ? room.id : '');
        }
        // Remove room id from localstorage
        store.set('openrooms', _.without(store.get('openrooms'), id));
    };
    Client.prototype.getRoomUsers = function(id, callback) {
        this.socket.emit('rooms:users', {
            room: id
        }, callback);
    };
    //
    // Messages
    //
    Client.prototype.addMessage = function(message) {
        var room = this.rooms.get(message.room);
        if (!room || !message) {
            // Unknown room, nothing to do!
            return;
        }
        room.set('lastActive', message.posted)
        room.lastMessage.set(message);
        room.trigger('messages:new', message);
    };
    Client.prototype.addMessages = function(messages, historical) {
        _.each(messages, function(message) {
            if (historical) {
                message.historical = true;
            }
            this.addMessage(message);
        }, this);
    };
    Client.prototype.sendMessage = function(message) {
        this.socket.emit('messages:create', message);
    };
    Client.prototype.getMessages = function(query, callback) {
        this.socket.emit('messages:list', query, callback);
    };
    //
    // Files
    //
    Client.prototype.getFiles = function(query, callback) {
        this.socket.emit('files:list', {
            room: query.room || '',
            take: query.take || 40,
            expand: query.expand || 'owner'
        }, callback);
    };
    Client.prototype.setFiles = function(roomId, files) {
        if (!roomId || !files || !files.length) {
            // Nothing to do here...
            return;
        }
        var room = this.rooms.get(roomId);
        if (!room) {
            // No room
            return;
        }
        room.files.set(files);
    };
    Client.prototype.addFile = function(file) {
        var room = this.rooms.get(file.room);
        if (!room) {
            // No room
            return;
        }
        room.files.add(file);
    };
    //
    // Users
    //
    Client.prototype.setUsers = function(roomId, users) {
        if (!roomId || !users || !users.length) {
            // Data is not valid
            return;
        }
        var room = this.rooms.get(roomId);
        if (!room) {
            // No room
            return;
        }
        room.users.set(users);
    };
    Client.prototype.addUser = function(user) {
        var room = this.rooms.get(user.room);
        if (!room) {
            // No room
            return;
        }
        room.users.add(user);
    };
    Client.prototype.removeUser = function(user) {
        var room = this.rooms.get(user.room);
        if (!room) {
            // No room
            return;
        }
        room.users.remove(user.id);
    };
    Client.prototype.updateUser = function(user) {
        // Update if current user
        if (user.id == this.user.id) {
            this.user.set(user);
        }
        // Update all rooms
        this.rooms.each(function(room) {
            var target = room.users.findWhere({
                id: user.id
            });
            target && target.set(user);
        }, this);
    };
    Client.prototype.getUsersSync = function() {
        if (this.users.length) {
            return this.users;
        }

        var that = this;

        function success(users) {
            that.users.set(users);
        }

        $.ajax({url:'./users', async: false, success: success});

        return this.users;
    };
    //
    // Extras
    //
    Client.prototype.getEmotes = function(callback) {
        this.extras = this.extras || {};
        if (!this.extras.emotes) {
            // Use AJAX, so we can take advantage of HTTP caching
            // Also, it's a promise - which ensures we only load emotes once
            this.extras.emotes = $.get('./extras/emotes');
        }
        if (callback) {
            this.extras.emotes.done(callback);
        }
    };
    Client.prototype.getReplacements = function(callback) {
        this.extras = this.extras || {};
        if (!this.extras.replacements) {
            // Use AJAX, so we can take advantage of HTTP caching
            // Also, it's a promise - which ensures we only load emotes once
            this.extras.replacements = $.get('./extras/replacements');
        }
        if (callback) {
            this.extras.replacements.done(callback);
        }
    };

    //
    // Router Setup
    //
    Client.prototype.route = function() {
        var that = this;
        var Router = Backbone.Router.extend({
            routes: {
                '!/room/': 'list',
                '!/room/:id': 'join',
                '*path': 'list'
            },
            join: function(id) {
                that.switchRoom(id);
            },
            list: function() {
                that.switchRoom('list');
            }
        });
        this.router = new Router();
        Backbone.history.start();
    };
    //
    // Listen
    //
    Client.prototype.listen = function() {
        var that = this;
        //
        // Socket
        //
        this.socket = io.connect(null, {
            reconnect: true
        });
        this.socket.on('connect', function() {
            that.getUser();
            that.getRooms();
            that.status.set('connected', true);
        });
        this.socket.on('reconnect', function() {
            _.each(that.rooms.where({ joined: true }), function(room) {
                that.joinRoom(room.id);
            });
        });
        this.socket.on('messages:new', function(message) {
            that.addMessage(message);
        });
        this.socket.on('rooms:new', function(data) {
            that.addRoom(data);
        });
        this.socket.on('rooms:update', function(room) {
            that.roomUpdate(room);
        });
        this.socket.on('rooms:archive', function(room) {
            that.roomArchive(room);
        });
        this.socket.on('users:join', function(user) {
            that.addUser(user);
        });
        this.socket.on('users:leave', function(user) {
            that.removeUser(user);
        });
        this.socket.on('users:update', function(user) {
            that.updateUser(user);
        });
        this.socket.on('files:new', function(file) {
            that.addFile(file);
        });
        this.socket.on('disconnect', function() {
            that.status.set('connected', false);
        });
        //
        // GUI
        //
        this.events.on('messages:send', this.sendMessage, this);
        this.events.on('rooms:update', this.updateRoom, this);
        this.events.on('rooms:leave', this.leaveRoom, this);
        this.events.on('rooms:create', this.createRoom, this);
        this.events.on('rooms:switch', this.switchRoom, this);
        this.events.on('rooms:archive', this.archiveRoom, this);
        this.events.on('profile:update', this.updateProfile, this);
    };
    //
    // Start
    //
    Client.prototype.start = function() {
        this.getEmotes();
        this.getReplacements();
        this.listen();
        this.route();
        this.view = new window.LCB.ClientView({
            client: this
        });
        //
        // Join rooms from localstorage
        //
        var openRooms = store.get('openrooms');
        if (openRooms instanceof Array) {
            // Flush the stored array
            store.set('openrooms', []);
            // Let's open some rooms!
            _.each(_.uniq(openRooms), function(id) {
                this.joinRoom(id);
            }, this);
        }
        return this;
    };
    //
    // Add to window
    //
    window.LCB = window.LCB || {};
    window.LCB.Client = Client;
})(window, $, _);
<commit_msg>issue #229 Room creation with invalid slug doesnt error out.<commit_after>//
// LCB Client
//

(function(window, $, _) {
    //
    // Base
    //
    var Client = function(options) {
        this.options = options;
        this.status = new Backbone.Model();
        this.user = new UserModel();
        this.users = new UsersCollection();
        this.rooms = new RoomsCollection();
        this.events = _.extend({}, Backbone.Events);
        return this;
    };
    //
    // Account
    //
    Client.prototype.getUser = function() {
        var that = this;
        this.socket.emit('account:whoami', function(user) {
            that.user.set(user);
        });
    };
    Client.prototype.updateProfile = function(profile) {
        var that = this;
        this.socket.emit('account:profile', profile, function(user) {
            that.user.set(user);
        });
    };

    //
    // Rooms
    //
    Client.prototype.createRoom = function(data) {
        var that = this;
        var room = {
            name: data.name,
            slug: data.slug,
            description: data.description
        };
        var callback = data.callback;
        this.socket.emit('rooms:create', room, function(room) {
            if (room && room.errors) {
                swal("Unable to create room",
                     "Room slugs can only contain lower case letters, numbers or underscores!",
                     "error");
            }
            else if (room && room.id) {
                that.rooms.add(room);
                that.switchRoom(room.id);
            }
            callback && callback(room);
        });
    };
    Client.prototype.getRooms = function() {
        var that = this;
        this.socket.emit('rooms:list', { users: true }, function(rooms) {
            that.rooms.set(rooms);
            // Get users for each room!
            // We do it here for the room browser
            _.each(rooms, function(room) {
                if (room.users) {
                    that.setUsers(room.id, room.users);
                }
            });
        });
    };
    Client.prototype.switchRoom = function(id) {
        // Make sure we have a last known room ID
        this.rooms.last.set('id', this.rooms.current.get('id'));
        if (!id || id === 'list') {
            this.rooms.current.set('id', 'list');
            this.router.navigate('!/', {
                replace: true
            });
            return;
        }
        var room = this.rooms.get(id);
        if (room && room.get('joined')) {
            this.rooms.current.set('id', id);
            this.router.navigate('!/room/' + room.id, {
                replace: true
            });
            return;
        } else {
            this.joinRoom(id, true);
        }
    };
    Client.prototype.updateRoom = function(room) {
        this.socket.emit('rooms:update', room);
    };
    Client.prototype.roomUpdate = function(resRoom) {
        var room = this.rooms.get(resRoom.id);
        if (!room) {
            // Nothing to do
            return;
        }
        room.set(resRoom);
    };
    Client.prototype.addRoom = function(room) {
        this.rooms.add(room);
    };
    Client.prototype.archiveRoom = function(id) {
        this.socket.emit('rooms:archive', id, function(room) {
            if (!room.id) {
                swal('Unable to Archive!',
                     'Unable to archive this room!',
                     'error');
            }
        });
    }
    Client.prototype.roomArchive = function(room) {
        this.leaveRoom(room.id);
        this.rooms.remove(room.id);
    };
    Client.prototype.joinRoom = function(id, switchRoom) {
        var that = this;
        // We need an id and unlocked joining
        if (!id || _.contains(this.joining, id)) {
            // Nothing to do
            return;
        }
        //
        // Setup joining lock
        //
        this.joining = this.joining || [];
        this.joining.push(id);
        this.socket.emit('rooms:join', id, function(resRoom) {
            // Room was likely archived if this returns
            if (!resRoom) {
                return;
            }
            var room = that.rooms.get(id);
            room = that.rooms.add(resRoom);
            room.set('joined', true);
            // Get room history
            that.getMessages({
                room: room.id,
                since_id: room.lastMessage.get('id'),
                take: 200,
                expand: 'owner',
                reverse: true
            }, function(messages) {
                messages.reverse();
                that.addMessages(messages, !room.get('loaded'));
                room.set('loaded', true);
            });
            if (that.options.filesEnabled) {
                that.getFiles({
                    room: room.id,
                    take: 15
                }, function(files) {
                    files.reverse();
                    that.setFiles(room.id, files);
                });
            }
            // Do we want to switch?
            if (switchRoom) {
                that.switchRoom(id);
            }
            //
            // Add room id to localstorage so we can reopen it on refresh
            //
            var openRooms = store.get('openrooms');
            if (openRooms instanceof Array) {
                // Check for duplicates
                if (!_.contains(openRooms, id)) {
                    openRooms.push(id);
                }
                store.set('openrooms', openRooms);
            } else {
                store.set('openrooms', [id]);
            }
        });
        // Remove joining lock
        _.defer(function() {
            that.joining = _.without(that.joining, id);
        });
    };
    Client.prototype.leaveRoom = function(id) {
        var room = this.rooms.get(id);
        if (room) {
            room.set('joined', false);
            room.lastMessage.clear();
        }
        this.socket.emit('rooms:leave', id);
        if (id === this.rooms.current.get('id')) {
            var room = this.rooms.get(this.rooms.last.get('id'));
            this.switchRoom(room && room.get('joined') ? room.id : '');
        }
        // Remove room id from localstorage
        store.set('openrooms', _.without(store.get('openrooms'), id));
    };
    Client.prototype.getRoomUsers = function(id, callback) {
        this.socket.emit('rooms:users', {
            room: id
        }, callback);
    };
    //
    // Messages
    //
    Client.prototype.addMessage = function(message) {
        var room = this.rooms.get(message.room);
        if (!room || !message) {
            // Unknown room, nothing to do!
            return;
        }
        room.set('lastActive', message.posted)
        room.lastMessage.set(message);
        room.trigger('messages:new', message);
    };
    Client.prototype.addMessages = function(messages, historical) {
        _.each(messages, function(message) {
            if (historical) {
                message.historical = true;
            }
            this.addMessage(message);
        }, this);
    };
    Client.prototype.sendMessage = function(message) {
        this.socket.emit('messages:create', message);
    };
    Client.prototype.getMessages = function(query, callback) {
        this.socket.emit('messages:list', query, callback);
    };
    //
    // Files
    //
    Client.prototype.getFiles = function(query, callback) {
        this.socket.emit('files:list', {
            room: query.room || '',
            take: query.take || 40,
            expand: query.expand || 'owner'
        }, callback);
    };
    Client.prototype.setFiles = function(roomId, files) {
        if (!roomId || !files || !files.length) {
            // Nothing to do here...
            return;
        }
        var room = this.rooms.get(roomId);
        if (!room) {
            // No room
            return;
        }
        room.files.set(files);
    };
    Client.prototype.addFile = function(file) {
        var room = this.rooms.get(file.room);
        if (!room) {
            // No room
            return;
        }
        room.files.add(file);
    };
    //
    // Users
    //
    Client.prototype.setUsers = function(roomId, users) {
        if (!roomId || !users || !users.length) {
            // Data is not valid
            return;
        }
        var room = this.rooms.get(roomId);
        if (!room) {
            // No room
            return;
        }
        room.users.set(users);
    };
    Client.prototype.addUser = function(user) {
        var room = this.rooms.get(user.room);
        if (!room) {
            // No room
            return;
        }
        room.users.add(user);
    };
    Client.prototype.removeUser = function(user) {
        var room = this.rooms.get(user.room);
        if (!room) {
            // No room
            return;
        }
        room.users.remove(user.id);
    };
    Client.prototype.updateUser = function(user) {
        // Update if current user
        if (user.id == this.user.id) {
            this.user.set(user);
        }
        // Update all rooms
        this.rooms.each(function(room) {
            var target = room.users.findWhere({
                id: user.id
            });
            target && target.set(user);
        }, this);
    };
    Client.prototype.getUsersSync = function() {
        if (this.users.length) {
            return this.users;
        }

        var that = this;

        function success(users) {
            that.users.set(users);
        }

        $.ajax({url:'./users', async: false, success: success});

        return this.users;
    };
    //
    // Extras
    //
    Client.prototype.getEmotes = function(callback) {
        this.extras = this.extras || {};
        if (!this.extras.emotes) {
            // Use AJAX, so we can take advantage of HTTP caching
            // Also, it's a promise - which ensures we only load emotes once
            this.extras.emotes = $.get('./extras/emotes');
        }
        if (callback) {
            this.extras.emotes.done(callback);
        }
    };
    Client.prototype.getReplacements = function(callback) {
        this.extras = this.extras || {};
        if (!this.extras.replacements) {
            // Use AJAX, so we can take advantage of HTTP caching
            // Also, it's a promise - which ensures we only load emotes once
            this.extras.replacements = $.get('./extras/replacements');
        }
        if (callback) {
            this.extras.replacements.done(callback);
        }
    };

    //
    // Router Setup
    //
    Client.prototype.route = function() {
        var that = this;
        var Router = Backbone.Router.extend({
            routes: {
                '!/room/': 'list',
                '!/room/:id': 'join',
                '*path': 'list'
            },
            join: function(id) {
                that.switchRoom(id);
            },
            list: function() {
                that.switchRoom('list');
            }
        });
        this.router = new Router();
        Backbone.history.start();
    };
    //
    // Listen
    //
    Client.prototype.listen = function() {
        var that = this;
        //
        // Socket
        //
        this.socket = io.connect(null, {
            reconnect: true
        });
        this.socket.on('connect', function() {
            that.getUser();
            that.getRooms();
            that.status.set('connected', true);
        });
        this.socket.on('reconnect', function() {
            _.each(that.rooms.where({ joined: true }), function(room) {
                that.joinRoom(room.id);
            });
        });
        this.socket.on('messages:new', function(message) {
            that.addMessage(message);
        });
        this.socket.on('rooms:new', function(data) {
            that.addRoom(data);
        });
        this.socket.on('rooms:update', function(room) {
            that.roomUpdate(room);
        });
        this.socket.on('rooms:archive', function(room) {
            that.roomArchive(room);
        });
        this.socket.on('users:join', function(user) {
            that.addUser(user);
        });
        this.socket.on('users:leave', function(user) {
            that.removeUser(user);
        });
        this.socket.on('users:update', function(user) {
            that.updateUser(user);
        });
        this.socket.on('files:new', function(file) {
            that.addFile(file);
        });
        this.socket.on('disconnect', function() {
            that.status.set('connected', false);
        });
        //
        // GUI
        //
        this.events.on('messages:send', this.sendMessage, this);
        this.events.on('rooms:update', this.updateRoom, this);
        this.events.on('rooms:leave', this.leaveRoom, this);
        this.events.on('rooms:create', this.createRoom, this);
        this.events.on('rooms:switch', this.switchRoom, this);
        this.events.on('rooms:archive', this.archiveRoom, this);
        this.events.on('profile:update', this.updateProfile, this);
    };
    //
    // Start
    //
    Client.prototype.start = function() {
        this.getEmotes();
        this.getReplacements();
        this.listen();
        this.route();
        this.view = new window.LCB.ClientView({
            client: this
        });
        //
        // Join rooms from localstorage
        //
        var openRooms = store.get('openrooms');
        if (openRooms instanceof Array) {
            // Flush the stored array
            store.set('openrooms', []);
            // Let's open some rooms!
            _.each(_.uniq(openRooms), function(id) {
                this.joinRoom(id);
            }, this);
        }
        return this;
    };
    //
    // Add to window
    //
    window.LCB = window.LCB || {};
    window.LCB.Client = Client;
})(window, $, _);
<|endoftext|>


<commit_before>const fse = require('fs-extra');
const os = require('os');
const inquirer = require('inquirer');
const crypto = require('crypto')
const zlib = require('zlib');
const fs = require('fs');
const shell = require('shelljs');
const figlet = require('figlet');
const path = require("path");
const replace = require("replace");
const Datauri = require('datauri').sync;
const absolutePath = path.resolve(".");
const algorithm = 'sha1';

function startBuild() {
    console.log(' Preparing for building Jste Framework ');
    shell.rm('-rf', 'tmp');
    shell.mkdir('tmp');
    shell.ln('-sf', absolutePath + '/src', 'tmp/src');
    shell.cd('build');
    shell.rm('-rf', '*');
    shell.mkdir('minified', 'compressed');
    fse.copySync(absolutePath + '/src/JS/Core/analyzeCommand-CompilationTemplate.js', absolutePath + '/tmp/analyzeCommand-Compiled.js');
    fse.copySync(absolutePath + '/src/JS/Core/wordsTranslationsInit-CompilationTemplate.js', absolutePath + '/tmp/wordsTranslationsInit-Compiled.js');
    fse.copySync(absolutePath + '/src/Res.html', absolutePath + '/tmp/Res.html');
    fse.copySync(absolutePath + '/src/Res-LiveVersion.html', absolutePath + '/tmp/Res-LiveVersion.html');
    var langCodes = ['en', 'fr', 'ar', 'arz'];
    for (var i = 0; i < langCodes.length; i++) {
        replace({
            regex: langCodes[i].toUpperCase() + "_RIVESCRIPT",
            replacement: Datauri(absolutePath + '/src/JS/Translations/RiveScript/' + langCodes[i] + '.rive'),
            paths: [absolutePath + '/tmp/analyzeCommand-Compiled.js'],
            recursive: true,
            silent: true,
        });
    }
    replace({
        regex: "DICTIONARY_URL",
        replacement: Datauri(absolutePath + '/src/JS/Translations/words.json'),
        paths: [absolutePath + '/tmp/wordsTranslationsInit-Compiled.js'],
        recursive: true,
        silent: true
    });
    replace({
        regex: 'src="(?!http)',
        replacement: 'src="src/',
        paths: [absolutePath + '/tmp/Res.html', absolutePath + '/tmp/Res-LiveVersion.html'],
        recursive: true,
        silent: true
    });
    replace({
        regex: 'href="(?!http)',
        replacement: 'href="src/',
        paths: [absolutePath + '/tmp/Res.html', absolutePath + '/tmp/Res-LiveVersion.html'],
        recursive: true,
        silent: true
    });
    replace({
        regex: 'src/JS/Core/wordsTranslationsInit\.js',
        replacement: 'wordsTranslationsInit-Compiled.js',
        paths: [absolutePath + '/tmp/Res.html', absolutePath + '/tmp/Res-LiveVersion.html'],
        recursive: true,
        silent: true
    });
    replace({
        regex: 'src/JS/Core/analyzeCommand\.js',
        replacement: 'analyzeCommand-Compiled.js',
        paths: [absolutePath + '/tmp/Res.html', absolutePath + '/tmp/Res-LiveVersion.html'],
        recursive: true,
        silent: true
    });
    console.log(' ');
    console.log(' Starting building Jste Framework ');
    var frameworkMinifiedFileInfo = {};
    var frameworkCompressedFileInfo = {};
    console.log(' Bundling the framework files into one HTML file ');
    shell.exec('polymer-bundler -r ' + absolutePath + '/tmp Res.html  --strip-comments --inline-scripts --inline-css --rewrite-urls-in-templates > framework.html');
    console.log(' Minifying the framework bundled file ');
    shell.exec('html-minifier framework.html --remove-comments --minify-css --minify-js --remove-comments --use-short-doctype > minified/framework.min.html');
    frameworkMinifiedFileInfo.size = fs.statSync('minified/framework.min.html').size;
    frameworkCompressedFileInfo.size = frameworkMinifiedFileInfo.size;
    console.log(' Hashing the framework minified file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fs.readFileSync('minified/framework.min.html', 'utf8'));
    frameworkMinifiedFileInfo.sha1 = shasum.digest('hex');
    fs.writeFileSync('minified/framework.info.json', JSON.stringify(frameworkMinifiedFileInfo));
    shell.rm('-rf', 'framework.html');
    console.log(' Compresssing the framework minified file ');
    var gzip = zlib.createGzip();
    var inp = fs.createReadStream('minified/framework.min.html');
    var out = fs.createWriteStream('compressed/framework.min.html.gz');
    inp.pipe(gzip).pipe(out);
    console.log(' Hashing the framework compressed file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fs.readFileSync('compressed/framework.min.html.gz', 'utf8'));
    frameworkCompressedFileInfo.sha1 = shasum.digest('hex');
    fs.writeFileSync('compressed/framework.info.json', JSON.stringify(frameworkCompressedFileInfo));
    console.log(' Jste Framework has been built properly ;) ');
    console.log(' ');
    console.log(' Starting building Jste Framework Live Version ');
    var frameworkLiveVersionMinifiedFileInfo = {};
    var frameworkLiveVersionCompressedFileInfo = {};
    console.log(' Bundling the framework files into one HTML file ');
    shell.exec('polymer-bundler -r ' + absolutePath + '/tmp Res-LiveVersion.html  --strip-comments --inline-scripts --inline-css --rewrite-urls-in-templates > framework-LiveVersion.html');
    console.log(' Minifying the framework bundled file ');
    shell.exec('html-minifier framework-LiveVersion.html --remove-comments --minify-css --minify-js --remove-comments --use-short-doctype > minified/framework-LiveVersion.min.html');
    frameworkLiveVersionMinifiedFileInfo.size = fs.statSync('minified/framework-LiveVersion.min.html').size;
    frameworkLiveVersionCompressedFileInfo.size = frameworkLiveVersionMinifiedFileInfo.size;
    console.log(' Hashing the framework minified file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fs.readFileSync('minified/framework-LiveVersion.min.html', 'utf8'));
    frameworkLiveVersionMinifiedFileInfo.sha1 = shasum.digest('hex');
    fs.writeFileSync('minified/framework-LiveVersion.info.json', JSON.stringify(frameworkLiveVersionMinifiedFileInfo));
    shell.rm('-rf', 'framework-LiveVersion.html');
    console.log(' Compresssing the framework minified file ');
    var gzip = zlib.createGzip();
    var inp = fs.createReadStream('minified/framework-LiveVersion.min.html');
    var out = fs.createWriteStream('compressed/framework-LiveVersion.min.html.gz');
    inp.pipe(gzip).pipe(out);
    console.log(' Hashing the framework compressed file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fs.readFileSync('compressed/framework-LiveVersion.min.html.gz', 'utf8'));
    frameworkLiveVersionCompressedFileInfo.sha1 = shasum.digest('hex');
    fs.writeFileSync('compressed/framework-LiveVersion.info.json', JSON.stringify(frameworkLiveVersionCompressedFileInfo));
    console.log(' Jste Framework Live Version has been built properly ;) ');
    console.log(' ');
    console.log(' Starting building the BLOB DB Manager for Jste Framework Live Version ');
    var dbManagerMinifiedFileInfo = {};
    var dbManagerCompressedFileInfo = {};
    console.log(' Minifying the BLOB DB Manager file ');
    shell.exec('html-minifier ../utils/db-manager.html --remove-comments --minify-css --minify-js --remove-comments --use-short-doctype > minified/db-manager.min.html');
    dbManagerMinifiedFileInfo.size = fs.statSync('minified/db-manager.min.html').size;
    dbManagerCompressedFileInfo.size = dbManagerMinifiedFileInfo.size;
    console.log(' Hashing the BLOB DB Manager minified file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fs.readFileSync('minified/db-manager.min.html', 'utf8'));
    dbManagerMinifiedFileInfo.sha1 = shasum.digest('hex');
    fs.writeFileSync('minified/db-manager.info.json', JSON.stringify(dbManagerMinifiedFileInfo));
    shell.rm('-rf', 'db-manager.html');
    console.log(' Compresssing the BLOB DB Manager minified file ');
    var gzip = zlib.createGzip();
    var inp = fs.createReadStream('minified/db-manager.min.html');
    var out = fs.createWriteStream('compressed/db-manager.min.html.gz');
    inp.pipe(gzip).pipe(out);
    console.log(' Hashing the BLOB DB Manager compressed file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fs.readFileSync('compressed/db-manager.min.html.gz', 'utf8'));
    dbManagerCompressedFileInfo.sha1 = shasum.digest('hex');
    fs.writeFileSync('compressed/db-manager.info.json', JSON.stringify(dbManagerCompressedFileInfo));
    console.log(' The BLOB DB Manager for Jste Framework Live Version has been built properly ;) ');
    shell.cd('../');
    shell.rm('-rf', 'tmp');
    if (global.gitURLPrefix) {
        console.log(' ');
        console.log(' Updating the index ');
        shell.exec('git add .');
        console.log(' ');
        console.log(' Recording the change to the local repo ');
        shell.exec('git commit -m "' + global.commitMessage + '"');
        console.log(' ');
        console.log(' Pushing the updates to GitHub ');
        shell.exec('git push ' + gitURLPrefix + 'framework.git master');
    }
    if (shell.test('-d', '../manager')) {
        console.log(' ');
        console.log(' Preparing for building Jste Manager ');
        shell.cd('../manager');
        console.log(' ');
        console.log(' Updating framework file ');
        shell.cp('../framework/build/compressed/framework.min.html.gz', 'src/assets');
        console.log(' ');
        console.log(' Starting building Jste Manager ');
        shell.exec('node build');
        if (global.gitURLPrefix) {
            console.log(' ');
            console.log(' Updating the index ');
            shell.exec('git add .');
            console.log(' ');
            console.log(' Recording the change to the local repo ');
            shell.exec('git commit -m "Updating Framework Files"');
            console.log(' ');
            console.log(' Pushing the updates to GitHub ');
            shell.exec('git push ' + gitURLPrefix + 'manager.git master');
        }
    }
    if (shell.test('-d', '../manager-heroku')) {
        console.log(' ');
        console.log(' Preparing for building Jste Manager Heroku version ');
        shell.cd('../manager-heroku');
        console.log(' ');
        console.log(' Updating framework file ');
        shell.cp(['../framework/build/compressed/framework-LiveVersion.min.html.gz', '../framework/build/compressed/db-manager.min.html.gz'], 'assets');
        if (global.gitURLPrefix) {
            console.log(' ');
            console.log(' Updating the index ');
            shell.exec('git add .');
            console.log(' ');
            console.log(' Recording the change to the local repo ');
            shell.exec('git commit -m "Updating Framework Files"');
            console.log(' ');
            console.log(' Pushing the updates to GitHub ');
            shell.exec('git push ' + gitURLPrefix + 'manager-heroku.git master');
            console.log(' ');
            console.log(' Pushing the updates to Heroku ');
            shell.exec('git push heroku master');
        }
    }
    if (shell.test('-d', '../manager-phone')) {
        console.log(' ');
        console.log(' Preparing for building Jste Manager phone version ');
        shell.cd('../manager-phone/src');
        console.log(' ');
        console.log(' Updating framework file ');
        shell.cp('../../framework/build/minified/framework.min.html', 'www/jxcore/assets');
        console.log(' ');
        console.log(' Starting building Jste Manager phone version ');
        shell.exec('cordova build');
        shell.cd('../');
        shell.cp('src/platforms/android/build/outputs/apk/debug/android-debug.apk', 'build');
        if (global.gitURLPrefix) {
            console.log(' ');
            console.log(' Updating the index ');
            shell.exec('git add .');
            console.log(' ');
            console.log(' Recording the change to the local repo ');
            shell.exec('git commit -m "Updating Framework Files"');
            console.log(' ');
            console.log(' Pushing the updates to GitHub ');
            shell.exec('git push ' + gitURLPrefix + 'manager-phone.git master');
        }
    }
}

figlet('JSTE FRAMEWORK', function (err, data) {
    console.log(data);
    console.log('');
    console.log(' Welcome to Jste Framework builder :) ')
    inquirer
        .prompt([{
            type: 'confirm',
            name: 'deploy',
            message: 'Do you want to deploy this build ?'
        }])
        .then(options => {
            if (options.deploy == true) {
                inquirer
                    .prompt([{
                        type: 'input',
                        name: 'commit_message',
                        message: 'Please enter the commit message '
                    },{
                            type: 'input',
                            name: 'git_username',
                            message: 'Please enter your GitHub username '
                        },
                        {
                            type: 'password',
                            name: 'git_password',
                            mask: '*',
                            message: 'Please enter your GitHub password '
                        }
                    ]).then(git_info => {
                        global.gitURLPrefix = 'https://' + git_info.git_username + ':' + git_info.git_password + '@github.com/project-jste/';
                        global.commitMessage = git_info.commit_message;
                        startBuild();
                    })
            } else {
                startBuild();
            }
        });
});<commit_msg>Bug Fixes<commit_after>const fse = require('fs-extra');
const os = require('os');
const inquirer = require('inquirer');
const crypto = require('crypto')
const zlib = require('zlib');
const shell = require('shelljs');
const figlet = require('figlet');
const path = require("path");
const replace = require("replace");
const Datauri = require('datauri').sync;
const absolutePath = path.resolve(".");
const algorithm = 'sha1';

function startBuild() {
    console.log(' Preparing for building Jste Framework ');
    shell.rm('-rf', 'tmp');
    shell.mkdir('tmp');
    shell.ln('-sf', absolutePath + '/src', 'tmp/src');
    shell.cd('build');
    shell.rm('-rf', '*');
    shell.mkdir('minified', 'compressed');
    fse.copySync(absolutePath + '/src/JS/Core/analyzeCommand-CompilationTemplate.js', absolutePath + '/tmp/analyzeCommand-Compiled.js');
    fse.copySync(absolutePath + '/src/JS/Core/wordsTranslationsInit-CompilationTemplate.js', absolutePath + '/tmp/wordsTranslationsInit-Compiled.js');
    fse.copySync(absolutePath + '/src/Res.html', absolutePath + '/tmp/Res.html');
    fse.copySync(absolutePath + '/src/Res-LiveVersion.html', absolutePath + '/tmp/Res-LiveVersion.html');
    var langCodes = ['en', 'fr', 'ar', 'arz'];
    for (var i = 0; i < langCodes.length; i++) {
        replace({
            regex: langCodes[i].toUpperCase() + "_RIVESCRIPT",
            replacement: Datauri(absolutePath + '/src/JS/Translations/RiveScript/' + langCodes[i] + '.rive'),
            paths: [absolutePath + '/tmp/analyzeCommand-Compiled.js'],
            recursive: true,
            silent: true,
        });
    }
    replace({
        regex: "DICTIONARY_URL",
        replacement: Datauri(absolutePath + '/src/JS/Translations/words.json'),
        paths: [absolutePath + '/tmp/wordsTranslationsInit-Compiled.js'],
        recursive: true,
        silent: true
    });
    replace({
        regex: 'src="(?!http)',
        replacement: 'src="src/',
        paths: [absolutePath + '/tmp/Res.html', absolutePath + '/tmp/Res-LiveVersion.html'],
        recursive: true,
        silent: true
    });
    replace({
        regex: 'href="(?!http)',
        replacement: 'href="src/',
        paths: [absolutePath + '/tmp/Res.html', absolutePath + '/tmp/Res-LiveVersion.html'],
        recursive: true,
        silent: true
    });
    replace({
        regex: 'src/JS/Core/wordsTranslationsInit\.js',
        replacement: 'wordsTranslationsInit-Compiled.js',
        paths: [absolutePath + '/tmp/Res.html', absolutePath + '/tmp/Res-LiveVersion.html'],
        recursive: true,
        silent: true
    });
    replace({
        regex: 'src/JS/Core/analyzeCommand\.js',
        replacement: 'analyzeCommand-Compiled.js',
        paths: [absolutePath + '/tmp/Res.html', absolutePath + '/tmp/Res-LiveVersion.html'],
        recursive: true,
        silent: true
    });
    console.log(' ');
    console.log(' Starting building Jste Framework ');
    var frameworkMinifiedFileInfo = {};
    var frameworkCompressedFileInfo = {};
    console.log(' Bundling the framework files into one HTML file ');
    shell.exec('polymer-bundler -r ' + absolutePath + '/tmp Res.html  --strip-comments --inline-scripts --inline-css --rewrite-urls-in-templates > framework.html');
    console.log(' Minifying the framework bundled file ');
    shell.exec('html-minifier framework.html --remove-comments --minify-css --minify-js --remove-comments --use-short-doctype > minified/framework.min.html');
    frameworkMinifiedFileInfo.size = fse.statSync('minified/framework.min.html').size;
    frameworkCompressedFileInfo.size = frameworkMinifiedFileInfo.size;
    console.log(' Hashing the framework minified file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fse.readFileSync('minified/framework.min.html', 'utf8'));
    frameworkMinifiedFileInfo.sha1 = shasum.digest('hex');
    fse.writeFileSync('minified/framework.info.json', JSON.stringify(frameworkMinifiedFileInfo));
    shell.rm('-rf', 'framework.html');
    console.log(' Compresssing the framework minified file ');
    var gzip = zlib.createGzip();
    var inp = fse.createReadStream('minified/framework.min.html');
    var out = fse.createWriteStream('compressed/framework.min.html.gz');
    inp.pipe(gzip).pipe(out);
    console.log(' Hashing the framework compressed file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fse.readFileSync('compressed/framework.min.html.gz', 'utf8'));
    frameworkCompressedFileInfo.sha1 = shasum.digest('hex');
    fse.writeFileSync('compressed/framework.info.json', JSON.stringify(frameworkCompressedFileInfo));
    console.log(' Jste Framework has been built properly ;) ');
    console.log(' ');
    console.log(' Starting building Jste Framework Live Version ');
    var frameworkLiveVersionMinifiedFileInfo = {};
    var frameworkLiveVersionCompressedFileInfo = {};
    console.log(' Bundling the framework files into one HTML file ');
    shell.exec('polymer-bundler -r ' + absolutePath + '/tmp Res-LiveVersion.html  --strip-comments --inline-scripts --inline-css --rewrite-urls-in-templates > framework-LiveVersion.html');
    console.log(' Minifying the framework bundled file ');
    shell.exec('html-minifier framework-LiveVersion.html --remove-comments --minify-css --minify-js --remove-comments --use-short-doctype > minified/framework-LiveVersion.min.html');
    frameworkLiveVersionMinifiedFileInfo.size = fse.statSync('minified/framework-LiveVersion.min.html').size;
    frameworkLiveVersionCompressedFileInfo.size = frameworkLiveVersionMinifiedFileInfo.size;
    console.log(' Hashing the framework minified file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fse.readFileSync('minified/framework-LiveVersion.min.html', 'utf8'));
    frameworkLiveVersionMinifiedFileInfo.sha1 = shasum.digest('hex');
    fse.writeFileSync('minified/framework-LiveVersion.info.json', JSON.stringify(frameworkLiveVersionMinifiedFileInfo));
    shell.rm('-rf', 'framework-LiveVersion.html');
    console.log(' Compresssing the framework minified file ');
    var gzip = zlib.createGzip();
    var inp = fse.createReadStream('minified/framework-LiveVersion.min.html');
    var out = fse.createWriteStream('compressed/framework-LiveVersion.min.html.gz');
    inp.pipe(gzip).pipe(out);
    console.log(' Hashing the framework compressed file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fse.readFileSync('compressed/framework-LiveVersion.min.html.gz', 'utf8'));
    frameworkLiveVersionCompressedFileInfo.sha1 = shasum.digest('hex');
    fse.writeFileSync('compressed/framework-LiveVersion.info.json', JSON.stringify(frameworkLiveVersionCompressedFileInfo));
    console.log(' Jste Framework Live Version has been built properly ;) ');
    console.log(' ');
    console.log(' Starting building the BLOB DB Manager for Jste Framework Live Version ');
    var dbManagerMinifiedFileInfo = {};
    var dbManagerCompressedFileInfo = {};
    console.log(' Minifying the BLOB DB Manager file ');
    shell.exec('html-minifier ../utils/db-manager.html --remove-comments --minify-css --minify-js --remove-comments --use-short-doctype > minified/db-manager.min.html');
    dbManagerMinifiedFileInfo.size = fse.statSync('minified/db-manager.min.html').size;
    dbManagerCompressedFileInfo.size = dbManagerMinifiedFileInfo.size;
    console.log(' Hashing the BLOB DB Manager minified file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fse.readFileSync('minified/db-manager.min.html', 'utf8'));
    dbManagerMinifiedFileInfo.sha1 = shasum.digest('hex');
    fse.writeFileSync('minified/db-manager.info.json', JSON.stringify(dbManagerMinifiedFileInfo));
    shell.rm('-rf', 'db-manager.html');
    console.log(' Compresssing the BLOB DB Manager minified file ');
    var gzip = zlib.createGzip();
    var inp = fse.createReadStream('minified/db-manager.min.html');
    var out = fse.createWriteStream('compressed/db-manager.min.html.gz');
    inp.pipe(gzip).pipe(out);
    console.log(' Hashing the BLOB DB Manager compressed file ');
    var shasum = crypto.createHash(algorithm);
    shasum.update(fse.readFileSync('compressed/db-manager.min.html.gz', 'utf8'));
    dbManagerCompressedFileInfo.sha1 = shasum.digest('hex');
    fse.writeFileSync('compressed/db-manager.info.json', JSON.stringify(dbManagerCompressedFileInfo));
    console.log(' The BLOB DB Manager for Jste Framework Live Version has been built properly ;) ');
    shell.cd('../');
    shell.rm('-rf', 'tmp');
    if (global.gitURLPrefix) {
        console.log(' ');
        console.log(' Updating the index ');
        shell.exec('git add .');
        console.log(' ');
        console.log(' Recording the change to the local repo ');
        shell.exec('git commit -m "' + global.commitMessage + '"');
        console.log(' ');
        console.log(' Pushing the updates to GitHub ');
        shell.exec('git push ' + gitURLPrefix + 'framework.git master');
    }
    if (shell.test('-d', '../manager')) {
        console.log(' ');
        console.log(' Preparing for building Jste Manager ');
        shell.cd('../manager');
        console.log(' ');
        console.log(' Updating framework file ');
        fse.copySync(path.resolve('..') + '/framework/build/compressed/framework.min.html.gz', path.resolve('.') + '/src/assets');
        console.log(' ');
        console.log(' Starting building Jste Manager ');
        shell.exec('node build');
        if (global.gitURLPrefix) {
            console.log(' ');
            console.log(' Updating the index ');
            shell.exec('git add .');
            console.log(' ');
            console.log(' Recording the change to the local repo ');
            shell.exec('git commit -m "Updating Framework Files"');
            console.log(' ');
            console.log(' Pushing the updates to GitHub ');
            shell.exec('git push ' + gitURLPrefix + 'manager.git master');
        }
    }
    if (shell.test('-d', '../manager-heroku')) {
        console.log(' ');
        console.log(' Preparing for building Jste Manager Heroku version ');
        shell.cd('../manager-heroku');
        console.log(' ');
        console.log(' Updating framework file ');
        fse.copySync(path.resolve('..') + '/framework/build/compressed/framework-LiveVersion.min.html.gz', path.resolve('.') + '/assets');
        fse.copySync(path.resolve('..') + '/framework/build/compressed/db-manager.min.html.gz', path.resolve('.') + '/assets');
        if (global.gitURLPrefix) {
            console.log(' ');
            console.log(' Updating the index ');
            shell.exec('git add .');
            console.log(' ');
            console.log(' Recording the change to the local repo ');
            shell.exec('git commit -m "Updating Framework Files"');
            console.log(' ');
            console.log(' Pushing the updates to GitHub ');
            shell.exec('git push ' + gitURLPrefix + 'manager-heroku.git master');
            console.log(' ');
            console.log(' Pushing the updates to Heroku ');
            shell.exec('git push heroku master');
        }
    }
    if (shell.test('-d', '../manager-phone')) {
        console.log(' ');
        console.log(' Preparing for building Jste Manager phone version ');
        shell.cd('../manager-phone/src');
        console.log(' ');
        console.log(' Updating framework file ');
        fse.copySync(path.resolve('../..') + '/framework/build/minified/framework.min.html', path.resolve('.') + '/www/jxcore/assets');
        console.log(' ');
        console.log(' Starting building Jste Manager phone version ');
        shell.exec('cordova build');
        shell.cd('../');
        shell.cp('src/platforms/android/build/outputs/apk/debug/android-debug.apk', 'build');
        if (global.gitURLPrefix) {
            console.log(' ');
            console.log(' Updating the index ');
            shell.exec('git add .');
            console.log(' ');
            console.log(' Recording the change to the local repo ');
            shell.exec('git commit -m "Updating Framework Files"');
            console.log(' ');
            console.log(' Pushing the updates to GitHub ');
            shell.exec('git push ' + gitURLPrefix + 'manager-phone.git master');
        }
    }
}

figlet('JSTE FRAMEWORK', function (err, data) {
    console.log(data);
    console.log('');
    console.log(' Welcome to Jste Framework builder :) ')
    inquirer
        .prompt([{
            type: 'confirm',
            name: 'deploy',
            message: 'Do you want to deploy this build ?'
        }])
        .then(options => {
            if (options.deploy == true) {
                inquirer
                    .prompt([{
                            type: 'input',
                            name: 'commit_message',
                            message: 'Please enter the commit message '
                        }, {
                            type: 'input',
                            name: 'git_username',
                            message: 'Please enter your GitHub username '
                        },
                        {
                            type: 'password',
                            name: 'git_password',
                            mask: '*',
                            message: 'Please enter your GitHub password '
                        }
                    ]).then(git_info => {
                        global.gitURLPrefix = 'https://' + git_info.git_username + ':' + git_info.git_password + '@github.com/project-jste/';
                        global.commitMessage = git_info.commit_message;
                        startBuild();
                    })
            } else {
                startBuild();
            }
        });
});<|endoftext|>