<commit_before>// Description:
//   Grants temporary acces to MySQL databases
//
// Commands:
//   hubot give me [ `read` | `write` | `admin` ] access to `environment` database - Gives you temporary credentials to access the `environment` database
//

/*
 * External dependencies
 */
var util = require('util');
var pkg = require('../package.json');
var CONFIG = require('config').get(pkg.name);
var uuid = require('node-uuid');
var crypto = require('crypto');
var swig = require('swig');

/*
 * Internal dependencies
 */
var heimdall = require('../lib/db_heimdall');

module.exports = function(robot) {

  var searchDb = function(db_name) {
    for (var i in CONFIG.Databases) {
      if (CONFIG.Databases[i].matcher.test(db_name)) {
        return CONFIG.Databases[i];
      }
    }
    return null;
  };

  var checkVaultRole = function(db, role) {
    for (var i in db.vault_roles) {
      if (db.vault_roles[i].matcher.test(role)) {
        return db.vault_roles[i].name;
      }
    }
    return null;
  };

  // Setup robot http render engine
  if (robot.router.engine) {
    // In test environment, we don't have an http server so this methods won't work
    robot.router.engine('html', swig.renderFile);
    robot.router.set('view engine', 'html');
    robot.router.set('views', __dirname + '/../views');
    robot.router.set('view cache', false);
  }

  // Register tasker to the robot instance
  require('../lib/tasker')(robot);

  // Setup db_heimdall module with the robot instance
  heimdall.setup(robot);

  robot.router.get('/heimdall/access/:nonce', function(req, res) {
    // Ignore robots
    if (req.headers['user-agent'].match(/Slackbot/i) !== null) {
      return res.send(200);
    }

    // Check if DB access request is genuine
    var brain_key = util.format('heimdall_access_%s', req.params.nonce);
    var access_request = robot.brain.get(brain_key);

    if (typeof(access_request) !== 'object' || access_request === null) {
      // Not found
      return res.render('not_found');
    }

    // Get client ip
    var ip = req.connection.remoteAddress; // fallback
    if (req.headers['x-real-ip'] !== undefined) { // 1st choice
      ip = req.headers['x-real-ip'].replace(/ /g, '');
    } else if (req.headers['x-forwarded-for'] !== undefined) { // 2nd choice
      ip = req.headers['x-forwarded-for'].split(',')[0].replace(/ /g, '');
    }

    // Append the CIDRIP notation
    ip += '/32';

    // Compute the ttl according the duration of the vault lease
    var ttl = (access_request.lease_duration * 1000) - (new Date().getTime() - access_request.requested);
    if (ttl < 0) {
      // Obsolete request
      res.render('not_found');
    } else {
      heimdall.allowAccessToIp({
        DBSecurityGroupName: access_request.rds_security_group,
        CIDRIP: ip,
        ttl: ttl
      }, function(err) {
        if (err) {
          res.render('error', { error: util.inspect(err) });
        } else {
          res.render('ip_success', { ip: ip, ttl: util.format('%d minutes', Math.floor(ttl / 60000)) });
        }
      });
    }

    // Remove access request from brain
    robot.brain.remove(brain_key);
  });

  robot.respond(/give me (\w+) access to (\w+) (?:database|db)/i, function(msg) {
    // Check if the user has a vault token
    if (msg.envelope.user.Creds === undefined || msg.envelope.user.Creds.vault_token === undefined) {
      return msg.send(util.format(
        CONFIG.Strings.sorry_dave +
        '\nI need your vault token in order to do this.\nYou should ask your beloved sysadmin ;)',
        msg.envelope.user.name
      ));
    }

    // First check the corresponding database
    var db = searchDb(msg.match[2]);
    if (db === null) {
      // TODO: print available databases
      return msg.send(util.format(
        CONFIG.Strings.sorry_dave + '\nUnknown database *%s*.',
        msg.envelope.user.name,
        msg.match[2]
      ));
    }

    // Now check the access level requested for this database
    var role = checkVaultRole(db, msg.match[1]);
    if (role === null) {
      // TODO: print available vault roles
      return msg.send(util.format(
        CONFIG.Strings.sorry_dave + '\nUnknown access level *%s*.',
        msg.envelope.user.name,
        msg.match[1]
      ));
    }

    // Request the credentials to vault
    // vault read mysql/creds/readonly
    var url = util.format(
      '%s/v1/%s/creds/%s',
      CONFIG.Urls.vault_base_url,
      db.vault_mount,
      role
    );

    robot.http(url)
    .header('X-Vault-Token', msg.envelope.user.Creds.vault_token)
    .get()(function(err, res, body) {
      // Unknown error handler
      var unknownError = function() {
        msg.reply('An error occurred talking to vault, please try again in a few moments');

        if (res && res.statusCode) msg.reply('Status code: ' + res.statusCode);
        if (err) msg.reply('Error: ' + err);
        if (body) msg.reply('Body: ' + body);
      };

      if (err) {
        return unknownError();
      }

      if (res.statusCode === 401 || res.statusCode === 400 || res.statusCode === 404) {
        return msg.send(util.format(
          CONFIG.Strings.sorry_dave + '\nYou\'re not authorized to request *%s* access to *%s* database',
          msg.envelope.user.name,
          role,
          db.name
        ));
      } else if (res.statusCode === 503) {
        return msg.send(util.format(
          CONFIG.Strings.sorry_dave + '\nVault is sealed and I cannot retreave any data from it',
          msg.envelope.user.name
        ));
      } else if (res.statusCode > 299) {
        return unknownError();
      }// else if (res.statusCode >= 200 && res.statusCode <= 299)

      // Build the response based on the fields returned by vault
      var response = [ 'Here ya go:' ];

      var parsedBody;
      try {
        parsedBody = JSON.parse(body);
      } catch (e) {
        return msg.reply('An error occurred parsing the vault response', body);
      }

      var parse = function(data) {
        for (var k in data) {
          if (data.hasOwnProperty(k)) {
            if (typeof(data[k]) === 'object') {
              // Parse recursively
              parse(data[k]);
            } else {
              if (k === 'username' || k === 'password') {
                response.push('*' + k + '*: ' + data[k]);
              } else {
                response.push(k + ': ' + data[k]);
              }
            }
          }
        }
      };

      // For now this will be sync as only small data will be parsed
      parse(parsedBody);

      robot.send({ room: msg.envelope.user.name }, response.join('\n'));

      // Send a link to enable IP access to DB
      var nonce = crypto.createHash('sha256').update(uuid.v4(), 'utf8').digest('hex');
      robot.brain.set(util.format('heimdall_access_%s', nonce), {
        rds_security_group: db.rds_security_group,
        requested: new Date().getTime(),
        lease_duration: parsedBody.lease_duration
      });

      robot.send(
        { room: msg.envelope.user.name },
        'Direct your browser here to enable access to DB from your current IP address\n' +
        CONFIG.Urls.base_url + 'heimdall/access/' + nonce
      );

      if (msg.envelope.room !== robot.brain.userForId(msg.envelope.user.id).room) {
        msg.reply('I\'ve sent the access credentials in a private chat');
      }
    });
  });

};
<commit_msg>Fix hubot command help accordingly<commit_after>// Description:
//   Grants temporary acces to MySQL databases
//
// Commands:
//   hubot give me `level` access to `database` database - Gives you temporary credentials to access the specified database
//

/*
 * External dependencies
 */
var util = require('util');
var pkg = require('../package.json');
var CONFIG = require('config').get(pkg.name);
var uuid = require('node-uuid');
var crypto = require('crypto');
var swig = require('swig');

/*
 * Internal dependencies
 */
var heimdall = require('../lib/db_heimdall');

module.exports = function(robot) {

  var searchDb = function(db_name) {
    for (var i in CONFIG.Databases) {
      if (CONFIG.Databases[i].matcher.test(db_name)) {
        return CONFIG.Databases[i];
      }
    }
    return null;
  };

  var checkVaultRole = function(db, role) {
    for (var i in db.vault_roles) {
      if (db.vault_roles[i].matcher.test(role)) {
        return db.vault_roles[i].name;
      }
    }
    return null;
  };

  // Setup robot http render engine
  if (robot.router.engine) {
    // In test environment, we don't have an http server so this methods won't work
    robot.router.engine('html', swig.renderFile);
    robot.router.set('view engine', 'html');
    robot.router.set('views', __dirname + '/../views');
    robot.router.set('view cache', false);
  }

  // Register tasker to the robot instance
  require('../lib/tasker')(robot);

  // Setup db_heimdall module with the robot instance
  heimdall.setup(robot);

  robot.router.get('/heimdall/access/:nonce', function(req, res) {
    // Ignore robots
    if (req.headers['user-agent'].match(/Slackbot/i) !== null) {
      return res.send(200);
    }

    // Check if DB access request is genuine
    var brain_key = util.format('heimdall_access_%s', req.params.nonce);
    var access_request = robot.brain.get(brain_key);

    if (typeof(access_request) !== 'object' || access_request === null) {
      // Not found
      return res.render('not_found');
    }

    // Get client ip
    var ip = req.connection.remoteAddress; // fallback
    if (req.headers['x-real-ip'] !== undefined) { // 1st choice
      ip = req.headers['x-real-ip'].replace(/ /g, '');
    } else if (req.headers['x-forwarded-for'] !== undefined) { // 2nd choice
      ip = req.headers['x-forwarded-for'].split(',')[0].replace(/ /g, '');
    }

    // Append the CIDRIP notation
    ip += '/32';

    // Compute the ttl according the duration of the vault lease
    var ttl = (access_request.lease_duration * 1000) - (new Date().getTime() - access_request.requested);
    if (ttl < 0) {
      // Obsolete request
      res.render('not_found');
    } else {
      heimdall.allowAccessToIp({
        DBSecurityGroupName: access_request.rds_security_group,
        CIDRIP: ip,
        ttl: ttl
      }, function(err) {
        if (err) {
          res.render('error', { error: util.inspect(err) });
        } else {
          res.render('ip_success', { ip: ip, ttl: util.format('%d minutes', Math.floor(ttl / 60000)) });
        }
      });
    }

    // Remove access request from brain
    robot.brain.remove(brain_key);
  });

  robot.respond(/give me (\w+) access to (\w+) (?:database|db)/i, function(msg) {
    // Check if the user has a vault token
    if (msg.envelope.user.Creds === undefined || msg.envelope.user.Creds.vault_token === undefined) {
      return msg.send(util.format(
        CONFIG.Strings.sorry_dave +
        '\nI need your vault token in order to do this.\nYou should ask your beloved sysadmin ;)',
        msg.envelope.user.name
      ));
    }

    // First check the corresponding database
    var db = searchDb(msg.match[2]);
    if (db === null) {
      // TODO: print available databases
      return msg.send(util.format(
        CONFIG.Strings.sorry_dave + '\nUnknown database *%s*.',
        msg.envelope.user.name,
        msg.match[2]
      ));
    }

    // Now check the access level requested for this database
    var role = checkVaultRole(db, msg.match[1]);
    if (role === null) {
      // TODO: print available vault roles
      return msg.send(util.format(
        CONFIG.Strings.sorry_dave + '\nUnknown access level *%s*.',
        msg.envelope.user.name,
        msg.match[1]
      ));
    }

    // Request the credentials to vault
    // vault read mysql/creds/readonly
    var url = util.format(
      '%s/v1/%s/creds/%s',
      CONFIG.Urls.vault_base_url,
      db.vault_mount,
      role
    );

    robot.http(url)
    .header('X-Vault-Token', msg.envelope.user.Creds.vault_token)
    .get()(function(err, res, body) {
      // Unknown error handler
      var unknownError = function() {
        msg.reply('An error occurred talking to vault, please try again in a few moments');

        if (res && res.statusCode) msg.reply('Status code: ' + res.statusCode);
        if (err) msg.reply('Error: ' + err);
        if (body) msg.reply('Body: ' + body);
      };

      if (err) {
        return unknownError();
      }

      if (res.statusCode === 401 || res.statusCode === 400 || res.statusCode === 404) {
        return msg.send(util.format(
          CONFIG.Strings.sorry_dave + '\nYou\'re not authorized to request *%s* access to *%s* database',
          msg.envelope.user.name,
          role,
          db.name
        ));
      } else if (res.statusCode === 503) {
        return msg.send(util.format(
          CONFIG.Strings.sorry_dave + '\nVault is sealed and I cannot retreave any data from it',
          msg.envelope.user.name
        ));
      } else if (res.statusCode > 299) {
        return unknownError();
      }// else if (res.statusCode >= 200 && res.statusCode <= 299)

      // Build the response based on the fields returned by vault
      var response = [ 'Here ya go:' ];

      var parsedBody;
      try {
        parsedBody = JSON.parse(body);
      } catch (e) {
        return msg.reply('An error occurred parsing the vault response', body);
      }

      var parse = function(data) {
        for (var k in data) {
          if (data.hasOwnProperty(k)) {
            if (typeof(data[k]) === 'object') {
              // Parse recursively
              parse(data[k]);
            } else {
              if (k === 'username' || k === 'password') {
                response.push('*' + k + '*: ' + data[k]);
              } else {
                response.push(k + ': ' + data[k]);
              }
            }
          }
        }
      };

      // For now this will be sync as only small data will be parsed
      parse(parsedBody);

      robot.send({ room: msg.envelope.user.name }, response.join('\n'));

      // Send a link to enable IP access to DB
      var nonce = crypto.createHash('sha256').update(uuid.v4(), 'utf8').digest('hex');
      robot.brain.set(util.format('heimdall_access_%s', nonce), {
        rds_security_group: db.rds_security_group,
        requested: new Date().getTime(),
        lease_duration: parsedBody.lease_duration
      });

      robot.send(
        { room: msg.envelope.user.name },
        'Direct your browser here to enable access to DB from your current IP address\n' +
        CONFIG.Urls.base_url + 'heimdall/access/' + nonce
      );

      if (msg.envelope.room !== robot.brain.userForId(msg.envelope.user.id).room) {
        msg.reply('I\'ve sent the access credentials in a private chat');
      }
    });
  });

};
<|endoftext|>


<commit_before>/*
* (C) Copyright 2014 Kurento (http://kurento.org/)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-2.1.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/

var webRtcPeer;
var videoInput;
var videoOutput;

window.onload = function() {
	console = new Console('console', console);
	videoInput = document.getElementById('videoInput');
	videoOutput = document.getElementById('videoOutput');
}

function start() {
	showSpinner(videoInput, videoOutput);

	webRtcPeer = kurentoUtils.WebRtcPeer.startSendRecv(videoInput, videoOutput,
			function(offerSdp, wp) {
				console.info('Invoking SDP offer callback function '
						+ location.host);
				$.ajax({
					url : location.protocol + '/helloworld',
					type : 'POST',
					dataType : 'text',
					contentType : 'application/sdp',
					data : offerSdp,
					success : function(data) {
						wp.processSdpAnswer(data);
					},
					error : function(jqXHR, textStatus, error) {
						console.error(error);
					}
				});
			});
}

function stop() {
	if (webRtcPeer) {
		webRtcPeer.dispose();
	}
	videoInput.src = '';
	videoOutput.src = '';
	hideSpinner(videoInput, videoOutput);
}

function showSpinner() {
	for (var i = 0; i < arguments.length; i++) {
		arguments[i].poster = './img/transparent-1px.png';
		arguments[i].style.background = "center transparent url('./img/spinner.gif') no-repeat";
	}
}

function hideSpinner() {
	for (var i = 0; i < arguments.length; i++) {
		arguments[i].poster = './img/webrtc.png';
		arguments[i].style.background = '';
	}
}
<commit_msg>Additional console log data helpful for diagnosis.<commit_after>/*
* (C) Copyright 2014 Kurento (http://kurento.org/)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-2.1.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/

var webRtcPeer;
var videoInput;
var videoOutput;

window.onload = function() {
	console = new Console('console', console);
	console.log("Loading complete ...");
	videoInput = document.getElementById('videoInput');
	videoOutput = document.getElementById('videoOutput');
}

function start() {
	console.log("Starting video call ...");
	showSpinner(videoInput, videoOutput);

	webRtcPeer = kurentoUtils.WebRtcPeer.startSendRecv(videoInput, videoOutput,
			function(offerSdp, wp) {
				console.info('Invoking SDP offer callback function '
						+ location.host);
				$.ajax({
					url : location.protocol + '/helloworld',
					type : 'POST',
					dataType : 'text',
					contentType : 'application/sdp',
					data : offerSdp,
					success : function(data) {
						console.log("Received sdpAnswer from server. Processing ...");
						wp.processSdpAnswer(data);
					},
					error : function(jqXHR, textStatus, error) {
						console.error(error);
					}
				});
			});
}

function stop() {
	console.log("Stopping video call ...");
	if (webRtcPeer) {
		webRtcPeer.dispose();
	}
	videoInput.src = '';
	videoOutput.src = '';
	hideSpinner(videoInput, videoOutput);
}

function showSpinner() {
	for (var i = 0; i < arguments.length; i++) {
		arguments[i].poster = './img/transparent-1px.png';
		arguments[i].style.background = "center transparent url('./img/spinner.gif') no-repeat";
	}
}

function hideSpinner() {
	for (var i = 0; i < arguments.length; i++) {
		arguments[i].poster = './img/webrtc.png';
		arguments[i].style.background = '';
	}
}
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
    isOpen: null,
    actions: {
        addLayer (type) {
            let item;
            switch(type) {
                case 'wiki' :
                item = {
                    "sectionHeader": "Wiki example",
                    "component": "layer-wiki",
                    "settings": {
                        "component": "layer-settings",
                        "wikiId": "",
                        "values": {
                            "sectionTitle": "Wiki example",
                            "showInNavigation": true,
                            "addShowMore": false,
                            "bgColor": "#FFFFFF",
                            "color": "#333333",
                            "alignment": "center"
                        },
                        "form": [
                        {
                            "type": "settings",
                            "items": [
                            {
                                "type": "checkbox",
                                "label": "Show in navigation",
                                "value": "showInNavigation",
                                "validation": null
                            },
                            {
                                "type": "checkbox",
                                "label": "Add show more",
                                "value": "addShowMore",
                                "validation": null
                            }
                            ]
                        },
                        {
                            "type": "alignment",
                            "label": "Alignment",
                            "value": "alignment",
                            "options": [
                                "left",
                                "center",
                                "right"
                            ],
                            "validation": null
                        }
                        ]
                    }
                };
                break;
                case 'file':
                item = {
                    "sectionHeader": "Download",
                    "component": "layer-file",
                    "settings": {
                        "component": "layer-settings",
                        "values": {
                            "sectionTitle": "Download this file",
                            "sectionDescription": "",
                            "showFileviewer": true,
                            "downloadLink": "",
                            "showInNavigation": true,
                            "bgColor": "#FFFFFF",
                            "alignment": "center",
                            "color": "#333333"
                        },
                        "form": [
                        {
                            "type": "settings",
                            "items": [
                            {
                                "type": "checkbox",
                                "label": "Show in navigation",
                                "value": "showInNavigation",
                                "validation": null
                            },
                            {
                                "type": "checkbox",
                                "label": "Show file viewer",
                                "value": "showFileviewer",
                                "validation": null
                            }
                            ]
                        },
                        {
                            "type": "alignment",
                            "label": "Alignment",
                            "value": "alignment",
                            "options": [
                                "left",
                                "center",
                                "right"
                            ],
                            "validation": null
                        }
                        ]
                    }
                };
                break;
                case 'link':
                item = {
                    "sectionHeader": "Link",
                    "component": "layer-link",
                    "settings": {
                        "component": "layer-settings",
                        "values": {
                            "sectionTitle": "Link Title",
                            "showInNavigation": true,
                            "sectionDescription": "this link goes to a place",
                            "sectionLink": "www.example.com",
                            "bgColor": "#FFFFFF",
                            "alignment": "center",
                            "color": "#333333"
                        },
                        "form": [
                        {
                            "type": "settings",
                            "items": [
                            {
                                "type": "checkbox",
                                "label": "Show in navigation",
                                "value": "showInNavigation",
                                "validation": null
                            },
                            {
                                "type": "text",
                                "label": "Link address",
                                "value": "sectionLink",
                                "validation": null
                            }
                            ]
                        },
                        {
                            "type": "alignment",
                            "label": "Alignment",
                            "value": "alignment",
                            "options": [
                                "left",
                                "center",
                                "right"
                            ],
                            "validation": null
                        }
                        ]
                    }
                };
                break;
                case 'advanced':
                item = {
                    "sectionHeader": "Advanced",
                    "component": "layer-advanced",
                    "content": "
Mauris imperdie Praesent ut fringilla orci. Proin feugiat auctor augue non rutrum. Sed ac metus in augue dignissim malesuada non et sem. Pellentesque ut metus odio. Integer fringilla nulla id leo consequat, a sollicitudin sapien fringilla. Fusce vestibulum malesuada nisl. Fusce augue leo, tempus eget matssstis vel, imperdiet at nulla
",
                    "settings": {
                        "component": "layer-settings",
                        "values": {
                            "sectionTitle": "Advanced",
                            "showInNavigation": true,
                            "bgColor": "#FFFFFF",
                            "alignment": "center",
                            "color": "#333333"
                        },
                        "form": [
                        {
                            "type": "settings",
                            "items": [
                            {
                                "type": "checkbox",
                                "label": "Show in navigation",
                                "value": "showInNavigation",
                                "validation": null
                            }
                            ]
                        },
                        {
                            "type": "alignment",
                            "label": "Alignment",
                            "value": "alignment",
                            "options": [
                                "left",
                                "center",
                                "right"
                            ],
                            "validation": null
                        }
                        ]
                    }
                };
                break;
                case 'image':
                item = {
                    "sectionHeader": "Image",
                    "component": "layer-image",
                    "settings": {
                        "component": "layer-settings",
                        "values": {
                            "height": 500,
                            "url": "http://localhost:4200/img/sample.jpg",
                            "bgColor": "#FFFFFF",
                            "color": "#333333"
                        },
                        "form": [
                        {
                            "type": "image",
                            "label": "Image link",
                            "value": "url",
                            "validation": null
                        },
                        {
                            "type": "increment",
                            "label": "Section height",
                            "value": "height",
                            "incrementSize": 20,
                            "validation": null
                        }
                        ]
                    }
                };
                break;
                case 'navigation':
                item = {
                    "sectionHeader": "Navigation",
                    "component": "pages-menu",
                    "settings": {
                        "component": "layer-settings",
                        "values": {
                            "fontSize": 16,
                            "bgColor": "#FFFFFF",
                            "color": "#333333",
                            "alignment": "center",
                            "stickToTop":false,
                        },
                        "form": [
                        {
                            "type": "increment",
                            "label": "Font size",
                            "value": "fontSize",
                            "incrementSize": 1,
                            "validation": null
                        },
                        {
                            "type": "alignment",
                            "label": "Alignment",
                            "value": "alignment",
                            "options": [
                                "left",
                                "center",
                                "right"
                            ],
                            "validation": null
                        },
                        {
                         "type": "settings",
                         "items": [
                         {
                            "type": "checkbox",
                            "label": "Stick to top of page on scroll",
                            "value": "stickToTop",
                            "validation": null
                        }
                        ]
                    }
                    ]
                }
            };
            break;
            case 'title':
            item = {
                "sectionHeader": "Title",
                "component": "layer-title",
                "settings": {
                    "values": {
                        "backgroundImage": "http://localhost:4200/img/bg.png",
                        "backgroundCover": true,
                        "showNavigation": true,
                        "showTitle": true,
                        "showLead": true,
                        "showInNavigation": false,
                        "h1Size": 30,
                        "bgColor": "#333333",
                        "color": "#EEEEEE",
                        "alignment": "right",
                        "lead": "Some lead text"
                    },
                    "form": [
                    {
                        "type": "image",
                        "label": "Background image",
                        "value": "backgroundImage",
                        "validation": null
                    },
                    {
                        "type": "increment",
                        "label": "Title size",
                        "value": "h1Size",
                        "size": 20,
                        "incrementSize": 4,
                        "validation": null
                    },
                    {
                        "type": "alignment",
                        "label": "Alignment",
                        "value": "alignment",
                        "options": [
                            "left",
                            "center",
                            "right"
                        ],
                        "validation": null
                    },
                    {
                        "type": "settings",
                        "items": [
                        {
                            "type": "checkbox",
                            "label": "Show navigation",
                            "value": "showNavigation",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Fit image to section size",
                            "value": "backgroundCover",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show title",
                            "value": "showTitle",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show lead text",
                            "value": "showLead",
                            "validation": null
                        }
                        ]
                    }
                    ]
                }
            };
            break;
            case 'info':
            item =  {
                "sectionHeader": "Info",
                "component": "layer-info",
                "settings": {
                    "values": {
                        "sectionTitle": "Info Title",
                        "showInNavigation": true,
                        "showDescription": true,
                        "showContributors": true,
                        "showBibliographicContributors": false,
                        "showAffiliatedInstitutions": true,
                        "bgColor": "#FFFFFF",
                        "alignment": "center",
                        "color": "#333333"
                    },
                    "form": [
                    {
                        "type": "settings",
                        "items": [
                        {
                            "type": "checkbox",
                            "label": "Show in navigation",
                            "value": "showInNavigation",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show description",
                            "value": "showDescription",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show contributors",
                            "value": "showContributors",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show only bibliographic contributors",
                            "value": "showBibliographicContributors",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show affiliated institutions",
                            "value": "showAffiliatedInstitutions",
                            "validation": null
                        }
                        ]
                    },
                    {
                        "type": "alignment",
                        "label": "Alignment",
                        "value": "alignment",
                        "options": [
                            "left",
                            "center",
                            "right"
                        ],
                        "validation": null
                    }
                    ]
                }
            };
            break;
            case 'imangeAndText':
            item = {
                "sectionHeader": "Image-Text",
                "component": "layer-image-text",
                "settings": {
                    "values": {
                        "sectionTitle": "Image and Text",
                        "showNavigation": true,
                        "showInNavigation": true,
                        "bgColor": "#ffffff",
                        "color": "#333333",
                        "alignment": "right",
                        "sectionDescription": "Mauris imperdiet ligula a mauris porttitor ultricies. Praesent ut fringilla orci. Proin feugiat auctor augue non rutrum. Sed ac metus in augue dignissim malesuada non et sem. Pellentesque ut metus odio. Integer fringilla nulla id leo consequat, a sollicitudin sapien fringilla.",
                        "image": "http://localhost:4200/img/img.jpg"
                    },
                    "form": [
                    {
                        "type": "image",
                        "label": "choose your image",
                        "value": "image",
                        "validation": null
                    },
                    {
                        "type": "alignment",
                        "label": "Alignment",
                        "value": "alignment",
                        "options": [
                            "left",
                            "center",
                            "right"
                        ],
                        "validation": null
                    },
                    {
                        "type": "settings",
                        "items": [
                        {
                            "type": "checkbox",
                            "label": "show in navigation",
                            "value": "showInNavigation",
                            "validation": null
                        }
                        ]
                    }
                    ]
                }
            };
            break;
        }
        let index = this.get('index')+1;
        this.get('layers.content').insertAt(index,item);
        this.set('isOpen', false);

    },
    toggleProperty(prop){
        this.toggleProperty(prop);
    }
}
});
<commit_msg>add ability to add image to advanced layer<commit_after>import Ember from 'ember';

export default Ember.Component.extend({
    isOpen: null,
    actions: {
        addLayer (type) {
            let item;
            switch(type) {
                case 'wiki' :
                item = {
                    "sectionHeader": "Wiki example",
                    "component": "layer-wiki",
                    "settings": {
                        "component": "layer-settings",
                        "wikiId": "",
                        "values": {
                            "sectionTitle": "Wiki example",
                            "showInNavigation": true,
                            "addShowMore": false,
                            "bgColor": "#FFFFFF",
                            "color": "#333333",
                            "alignment": "center"
                        },
                        "form": [
                        {
                            "type": "settings",
                            "items": [
                            {
                                "type": "checkbox",
                                "label": "Show in navigation",
                                "value": "showInNavigation",
                                "validation": null
                            },
                            {
                                "type": "checkbox",
                                "label": "Add show more",
                                "value": "addShowMore",
                                "validation": null
                            }
                            ]
                        },
                        {
                            "type": "alignment",
                            "label": "Alignment",
                            "value": "alignment",
                            "options": [
                                "left",
                                "center",
                                "right"
                            ],
                            "validation": null
                        }
                        ]
                    }
                };
                break;
                case 'file':
                item = {
                    "sectionHeader": "Download",
                    "component": "layer-file",
                    "settings": {
                        "component": "layer-settings",
                        "values": {
                            "sectionTitle": "Download this file",
                            "sectionDescription": "",
                            "showFileviewer": true,
                            "downloadLink": "",
                            "showInNavigation": true,
                            "bgColor": "#FFFFFF",
                            "alignment": "center",
                            "color": "#333333"
                        },
                        "form": [
                        {
                            "type": "settings",
                            "items": [
                            {
                                "type": "checkbox",
                                "label": "Show in navigation",
                                "value": "showInNavigation",
                                "validation": null
                            },
                            {
                                "type": "checkbox",
                                "label": "Show file viewer",
                                "value": "showFileviewer",
                                "validation": null
                            }
                            ]
                        },
                        {
                            "type": "alignment",
                            "label": "Alignment",
                            "value": "alignment",
                            "options": [
                                "left",
                                "center",
                                "right"
                            ],
                            "validation": null
                        }
                        ]
                    }
                };
                break;
                case 'link':
                item = {
                    "sectionHeader": "Link",
                    "component": "layer-link",
                    "settings": {
                        "component": "layer-settings",
                        "values": {
                            "sectionTitle": "Link Title",
                            "showInNavigation": true,
                            "sectionDescription": "this link goes to a place",
                            "sectionLink": "www.example.com",
                            "bgColor": "#FFFFFF",
                            "alignment": "center",
                            "color": "#333333"
                        },
                        "form": [
                        {
                            "type": "settings",
                            "items": [
                            {
                                "type": "checkbox",
                                "label": "Show in navigation",
                                "value": "showInNavigation",
                                "validation": null
                            },
                            {
                                "type": "text",
                                "label": "Link address",
                                "value": "sectionLink",
                                "validation": null
                            }
                            ]
                        },
                        {
                            "type": "alignment",
                            "label": "Alignment",
                            "value": "alignment",
                            "options": [
                                "left",
                                "center",
                                "right"
                            ],
                            "validation": null
                        }
                        ]
                    }
                };
                break;
                case 'advanced':
                item = {
                    "sectionHeader": "Advanced",
                    "component": "layer-advanced",
                    "content": "
Mauris imperdie Praesent ut fringilla orci. Proin feugiat auctor augue non rutrum. Sed ac metus in augue dignissim malesuada non et sem. Pellentesque ut metus odio. Integer fringilla nulla id leo consequat, a sollicitudin sapien fringilla. Fusce vestibulum malesuada nisl. Fusce augue leo, tempus eget matssstis vel, imperdiet at nulla
",
                    "settings": {
                        "component": "layer-settings",
                        "values": {
                            "sectionTitle": "Advanced",
                            "backgroundImage": "http://localhost:4200/img/bg.png",
                            "showInNavigation": true,
                            "bgColor": "#FFFFFF",
                            "alignment": "center",
                            "color": "#333333"
                        },
                        "form": [
                        {
                            "type": "settings",
                            "items": [
                            {
                                "type": "checkbox",
                                "label": "Show in navigation",
                                "value": "showInNavigation",
                                "validation": null
                            },
                            {
                                "type": "checkbox",
                                "label": "Fit image to section size",
                                "value": "backgroundCover",
                                "validation": null
                            },
                            ]
                        },
                        {
                            "type": "image",
                            "label": "Background image",
                            "value": "backgroundImage",
                            "validation": null
                        },
                        {
                            "type": "alignment",
                            "label": "Alignment",
                            "value": "alignment",
                            "options": [
                                "left",
                                "center",
                                "right"
                            ],
                            "validation": null
                        }
                        ]
                    }
                };
                break;
                case 'image':
                item = {
                    "sectionHeader": "Image",
                    "component": "layer-image",
                    "settings": {
                        "component": "layer-settings",
                        "values": {
                            "height": 500,
                            "url": "http://localhost:4200/img/sample.jpg",
                            "bgColor": "#FFFFFF",
                            "color": "#333333"
                        },
                        "form": [
                        {
                            "type": "image",
                            "label": "Image link",
                            "value": "url",
                            "validation": null
                        },
                        {
                            "type": "increment",
                            "label": "Section height",
                            "value": "height",
                            "incrementSize": 20,
                            "validation": null
                        }
                        ]
                    }
                };
                break;
                case 'navigation':
                item = {
                    "sectionHeader": "Navigation",
                    "component": "pages-menu",
                    "settings": {
                        "component": "layer-settings",
                        "values": {
                            "fontSize": 16,
                            "bgColor": "#FFFFFF",
                            "color": "#333333",
                            "alignment": "center",
                            "stickToTop":false,
                        },
                        "form": [
                        {
                            "type": "increment",
                            "label": "Font size",
                            "value": "fontSize",
                            "incrementSize": 1,
                            "validation": null
                        },
                        {
                            "type": "alignment",
                            "label": "Alignment",
                            "value": "alignment",
                            "options": [
                                "left",
                                "center",
                                "right"
                            ],
                            "validation": null
                        },
                        {
                         "type": "settings",
                         "items": [
                         {
                            "type": "checkbox",
                            "label": "Stick to top of page on scroll",
                            "value": "stickToTop",
                            "validation": null
                        }
                        ]
                    }
                    ]
                }
            };
            break;
            case 'title':
            item = {
                "sectionHeader": "Title",
                "component": "layer-title",
                "settings": {
                    "values": {
                        "backgroundImage": "http://localhost:4200/img/bg.png",
                        "backgroundCover": true,
                        "showNavigation": true,
                        "showTitle": true,
                        "showLead": true,
                        "showInNavigation": false,
                        "h1Size": 30,
                        "bgColor": "#333333",
                        "color": "#EEEEEE",
                        "alignment": "right",
                        "lead": "Some lead text"
                    },
                    "form": [
                    {
                        "type": "image",
                        "label": "Background image",
                        "value": "backgroundImage",
                        "validation": null
                    },
                    {
                        "type": "increment",
                        "label": "Title size",
                        "value": "h1Size",
                        "size": 20,
                        "incrementSize": 4,
                        "validation": null
                    },
                    {
                        "type": "alignment",
                        "label": "Alignment",
                        "value": "alignment",
                        "options": [
                            "left",
                            "center",
                            "right"
                        ],
                        "validation": null
                    },
                    {
                        "type": "settings",
                        "items": [
                        {
                            "type": "checkbox",
                            "label": "Show navigation",
                            "value": "showNavigation",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Fit image to section size",
                            "value": "backgroundCover",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show title",
                            "value": "showTitle",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show lead text",
                            "value": "showLead",
                            "validation": null
                        }
                        ]
                    }
                    ]
                }
            };
            break;
            case 'info':
            item =  {
                "sectionHeader": "Info",
                "component": "layer-info",
                "settings": {
                    "values": {
                        "sectionTitle": "Info Title",
                        "showInNavigation": true,
                        "showDescription": true,
                        "showContributors": true,
                        "showBibliographicContributors": false,
                        "showAffiliatedInstitutions": true,
                        "bgColor": "#FFFFFF",
                        "alignment": "center",
                        "color": "#333333"
                    },
                    "form": [
                    {
                        "type": "settings",
                        "items": [
                        {
                            "type": "checkbox",
                            "label": "Show in navigation",
                            "value": "showInNavigation",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show description",
                            "value": "showDescription",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show contributors",
                            "value": "showContributors",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show only bibliographic contributors",
                            "value": "showBibliographicContributors",
                            "validation": null
                        },
                        {
                            "type": "checkbox",
                            "label": "Show affiliated institutions",
                            "value": "showAffiliatedInstitutions",
                            "validation": null
                        }
                        ]
                    },
                    {
                        "type": "alignment",
                        "label": "Alignment",
                        "value": "alignment",
                        "options": [
                            "left",
                            "center",
                            "right"
                        ],
                        "validation": null
                    }
                    ]
                }
            };
            break;
            case 'imangeAndText':
            item = {
                "sectionHeader": "Image-Text",
                "component": "layer-image-text",
                "settings": {
                    "values": {
                        "sectionTitle": "Image and Text",
                        "showNavigation": true,
                        "showInNavigation": true,
                        "bgColor": "#ffffff",
                        "color": "#333333",
                        "alignment": "right",
                        "sectionDescription": "Mauris imperdiet ligula a mauris porttitor ultricies. Praesent ut fringilla orci. Proin feugiat auctor augue non rutrum. Sed ac metus in augue dignissim malesuada non et sem. Pellentesque ut metus odio. Integer fringilla nulla id leo consequat, a sollicitudin sapien fringilla.",
                        "image": "http://localhost:4200/img/img.jpg"
                    },
                    "form": [
                    {
                        "type": "image",
                        "label": "choose your image",
                        "value": "image",
                        "validation": null
                    },
                    {
                        "type": "alignment",
                        "label": "Alignment",
                        "value": "alignment",
                        "options": [
                            "left",
                            "center",
                            "right"
                        ],
                        "validation": null
                    },
                    {
                        "type": "settings",
                        "items": [
                        {
                            "type": "checkbox",
                            "label": "show in navigation",
                            "value": "showInNavigation",
                            "validation": null
                        }
                        ]
                    }
                    ]
                }
            };
            break;
        }
        let index = this.get('index')+1;
        this.get('layers.content').insertAt(index,item);
        this.set('isOpen', false);

    },
    toggleProperty(prop){
        this.toggleProperty(prop);
    }
}
});
<|endoftext|>


<commit_before>// Import React
import React from "react";

// Import Spectacle Core tags
import {
  Deck,
  Heading,
  ListItem,
  List,
  Slide,
  Text,
  Appear,
  Image,
  Link
} from "spectacle";

import CodeSlide from "spectacle-code-slide";

// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
// import createTheme from "spectacle/lib/themes/default";

import { theme } from "spectacle-theme-solarized-dark";
// Require CSS
require("normalize.css");
require("spectacle/lib/themes/default/index.css");

const images = {
  npmDownloads: require("../assets/TypescriptNPM-Downloads.png")
};

preloader(images);

/*const theme = createTheme({
  primary: "white",
  secondary: "#1F2022",
  tertiary: "#03A9FC",
  quartenary: "#CECECE"
}, {
  primary: "Montserrat",
  secondary: "Helvetica"
});*/

export default class Presentation extends React.Component {
  render() {
    return (
      <Deck transition={[]} transitionDuration={500} theme={theme}>
        <Slide transition={["zoom"]} bgColor="primary">
          <Heading size={1} fit caps lineHeight={1} textColor="secondary">
            Typescript
          </Heading>
          <Text margin="10px 0 0" textColor="tertiary" size={1} fit bold>
            Javascript that scales
          </Text>
        </Slide>
        <Slide transition={["fade"]} bgColor="tertiary">
          <Heading size={6} textColor="primary" caps>Why Typescript</Heading>
          <List textColor="primary">
            <Appear><ListItem>Superset of Javascript(Commitment to EcmaScript compatibility)</ListItem></Appear>
            <Appear><ListItem>Can Mix JS and TS</ListItem></Appear>
            <Appear><ListItem>Zero runtime cost (ts disappears at runtime)</ListItem></Appear>
            <Appear><ListItem>Great tooling(Intellisense, autocomplete, refactor, errors, etc)</ListItem></Appear>
            <Appear><ListItem>Type inference</ListItem></Appear>
            <Appear><ListItem>Mature ecosystem</ListItem></Appear>
            <Appear><ListItem>Kept up to date(bi-monthly releases)</ListItem></Appear>
          </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="primary" textColor="tertiary">
          <Heading size={6} textColor="secondary" caps>Typescript - Usage(NPM downloads)</Heading>
          <Image src={images.npmDownloads} />
          <Link href="https://npm-stat.com/charts.html?package=babel&package=typescript&package=flow-bin&from=2016-10-01&to=2017-03-31" target="blank" >Source</Link>
        </Slide>
        <Slide transition={["fade"]} bgColor="tertiary">
          <Heading size={6} textColor="primary" caps>Projects using Typescript</Heading>
          <List textColor="primary">
            <Appear><ListItem>Angular</ListItem></Appear>
            <Appear><ListItem>VSCode</ListItem></Appear>
            <Appear><ListItem>Slack</ListItem></Appear>
            <Appear><ListItem>Glimmer(Ember rendering engine)</ListItem></Appear>
            <Appear><ListItem>Apollo GraphQL</ListItem></Appear>
            <Appear><ListItem>RxJS</ListItem></Appear>
            <Appear><ListItem>CycleJs</ListItem></Appear>
          </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="tertiary">
            <Heading size={6} textColor="primary" caps>How does this help me?</Heading>
            <Text textAlign="Center" lineHeight={5} textSize={52} bold caps>Demo</Text>
        </Slide>
        <CodeSlide
          transition={[]}
          lang="bash"
          code={require("raw-loader!../code/createTypescript.example")}
          ranges={[
              { loc: [0, 8], title: "Easy Way - Greenfield" },
              { loc: [0, 1], title: "Install CRA" },
              { loc: [2, 3], title: "Run CRA with Scripts", note: "Uses template/script to create project" },
              { loc: [3, 5], title: "Start the project" }
          ]}
        />
        <Slide transition={["fade"]} bgColor="tertiary">
          <Heading size={6} textColor="primary" caps>Existing project: Init</Heading>
          <List textColor="primary">
            <Appear><ListItem textSize={24}>Use CRA/Typescript as reference(eject)</ListItem></Appear>
            <Appear><ListItem textSize={24}>Yarn add --dev typescript ts-loader tslint tslint-loader tslint-react @types/jest @types/node @types/react @types/react-dom</ListItem></Appear>
          </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="primary" textColor="tertiary">
          <Heading size={6} textColor="secondary" caps>Existing Project: Webpack</Heading>
          <List>
            <Appear><ListItem>Add entry Resolve>Extensions</ListItem></Appear>
            <Appear><ListItem>Add entry for Preloaders>ts-lint</ListItem></Appear>
            <Appear><ListItem>Add entry to exlude ts(x) from url loader </ListItem></Appear>
            <Appear><ListItem>Add entry for ts(x)files passing to ts-loader</ListItem></Appear>
          </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="tertiary">
            <Heading size={6} textColor="primary" caps>Existing Project: Jest support</Heading>
            <List>
              <Appear><ListItem textColor="primary">Add support for Jest in project.json</ListItem></Appear>
              <Appear><ListItem textColor="primary">Add TS Transform for Jest</ListItem></Appear>
            </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="primary" textColor="tertiary">
          <Heading size={5} textColor="secondary" caps>Existing Project: Hardest part</Heading>
          <List>
            <Appear><ListItem textColor="tertiary" lineHeight={5} >Rename js files to ts/tsx</ListItem></Appear>
            <Appear><ListItem textColor="tertiary" lineHeight={5} >Fix components to use generic declaration</ListItem></Appear>
          </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="tertiary">
            <Heading size={6} textColor="primary" caps>Existing Project: Webpack and Using Typescript</Heading>
            <Text textAlign="Center" lineHeight={5} textSize={52} bold caps>Demo</Text>
        </Slide>
        <Slide transition={["fade"]} bgColor="primary" textColor="tertiary">
          <Heading size={5} textColor="secondary" caps>Contact Me</Heading>
          <List>
            <ListItem textColor="tertiary" lineHeight={5} >Twitter: @Intellemerc</ListItem>
            <ListItem textColor="tertiary" lineHeight={5} >ReactJs Slack: @Intellemerc</ListItem>
          </List>
        </Slide>
      </Deck>
    );
  }
}
<commit_msg>remove existing app section<commit_after>// Import React
import React from "react";

// Import Spectacle Core tags
import {
  Deck,
  Heading,
  ListItem,
  List,
  Slide,
  Text,
  Appear,
  Image,
  Link
} from "spectacle";

import CodeSlide from "spectacle-code-slide";

// Import image preloader util
import preloader from "spectacle/lib/utils/preloader";

// Import theme
// import createTheme from "spectacle/lib/themes/default";

import { theme } from "spectacle-theme-solarized-dark";
// Require CSS
require("normalize.css");
require("spectacle/lib/themes/default/index.css");

const images = {
  npmDownloads: require("../assets/TypescriptNPM-Downloads.png")
};

preloader(images);

/*const theme = createTheme({
  primary: "white",
  secondary: "#1F2022",
  tertiary: "#03A9FC",
  quartenary: "#CECECE"
}, {
  primary: "Montserrat",
  secondary: "Helvetica"
});*/

export default class Presentation extends React.Component {
  render() {
    return (
      <Deck transition={[]} transitionDuration={500} theme={theme}>
        <Slide transition={["zoom"]} bgColor="primary">
          <Heading size={1} fit caps lineHeight={1} textColor="secondary">
            Typescript
          </Heading>
          <Text margin="10px 0 0" textColor="tertiary" size={1} fit bold>
            Javascript that scales
          </Text>
        </Slide>
        <Slide transition={["fade"]} bgColor="tertiary">
          <Heading size={6} textColor="primary" caps>Why Typescript</Heading>
          <List textColor="primary">
            <Appear><ListItem>Superset of Javascript(Commitment to EcmaScript compatibility)</ListItem></Appear>
            <Appear><ListItem>Can Mix JS and TS</ListItem></Appear>
            <Appear><ListItem>Zero runtime cost (ts disappears at runtime)</ListItem></Appear>
            <Appear><ListItem>Great tooling(Intellisense, autocomplete, refactor, errors, etc)</ListItem></Appear>
            <Appear><ListItem>Type inference</ListItem></Appear>
            <Appear><ListItem>Mature ecosystem</ListItem></Appear>
            <Appear><ListItem>Kept up to date(bi-monthly releases)</ListItem></Appear>
          </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="primary" textColor="tertiary">
          <Heading size={6} textColor="secondary" caps>Typescript - Usage(NPM downloads)</Heading>
          <Image src={images.npmDownloads} />
          <Link href="https://npm-stat.com/charts.html?package=babel&package=typescript&package=flow-bin&from=2016-10-01&to=2017-03-31" target="blank" >Source</Link>
        </Slide>
        <Slide transition={["fade"]} bgColor="tertiary">
          <Heading size={6} textColor="primary" caps>Projects using Typescript</Heading>
          <List textColor="primary">
            <Appear><ListItem>Angular</ListItem></Appear>
            <Appear><ListItem>VSCode</ListItem></Appear>
            <Appear><ListItem>Slack</ListItem></Appear>
            <Appear><ListItem>Glimmer(Ember rendering engine)</ListItem></Appear>
            <Appear><ListItem>Apollo GraphQL</ListItem></Appear>
            <Appear><ListItem>RxJS</ListItem></Appear>
            <Appear><ListItem>CycleJs</ListItem></Appear>
          </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="tertiary">
            <Heading size={6} textColor="primary" caps>How does this help me?</Heading>
            <Text textAlign="Center" lineHeight={5} textSize={52} bold caps>Demo</Text>
        </Slide>
        <CodeSlide
          transition={[]}
          lang="bash"
          code={require("raw-loader!../code/createTypescript.example")}
          ranges={[
              { loc: [0, 8], title: "Easy Way - Greenfield" },
              { loc: [0, 1], title: "Install CRA" },
              { loc: [2, 3], title: "Run CRA with Scripts", note: "Uses template/script to create project" },
              { loc: [3, 5], title: "Start the project" }
          ]}
        />
        {/*<Slide transition={["fade"]} bgColor="tertiary">
          <Heading size={6} textColor="primary" caps>Existing project: Init</Heading>
          <List textColor="primary">
            <Appear><ListItem textSize={24}>Use CRA/Typescript as reference(eject)</ListItem></Appear>
            <Appear><ListItem textSize={24}>Yarn add --dev typescript ts-loader tslint tslint-loader tslint-react @types/jest @types/node @types/react @types/react-dom</ListItem></Appear>
          </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="primary" textColor="tertiary">
          <Heading size={6} textColor="secondary" caps>Existing Project: Webpack</Heading>
          <List>
            <Appear><ListItem>Add entry Resolve>Extensions</ListItem></Appear>
            <Appear><ListItem>Add entry for Preloaders>ts-lint</ListItem></Appear>
            <Appear><ListItem>Add entry to exlude ts(x) from url loader </ListItem></Appear>
            <Appear><ListItem>Add entry for ts(x)files passing to ts-loader</ListItem></Appear>
          </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="tertiary">
            <Heading size={6} textColor="primary" caps>Existing Project: Jest support</Heading>
            <List>
              <Appear><ListItem textColor="primary">Add support for Jest in project.json</ListItem></Appear>
              <Appear><ListItem textColor="primary">Add TS Transform for Jest</ListItem></Appear>
            </List>
        </Slide>
        <Slide transition={["fade"]} bgColor="primary" textColor="tertiary">
          <Heading size={5} textColor="secondary" caps>Existing Project: Hardest part</Heading>
          <List>
            <Appear><ListItem textColor="tertiary" lineHeight={5} >Rename js files to ts/tsx</ListItem></Appear>
            <Appear><ListItem textColor="tertiary" lineHeight={5} >Fix components to use generic declaration</ListItem></Appear>
          </List>
        </Slide>*/}
        <Slide transition={["fade"]} bgColor="tertiary">
            <Heading size={6} textColor="primary" caps>Using Typescript</Heading>
            <Text textAlign="Center" lineHeight={5} textSize={52} bold caps>Demo</Text>
        </Slide>
        <Slide transition={["fade"]} bgColor="primary" textColor="tertiary">
          <Heading size={5} textColor="secondary" caps>Contact Me</Heading>
          <List>
            <ListItem textColor="tertiary" lineHeight={5} >Twitter: @Intellemerc</ListItem>
            <ListItem textColor="tertiary" lineHeight={5} >ReactJs Slack: @Intellemerc</ListItem>
          </List>
        </Slide>
      </Deck>
    );
  }
}
<|endoftext|>


<commit_before>'use strict';

var uuid = require('uuid'),
  Q = require('q'),
  _ = require('lodash'),
  path = require('path'),
  config = require(path.join(__dirname, '../config')),
  puppeteer = require('puppeteer'),
  platforms = config.platforms;

function PWABuilder(pwabuilderLib) {
  this.lib = pwabuilderLib;
  var platformsConfig = path.resolve(__dirname, '..', '..', 'platforms.json');
  this.lib.platformTools.configurePlatforms(platformsConfig);
}

const expirationTime = 604800;

PWABuilder.prototype.createManifestFromUrl = function (url, client) {
  var self = this;

  if (url.indexOf('http') === -1) {
    url = 'http://' + url;
  }

  return Q.Promise(function (resolve, reject) {

    var callback = function (err, manifestInfo) {
      if (err) {
        return reject(err);
      }

      var manifest = _.assign(manifestInfo, { id: uuid.v4().slice(0, 8) });

      self.validateManifest(manifest)
        .then(function (manifest) {
          client.set(manifest.id, JSON.stringify(manifest), 'EX', expirationTime);
          return resolve(manifest);
        })
        .fail(reject);
    }

    var resolveStartUrl = function (err, manifestInfo) {
      if (err) {
        return callback(err, manifestInfo);
      }

      if (manifestInfo.format === self.lib.constants.BASE_MANIFEST_FORMAT) {
        return self.lib.manifestTools.validateAndNormalizeStartUrl(url, manifestInfo, callback);
      } else {
        return callback(undefined, manifestInfo);
      }
    }
    self.lib.manifestTools.getManifestFromSite(url, undefined, resolveStartUrl);
  });
};

PWABuilder.prototype.createManifestFromFile = function (file, client) {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    self.lib.manifestTools.getManifestFromFile(file.path, function (err, manifestInfo) {
      if (err) { return reject(err); }

      var manifest = _.assign(manifestInfo, { id: uuid.v4().slice(0, 8) });
      self.validateManifest(manifest)
        .then(function (manifest) {
          client.set(manifest.id, JSON.stringify(manifest), 'EX', expirationTime);
          return resolve(manifest);
        })
        .fail(reject);
    });
  });
};

PWABuilder.prototype.validateManifest = function (manifest) {
  var self = this;

  var originalIcons = manifest.content.icons;
  manifest = self.cleanGeneratedIcons(manifest);

  // handle related apps issue
  // this should always be an array
  if (manifest.content.related_applications && typeof manifest.content.related_applications === 'string') {
    manifest.content.related_applications = [];
  }

  // handle prefer related applications
  // should always be a boolean
  if (manifest.content.prefer_related_applications && typeof manifest.content.prefer_related_applications === 'string') {
    manifest.content.prefer_related_applications = JSON.parse(manifest.content.prefer_related_applications);
  }

  return Q.Promise(function (resolve, reject) {
     self.lib.manifestTools.validateManifest(manifest, platforms, function (err, results) {
      if (err) { return reject(err); }

      var errors = _.filter(results, { level: 'error' }),
        suggestions = _.filter(results, { level: 'suggestion' }),
        warnings = _.filter(results, { level: 'warning' });

      self.assignValidationErrors(errors, manifest);
      self.assignSuggestions(suggestions, manifest);
      self.assignWarnings(warnings, manifest);

      // restore original icons
      manifest.content.icons = originalIcons;

      return resolve(manifest);
    });
  });
};

PWABuilder.prototype.updateManifest = function (client, manifestId, updates, assets) {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    client.get(manifestId, function (err, reply) {
      if (err) return reject(err);
      if (!reply) return reject(new Error('Manifest not found'));

      var manifest = JSON.parse(reply);
      manifest.content = updates;

      if (assets) {
        manifest.assets = assets;
      } else {
        if ((updates.icons || []).filter(function (icon) { return icon.generated; }).length === 0) {
          delete manifest.assets;
        }
      }

      return self.validateManifest(manifest)
        .then(function (manifest) {
          client.set(manifest.id, JSON.stringify(manifest), 'EX', expirationTime);

          resolve(manifest);
        });
    });
  });
};

PWABuilder.prototype.normalize = function (manifest) {
  var self = this;

  return Q.Promise(function (resolve, reject) {

    // check for orientation and set to portrait as default
    if (manifest.content.orientation) {
      manifest.content.orientation = manifest.content.orientation.toLowerCase();
    }
    else {
      manifest.content.orientation = 'portrait';
    }

    if (manifest.content.short_name && manifest.content.short_name.includes('-')) {
      manifest.content.short_name = manifest.content.short_name.replace(/-/g, ' ');
    }
    else if (manifest.content.name) {
      manifest.content.short_name === manifest.content.name;
    }
    else if(manifest.default.short_name) {
      manifest.content.short_name = manifest.default.short_name;
    }

    if (manifest.content.name && manifest.content.name.includes('-')) {
      manifest.content.name = manifest.content.name.replace(/-/g, ' ');
    }

    console.log('Validating start url...', manifest);
    self.lib.manifestTools.validateAndNormalizeStartUrl(manifest.content.start_url, manifest, function (err, normManifest) {
      if (err) {
        console.log('Normalizing Error', err);
        return reject(err);
      }

      manifest = _.assign(manifest, normManifest);

      resolve(manifest);
    });
  });
};

PWABuilder.prototype.cleanGeneratedIcons = function (manifest) {
  var self = this;

  // remove properties in the manifest to track generated icons
  manifest.content.icons = (manifest.content.icons || []).map(function (icon) {
    return _.omit(icon, 'generated', 'fileName');
  });

  return manifest;
};

PWABuilder.prototype.createProject = function (manifest, outputDir, platforms, href) {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    var cleanManifest = _.omit(manifest, 'id');
    cleanManifest = _.assign(cleanManifest, { generatedFrom: 'Website Wizard' });
    console.log('Building the project...', cleanManifest, outputDir, platforms);

    try {
      if (!manifest.assets) {
        manifest.assets = [];
      }
      manifest.assets.map(function (asset) {
        asset.data = new Buffer(asset.data, 'hex');
      });

      var options = {
        'crosswalk': false,
        'build': false,
        'assets': manifest.assets
      };

      self.lib.projectBuilder.createApps(cleanManifest, outputDir, platforms, options, href, function (err, projectDir) {

        if (err) {
          console.log('Create Projects Errors!!!', err);
          return reject(err);
        }

        return resolve(projectDir);
      });
    } catch (e) {
      return reject(e);
    }
  });
};

PWABuilder.prototype.packageProject = function (platforms, outputDir, options) {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    console.log('Packaging the project...', outputDir, platforms);
    try {

      self.lib.projectBuilder.packageApps(platforms, outputDir, options, function (err, packagePaths) {

        if (err) {
          console.log('Package Project Errors!!!', err);
          return reject(err);
        }

        return resolve(packagePaths);
      });
    } catch (e) {
      return reject(e);
    }
  });
};

PWABuilder.prototype.getServiceWorkers = function (id) {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    self.lib.serviceWorkerTools.getAssetsFolders(id, function (err, resultURL) {
      return resolve(resultURL);
    });
  });
};

PWABuilder.prototype.getServiceWorkersDescription = function () {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    self.lib.serviceWorkerTools.getServiceWorkersDescription(function (err, resultURL) {
      return resolve(resultURL);
    });
  });
};

PWABuilder.prototype.assignValidationErrors = function (errors, manifest) {
  var data = { errors: [] };

  _.each(errors, function (e) {
    if (_.some(data.errors, 'member', e.member)) {
      var error = _.find(data.errors, 'member', e.member);
      error.issues = error.issues || [];
      error.issues.push({ description: e.description, platform: e.platform, code: e.code });
    } else {
      data.errors.push({
        member: e.member,
        issues: [{
          description: e.description,
          platform: e.platform,
          code: e.code
        }]
      });
    }
  });

  manifest = _.assign(manifest, data);
};

PWABuilder.prototype.assignSuggestions = function (suggestions, manifest) {
  var data = { suggestions: [] };

  _.each(suggestions, function (s) {
    if (_.some(data.suggestions, 'member', s.member)) {
      var suggestion = _.find(data.suggestions, 'member', s.member);
      suggestion.issues = suggestion.issues || [];
      suggestion.issues.push({ description: s.description, platform: s.platform, code: s.code });
    } else {
      data.suggestions.push({
        member: s.member,
        issues: [{
          description: s.description,
          platform: s.platform,
          code: s.code
        }]
      });
    }
  });

  manifest = _.assign(manifest, data);
};

PWABuilder.prototype.assignWarnings = function (warnings, manifest) {
  var data = { warnings: [] };

  _.each(warnings, function (w) {
    if (_.some(data.warnings, 'member', w.member)) {
      var warning = _.find(data.warnings, 'member', w.member);
      warning.issues = warning.issues || [];
      warning.issues.push({ description: w.description, platform: w.platform, code: w.code });
    } else {
      data.warnings.push({
        member: w.member,
        issues: [{
          description: w.description,
          platform: w.platform,
          code: w.code
        }]
      });
    }
  });

  manifest = _.assign(manifest, data);
};

PWABuilder.prototype.generateImagesForManifest = function (image, manifestInfo, client) {
  var self = this;

  var options = {
    generationSvcUrl: config.images.generationSvcUrl
  };

  return Q.Promise(function (resolve, reject) {
    self.lib.manifestTools.generateImagesForManifest(image, manifestInfo.content, options, function (err, resultManifestInfo) {
      if (err) {
        return reject(err);
      } else {
        return resolve(resultManifestInfo);
      }
    });
  });
}

PWABuilder.prototype.getServiceWorkerFromURL = function (url) {
  return Q.Promise(async function (resolve, reject) {
    const browser = await puppeteer.launch({ headless: true, args: ["--no-sandbox"] });
    const page = await browser.newPage();

    // empty object that we fill with data below
    let swInfo = {};

    await page.setRequestInterception(true);

    let whiteList = ['document', 'plain', 'script', 'javascript']
    page.on('request', (req) => {
      const type = req.resourceType();
      if (whiteList.some(el => type.indexOf(el) >= 0)) {
        req.continue();
      } else {
        req.abort();
      }
    })

    await page.goto(url, { waitUntil: ['domcontentloaded'] });

    try {
      // Check to see if there is a service worker
      let serviceWorkerHandle = await page.waitForFunction(() => {
        return navigator.serviceWorker.ready.then((res) => res.active.scriptURL);
      }, { timeout: config.serviceWorkerChecker.timeout });

      swInfo['hasSW'] = serviceWorkerHandle && await serviceWorkerHandle.jsonValue();

      // try to grab service worker scope
      const serviceWorkerScope = await page.evaluate(() => {
        return navigator.serviceWorker.getRegistration().then((res) => res.scope);
      }, { timeout: config.serviceWorkerChecker.timeout });

      swInfo['scope'] = serviceWorkerScope;

      // checking push reg
      const pushReg = await page.evaluate(() => {
        return navigator.serviceWorker.getRegistration().then((reg) => {
          return reg.pushManager.getSubscription().then((sub) => sub);
        });
      }, { timeout: config.serviceWorkerChecker.timeout });

      swInfo['pushReg'] = pushReg;

      // Checking cache
      // Capture requests during 2nd load.
      const allRequests = new Map();
      page.on('request', req => {
        allRequests.set(req.url(), req);
      });

      // Reload page to pick up any runtime caching done by the service worker.
      await page.reload({ waitUntil: ['domcontentloaded'] });

      const swRequests = Array.from(allRequests.values());

      let requestChecks = [];
      swRequests.forEach((req) => {
        const fromSW = req.response() != null ? req.response().fromServiceWorker() : null;
        const requestURL = req.response() != null ? req.response().url() : null;

        requestChecks.push({
          fromSW,
          requestURL
        });
      });

      swInfo['cache'] = requestChecks;

      return resolve(swInfo);
    } catch (error) {
      console.log('timing out', error);
      if (error.name && error.name.indexOf("TimeoutError") > -1) {
        return resolve(false);
      }
      return reject(error);
    } finally {
      await page.close();
      await browser.close();
    }
  })
}

exports.create = function (pwabuilderLib) {
  return new PWABuilder(pwabuilderLib);
};
<commit_msg>load serviceWorkerHandler and check fi push event has been added<commit_after>'use strict';

var uuid = require('uuid'),
  Q = require('q'),
  _ = require('lodash'),
  path = require('path'),
  config = require(path.join(__dirname, '../config')),
  puppeteer = require('puppeteer'),
  platforms = config.platforms;

function PWABuilder(pwabuilderLib) {
  this.lib = pwabuilderLib;
  var platformsConfig = path.resolve(__dirname, '..', '..', 'platforms.json');
  this.lib.platformTools.configurePlatforms(platformsConfig);
}

const expirationTime = 604800;

PWABuilder.prototype.createManifestFromUrl = function (url, client) {
  var self = this;

  if (url.indexOf('http') === -1) {
    url = 'http://' + url;
  }

  return Q.Promise(function (resolve, reject) {

    var callback = function (err, manifestInfo) {
      if (err) {
        return reject(err);
      }

      var manifest = _.assign(manifestInfo, { id: uuid.v4().slice(0, 8) });

      self.validateManifest(manifest)
        .then(function (manifest) {
          client.set(manifest.id, JSON.stringify(manifest), 'EX', expirationTime);
          return resolve(manifest);
        })
        .fail(reject);
    }

    var resolveStartUrl = function (err, manifestInfo) {
      if (err) {
        return callback(err, manifestInfo);
      }

      if (manifestInfo.format === self.lib.constants.BASE_MANIFEST_FORMAT) {
        return self.lib.manifestTools.validateAndNormalizeStartUrl(url, manifestInfo, callback);
      } else {
        return callback(undefined, manifestInfo);
      }
    }
    self.lib.manifestTools.getManifestFromSite(url, undefined, resolveStartUrl);
  });
};

PWABuilder.prototype.createManifestFromFile = function (file, client) {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    self.lib.manifestTools.getManifestFromFile(file.path, function (err, manifestInfo) {
      if (err) { return reject(err); }

      var manifest = _.assign(manifestInfo, { id: uuid.v4().slice(0, 8) });
      self.validateManifest(manifest)
        .then(function (manifest) {
          client.set(manifest.id, JSON.stringify(manifest), 'EX', expirationTime);
          return resolve(manifest);
        })
        .fail(reject);
    });
  });
};

PWABuilder.prototype.validateManifest = function (manifest) {
  var self = this;

  var originalIcons = manifest.content.icons;
  manifest = self.cleanGeneratedIcons(manifest);

  // handle related apps issue
  // this should always be an array
  if (manifest.content.related_applications && typeof manifest.content.related_applications === 'string') {
    manifest.content.related_applications = [];
  }

  // handle prefer related applications
  // should always be a boolean
  if (manifest.content.prefer_related_applications && typeof manifest.content.prefer_related_applications === 'string') {
    manifest.content.prefer_related_applications = JSON.parse(manifest.content.prefer_related_applications);
  }

  return Q.Promise(function (resolve, reject) {
     self.lib.manifestTools.validateManifest(manifest, platforms, function (err, results) {
      if (err) { return reject(err); }

      var errors = _.filter(results, { level: 'error' }),
        suggestions = _.filter(results, { level: 'suggestion' }),
        warnings = _.filter(results, { level: 'warning' });

      self.assignValidationErrors(errors, manifest);
      self.assignSuggestions(suggestions, manifest);
      self.assignWarnings(warnings, manifest);

      // restore original icons
      manifest.content.icons = originalIcons;

      return resolve(manifest);
    });
  });
};

PWABuilder.prototype.updateManifest = function (client, manifestId, updates, assets) {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    client.get(manifestId, function (err, reply) {
      if (err) return reject(err);
      if (!reply) return reject(new Error('Manifest not found'));

      var manifest = JSON.parse(reply);
      manifest.content = updates;

      if (assets) {
        manifest.assets = assets;
      } else {
        if ((updates.icons || []).filter(function (icon) { return icon.generated; }).length === 0) {
          delete manifest.assets;
        }
      }

      return self.validateManifest(manifest)
        .then(function (manifest) {
          client.set(manifest.id, JSON.stringify(manifest), 'EX', expirationTime);

          resolve(manifest);
        });
    });
  });
};

PWABuilder.prototype.normalize = function (manifest) {
  var self = this;

  return Q.Promise(function (resolve, reject) {

    // check for orientation and set to portrait as default
    if (manifest.content.orientation) {
      manifest.content.orientation = manifest.content.orientation.toLowerCase();
    }
    else {
      manifest.content.orientation = 'portrait';
    }

    if (manifest.content.short_name && manifest.content.short_name.includes('-')) {
      manifest.content.short_name = manifest.content.short_name.replace(/-/g, ' ');
    }
    else if (manifest.content.name) {
      manifest.content.short_name === manifest.content.name;
    }
    else if(manifest.default.short_name) {
      manifest.content.short_name = manifest.default.short_name;
    }

    if (manifest.content.name && manifest.content.name.includes('-')) {
      manifest.content.name = manifest.content.name.replace(/-/g, ' ');
    }

    console.log('Validating start url...', manifest);
    self.lib.manifestTools.validateAndNormalizeStartUrl(manifest.content.start_url, manifest, function (err, normManifest) {
      if (err) {
        console.log('Normalizing Error', err);
        return reject(err);
      }

      manifest = _.assign(manifest, normManifest);

      resolve(manifest);
    });
  });
};

PWABuilder.prototype.cleanGeneratedIcons = function (manifest) {
  var self = this;

  // remove properties in the manifest to track generated icons
  manifest.content.icons = (manifest.content.icons || []).map(function (icon) {
    return _.omit(icon, 'generated', 'fileName');
  });

  return manifest;
};

PWABuilder.prototype.createProject = function (manifest, outputDir, platforms, href) {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    var cleanManifest = _.omit(manifest, 'id');
    cleanManifest = _.assign(cleanManifest, { generatedFrom: 'Website Wizard' });
    console.log('Building the project...', cleanManifest, outputDir, platforms);

    try {
      if (!manifest.assets) {
        manifest.assets = [];
      }
      manifest.assets.map(function (asset) {
        asset.data = new Buffer(asset.data, 'hex');
      });

      var options = {
        'crosswalk': false,
        'build': false,
        'assets': manifest.assets
      };

      self.lib.projectBuilder.createApps(cleanManifest, outputDir, platforms, options, href, function (err, projectDir) {

        if (err) {
          console.log('Create Projects Errors!!!', err);
          return reject(err);
        }

        return resolve(projectDir);
      });
    } catch (e) {
      return reject(e);
    }
  });
};

PWABuilder.prototype.packageProject = function (platforms, outputDir, options) {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    console.log('Packaging the project...', outputDir, platforms);
    try {

      self.lib.projectBuilder.packageApps(platforms, outputDir, options, function (err, packagePaths) {

        if (err) {
          console.log('Package Project Errors!!!', err);
          return reject(err);
        }

        return resolve(packagePaths);
      });
    } catch (e) {
      return reject(e);
    }
  });
};

PWABuilder.prototype.getServiceWorkers = function (id) {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    self.lib.serviceWorkerTools.getAssetsFolders(id, function (err, resultURL) {
      return resolve(resultURL);
    });
  });
};

PWABuilder.prototype.getServiceWorkersDescription = function () {
  var self = this;

  return Q.Promise(function (resolve, reject) {
    self.lib.serviceWorkerTools.getServiceWorkersDescription(function (err, resultURL) {
      return resolve(resultURL);
    });
  });
};

PWABuilder.prototype.assignValidationErrors = function (errors, manifest) {
  var data = { errors: [] };

  _.each(errors, function (e) {
    if (_.some(data.errors, 'member', e.member)) {
      var error = _.find(data.errors, 'member', e.member);
      error.issues = error.issues || [];
      error.issues.push({ description: e.description, platform: e.platform, code: e.code });
    } else {
      data.errors.push({
        member: e.member,
        issues: [{
          description: e.description,
          platform: e.platform,
          code: e.code
        }]
      });
    }
  });

  manifest = _.assign(manifest, data);
};

PWABuilder.prototype.assignSuggestions = function (suggestions, manifest) {
  var data = { suggestions: [] };

  _.each(suggestions, function (s) {
    if (_.some(data.suggestions, 'member', s.member)) {
      var suggestion = _.find(data.suggestions, 'member', s.member);
      suggestion.issues = suggestion.issues || [];
      suggestion.issues.push({ description: s.description, platform: s.platform, code: s.code });
    } else {
      data.suggestions.push({
        member: s.member,
        issues: [{
          description: s.description,
          platform: s.platform,
          code: s.code
        }]
      });
    }
  });

  manifest = _.assign(manifest, data);
};

PWABuilder.prototype.assignWarnings = function (warnings, manifest) {
  var data = { warnings: [] };

  _.each(warnings, function (w) {
    if (_.some(data.warnings, 'member', w.member)) {
      var warning = _.find(data.warnings, 'member', w.member);
      warning.issues = warning.issues || [];
      warning.issues.push({ description: w.description, platform: w.platform, code: w.code });
    } else {
      data.warnings.push({
        member: w.member,
        issues: [{
          description: w.description,
          platform: w.platform,
          code: w.code
        }]
      });
    }
  });

  manifest = _.assign(manifest, data);
};

PWABuilder.prototype.generateImagesForManifest = function (image, manifestInfo, client) {
  var self = this;

  var options = {
    generationSvcUrl: config.images.generationSvcUrl
  };

  return Q.Promise(function (resolve, reject) {
    self.lib.manifestTools.generateImagesForManifest(image, manifestInfo.content, options, function (err, resultManifestInfo) {
      if (err) {
        return reject(err);
      } else {
        return resolve(resultManifestInfo);
      }
    });
  });
}

PWABuilder.prototype.getServiceWorkerFromURL = function (url) {
  return Q.Promise(async function (resolve, reject) {
    const browser = await puppeteer.launch({ headless: true, args: ["--no-sandbox"] });
    const page = await browser.newPage();

    // empty object that we fill with data below
    let swInfo = {};

    await page.setRequestInterception(true);

    let whiteList = ['document', 'plain', 'script', 'javascript']
    page.on('request', (req) => {
      const type = req.resourceType();
      if (whiteList.some(el => type.indexOf(el) >= 0)) {
        req.continue();
      } else {
        req.abort();
      }
    })

    await page.goto(url, { waitUntil: ['domcontentloaded'] });

    try {
      // Check to see if there is a service worker
      let serviceWorkerHandle = await page.waitForFunction(() => {
        return navigator.serviceWorker.ready.then((res) => res.active.scriptURL);
      }, { timeout: config.serviceWorkerChecker.timeout });

      swInfo['hasSW'] = serviceWorkerHandle && await serviceWorkerHandle.jsonValue();

      // try to grab service worker scope
      const serviceWorkerScope = await page.evaluate(() => {
        return navigator.serviceWorker.getRegistration().then((res) => res.scope);
      }, { timeout: config.serviceWorkerChecker.timeout });

      swInfo['scope'] = serviceWorkerScope;

      // checking push reg
      var pushReg = await page.evaluate(() => {
        return navigator.serviceWorker.getRegistration().then((reg) => {
          return reg.pushManager.getSubscription().then((sub) => sub);
        });
      }, { timeout: config.serviceWorkerChecker.timeout });

      if(!pushReg && swInfo.hasSW)
      {
        await page.goto(swInfo.hasSW, { waitUntil: ['domcontentloaded'] });
        pushReg = await page.content().then((content) => {
          return content.indexOf('self.addEventListener("push"') >= 0 || content.indexOf("self.addEventListener('push'") >= 0
        });
      }
      swInfo['pushReg'] = pushReg;

      // Checking cache
      // Capture requests during 2nd load.
      const allRequests = new Map();
      page.on('request', req => {
        allRequests.set(req.url(), req);
      });

      // Reload page to pick up any runtime caching done by the service worker.
      await page.reload({ waitUntil: ['domcontentloaded'] });

      const swRequests = Array.from(allRequests.values());

      let requestChecks = [];
      swRequests.forEach((req) => {
        const fromSW = req.response() != null ? req.response().fromServiceWorker() : null;
        const requestURL = req.response() != null ? req.response().url() : null;

        requestChecks.push({
          fromSW,
          requestURL
        });
      });

      swInfo['cache'] = requestChecks;

      return resolve(swInfo);
    } catch (error) {
      console.log('timing out', error);
      if (error.name && error.name.indexOf("TimeoutError") > -1) {
        return resolve(false);
      }
      return reject(error);
    } finally {
      await page.close();
      await browser.close();
    }
  })
}

exports.create = function (pwabuilderLib) {
  return new PWABuilder(pwabuilderLib);
};
<|endoftext|>