├── .gitignore ├── api ├── .gitignore ├── .env.dist ├── package.json ├── src │ ├── handler │ │ └── shotstack │ │ │ ├── handler.js │ │ │ └── lib │ │ │ └── shotstack.js │ ├── shared │ │ └── response.js │ └── app.js ├── serverless.yml └── package-lock.json ├── LICENSE ├── web ├── styles.css ├── index.html └── app.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .tags -------------------------------------------------------------------------------- /api/.gitignore: -------------------------------------------------------------------------------- 1 | # package directories 2 | node_modules 3 | jspm_packages 4 | 5 | # Serverless directories 6 | .serverless 7 | 8 | # Environment variables 9 | .env 10 | -------------------------------------------------------------------------------- /api/.env.dist: -------------------------------------------------------------------------------- 1 | PEXELS_API_KEY=replace_with_your_pexels_key 2 | SHOTSTACK_API_KEY=replace_with_your_shotstack_key 3 | SHOTSTACK_HOST=https://api.shotstack.io/stage/ 4 | SHOTSTACK_ASSETS_URL=https://s3-ap-southeast-2.amazonaws.com/shotstack-assets/ -------------------------------------------------------------------------------- /api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-pexels-shotstack", 3 | "version": "1.0.0", 4 | "description": "Shotstack demo using Pixels Video API and Serverless", 5 | "main": "index.js", 6 | "dependencies": { 7 | "@hapi/joi": "^15.0.3", 8 | "pexels-api-wrapper": "^1.1.1", 9 | "request": "^2.88.0" 10 | }, 11 | "devDependencies": { 12 | "body-parser": "^1.19.0", 13 | "express": "^4.17.1", 14 | "serverless-dotenv-plugin": "^1.2.1" 15 | }, 16 | "scripts": { 17 | "deploy": "sls deploy", 18 | "start": "node src/app.js" 19 | }, 20 | "author": "Shotstack", 21 | "license": "ISC" 22 | } 23 | -------------------------------------------------------------------------------- /api/src/handler/shotstack/handler.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const response = require('../../shared/response'); 4 | const shotstack = require('./lib/shotstack'); 5 | 6 | module.exports.submit = (event, context, callback) => { 7 | const data = JSON.parse(event.body); 8 | 9 | shotstack.submit(data).then((res) => { 10 | console.log('Success'); 11 | callback(null, response.format(201, 'success', 'OK', res)); 12 | }).catch(function(res) { 13 | console.log('Fail: ', res); 14 | callback(null, response.format(400, 'fail', 'Bad Request', res)); 15 | }); 16 | }; 17 | 18 | module.exports.status = (event, context, callback) => { 19 | const id = event.pathParameters.id; 20 | 21 | shotstack.status(id).then((res) => { 22 | console.log('Success'); 23 | callback(null, response.format(201, 'success', 'OK', res)); 24 | }).catch(function(res) { 25 | console.log('Fail: ', res); 26 | callback(null, response.format(400, 'fail', 'Bad Request', res)); 27 | }); 28 | }; 29 | -------------------------------------------------------------------------------- /api/src/shared/response.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Format the response body 5 | * 6 | * @param {String} status 7 | * @param {String} message 8 | * @param {Object} data 9 | * 10 | * @returns {{status: *, message: *, data: *}} 11 | */ 12 | module.exports.getBody = (status, message, data) => { 13 | return { 14 | status: status, 15 | message: message, 16 | data: data 17 | } 18 | }; 19 | 20 | /** 21 | * API Standard response format (JSend - https://labs.omniti.com/labs/jsend) 22 | * 23 | * @param {Number} code 24 | * @param {String} status 25 | * @param {String} message 26 | * @param {Object} data 27 | * @returns {{statusCode: *, headers: {Access-Control-Allow-Origin: string}, body}} 28 | */ 29 | module.exports.format = (code, status, message, data) => { 30 | return { 31 | statusCode: parseInt(code), 32 | headers: { 33 | 'Access-Control-Allow-Origin' : '*' 34 | }, 35 | body: JSON.stringify(this.getBody(status, message, data)) 36 | }; 37 | }; 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Shotstack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /api/serverless.yml: -------------------------------------------------------------------------------- 1 | service: demo-pexels-shotstack 2 | 3 | provider: 4 | name: aws 5 | runtime: nodejs12.x 6 | stage: demo 7 | region: ap-southeast-2 8 | logRetentionInDays: 30 9 | deploymentBucket: 10 | name: shotstack-serverless-deploys-${self:provider.region} 11 | blockPublicAccess: true 12 | environment: 13 | PEXELS_API_KEY: ${env:PEXELS_API_KEY} 14 | 15 | package: 16 | exclude: 17 | - .env 18 | - .env.dist 19 | - package.json 20 | - package-lock.json 21 | - src/app.js 22 | 23 | functions: 24 | shotstack: 25 | handler: src/handler/shotstack/handler.submit 26 | description: Demo - Pexels video search and render 27 | timeout: 15 28 | memorySize: 128 29 | events: 30 | - http: 31 | path: shotstack 32 | method: post 33 | cors: true 34 | status: 35 | handler: src/handler/shotstack/handler.status 36 | description: Demo - Pexels video status check 37 | timeout: 10 38 | memorySize: 128 39 | events: 40 | - http: 41 | path: shotstack/{id} 42 | method: get 43 | cors: true 44 | 45 | plugins: 46 | - serverless-dotenv-plugin -------------------------------------------------------------------------------- /web/styles.css: -------------------------------------------------------------------------------- 1 | .content .jumbotron { 2 | padding-top: 2rem; 3 | padding-bottom: 2rem; 4 | margin-bottom: 0; 5 | } 6 | .display-4 { 7 | font-size: 2.5rem; 8 | } 9 | 10 | .video-container { 11 | padding-bottom: 16px; 12 | } 13 | 14 | #player, #json { 15 | display: none; 16 | } 17 | 18 | #status .fas { 19 | margin-bottom: 8px; 20 | } 21 | 22 | #status small { 23 | margin-top: 10px; 24 | color: #777777; 25 | } 26 | 27 | .progress { 28 | height: 2px; 29 | margin-bottom: 14px; 30 | } 31 | 32 | #json { 33 | margin-top: 16px; 34 | } 35 | .json-key { 36 | color: brown; 37 | } 38 | .json-value { 39 | color: navy; 40 | } 41 | .json-string { 42 | color: olive; 43 | } 44 | 45 | header { 46 | margin-bottom: 2rem; 47 | } 48 | 49 | .btn-primary { 50 | font-weight: bold; 51 | background-color: #25d3d0; 52 | border-color: #25d3d0; 53 | } 54 | 55 | .btn-primary:hover, .btn-primary:active { 56 | background-color: #25d3d0; 57 | border-color: #25d3d0; 58 | } 59 | 60 | a { 61 | color: #25d3d0; 62 | } 63 | a:hover { 64 | color: #25d3d0; 65 | } 66 | 67 | .video-container .jumbotron { 68 | background-color: transparent; 69 | } 70 | 71 | #instructions, #status { 72 | margin-top: 7rem; 73 | } 74 | 75 | #instructions p { 76 | margin: 0; 77 | } 78 | 79 | label { 80 | font-weight: 600; 81 | } 82 | -------------------------------------------------------------------------------- /api/src/app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | 3 | const express = require('express'); 4 | const bodyParser = require('body-parser'); 5 | const path = require('path'); 6 | const shotstack = require('./handler/shotstack/lib/shotstack'); 7 | const responseHandler = require('./shared/response'); 8 | const app = express(); 9 | 10 | app.use(bodyParser.urlencoded({ extended: false })); 11 | app.use(bodyParser.json()); 12 | app.use(express.static(path.join(__dirname + '../../../web'))); 13 | 14 | app.post('/demo/shotstack', async (req, res) => { 15 | try { 16 | let render = await shotstack.submit(req.body); 17 | 18 | res.header("Access-Control-Allow-Origin", "*"); 19 | res.status(201); 20 | res.send(responseHandler.getBody('success', 'OK', render)); 21 | } catch (err) { 22 | res.header("Access-Control-Allow-Origin", "*"); 23 | res.status(400); 24 | res.send(responseHandler.getBody('fail', 'Bad Request', err)); 25 | } 26 | }); 27 | 28 | app.get('/demo/shotstack/:renderId', async (req, res) => { 29 | try { 30 | let render = await shotstack.status(req.params.renderId); 31 | 32 | res.header("Access-Control-Allow-Origin", "*"); 33 | res.status(200); 34 | res.send(responseHandler.getBody('success', 'OK', render)); 35 | } catch (err) { 36 | res.header("Access-Control-Allow-Origin", "*"); 37 | res.status(400); 38 | res.send(responseHandler.getBody('fail', 'Bad Request', err)); 39 | } 40 | }); 41 | 42 | app.listen(3000, () => console.log("Server running...\n\nOpen http://localhost:3000 in your browser\n")); 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shotstack Pexels Demo 2 | 3 | This project demonstrates how to use the Shotstack cloud video editing API to create 4 | a video using an HTML form and video sourced from the Pexels video library. 5 | 6 | An HTML web form allows the user to search the Pexels library via the Pexels API, choose 7 | a soundtrack and add a title. A video is the created by the Shotstack API using the video 8 | clips returned by the Pexels search and the track and title entered by the user. 9 | 10 | View the live demo at: https://shotstack.io/demo/pexels/ 11 | 12 | The demo is built using Node JS and can be used with either Express Framework or deployed 13 | as a serverless projects using AWS Lambda and API Gateway. 14 | 15 | ### Requirements 16 | 17 | - Node 8.10+ 18 | - Pexels API key: https://www.pexels.com/api 19 | - Shotstack API key: https://dashboard.shotstack.io/register 20 | 21 | ### Project Structure 22 | 23 | The project is divided in to a two components: 24 | 25 | #### Backend API 26 | 27 | The backend API with an endpoint which searches the Pexels API, prepares the edit and posts 28 | the data to the Shotstack API. A status endpoint is also available which can be polled to 29 | return the status of the video as it renders. 30 | 31 | The backend API source code is in the _api_ directory. 32 | 33 | #### Frontend Web Form & Player 34 | 35 | The frontend is a simple HTML form that allows the user to enter a search term and basic 36 | options to create a video. The form uses jQuery to submit the data to the backend API and 37 | poll the status of the current render. There is also a video player that is loaded with 38 | the final rendered video when ready. 39 | 40 | The front end API source code is in the _web_ directory. 41 | 42 | ### Installation 43 | 44 | Install node module dependencies: 45 | 46 | ```bash 47 | cd api 48 | npm install 49 | ``` 50 | 51 | ### Configuration 52 | 53 | Copy the .env.dist file and rename it .env. Replace the environment variables below with your 54 | Pexels and Shotstack API key (staging key): 55 | 56 | ```bash 57 | PEXELS_API_KEY=replace_with_your_pexels_key 58 | SHOTSTACK_API_KEY=replace_with_your_shotstack_key 59 | ``` 60 | 61 | ### Run Locally 62 | 63 | To start the API and serve the front end form (from the _api_ directory): 64 | 65 | ```bash 66 | cd api 67 | npm run start 68 | ``` 69 | 70 | The visit [http://localhost:3000](http://localhost:3000) 71 | 72 | 73 | ### Deploy Serverless Application (optional) 74 | 75 | The project has been built as a serverless application using the Serverless Framework 76 | and AWS Lambda. To understand more about the Serverless Framework and how to set 77 | everything up consult the documentation: https://serverless.com/framework/docs/providers/aws/ 78 | 79 | To deploy to AWS Lambda (from the _api_ directory): 80 | 81 | ```bash 82 | cd api 83 | npm run serverless 84 | ``` 85 | 86 | Once the API is deployed set the `var apiEndpoint` variable in **web/app.js** to the returned 87 | API Gateway URL. 88 | 89 | Run the **web/index.html** file locally or use AWS S3 static hosting to serve the web page. 90 | -------------------------------------------------------------------------------- /api/src/handler/shotstack/lib/shotstack.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const request = require('request'); 4 | const Joi = require('@hapi/joi'); 5 | const PexelsAPI = require('pexels-api-wrapper'); 6 | const pexelsClient = new PexelsAPI(process.env.PEXELS_API_KEY); 7 | const shotstackUrl = process.env.SHOTSTACK_HOST; 8 | const shotstackApiKey = process.env.SHOTSTACK_API_KEY; 9 | const shotstackAssetsUrl = process.env.SHOTSTACK_ASSETS_URL; 10 | 11 | module.exports.submit = (data) => { 12 | const schema = { 13 | search: Joi.string().regex(/^[a-zA-Z0-9 ]*$/).min(2).max(30).required(), 14 | title: Joi.string().regex(/^[a-zA-Z0-9 ]*$/).min(2).max(30).required(), 15 | soundtrack: Joi.string().valid(['disco', 'freeflow', 'melodic']).required(), 16 | }; 17 | 18 | const valid = Joi.validate({ 19 | search: data.search, 20 | soundtrack: data.soundtrack, 21 | title: data.title 22 | }, schema); 23 | 24 | return new Promise((resolve, reject) => { 25 | if (valid.error) { 26 | return reject(valid.error); 27 | } 28 | 29 | const minClips = 4; 30 | const maxClips = 8; 31 | const clipLength = 2; 32 | const videoStart = 4; 33 | 34 | pexelsClient.searchVideos(data.search, maxClips, 1).then(function(pexels) { 35 | if (pexels.total_results < minClips) { 36 | throw "There are not enough clips for '" + data.search + "' to create a video"; 37 | } 38 | 39 | let tracks = []; 40 | let videos = []; 41 | 42 | let title = { 43 | asset: { 44 | type: "title", 45 | text: data.title, 46 | style: "minimal", 47 | size: "small" 48 | }, 49 | start: 0, 50 | length: 4, 51 | effect: "zoomIn", 52 | transition: { 53 | in: "fade", 54 | out: "fade" 55 | } 56 | }; 57 | 58 | for (let [index, video] of pexels.videos.entries()) { 59 | let videoFiles = video.video_files; 60 | let hdVideo = videoFiles.find(file => file.height === 720 || file.height === 1920) || videoFiles[0]; 61 | 62 | videos[index] = { 63 | asset: { 64 | type: "video", 65 | src: hdVideo.link, 66 | trim: 1 67 | }, 68 | start: videoStart + (index * clipLength), 69 | length: clipLength 70 | }; 71 | 72 | if (index === 0) { 73 | videos[index].transition = { 74 | in: "fade" 75 | } 76 | } 77 | 78 | if (index === (maxClips - 1)) { 79 | videos[index].transition = { 80 | out: "fade" 81 | } 82 | } 83 | } 84 | 85 | tracks[0] = { 86 | clips: [ 87 | title 88 | ] 89 | }; 90 | 91 | tracks[1] = { 92 | clips: videos 93 | }; 94 | 95 | let timeline = { 96 | soundtrack: { 97 | src: shotstackAssetsUrl + "music/" + data.soundtrack + ".mp3", 98 | effect: "fadeOut" 99 | }, 100 | background: "#000000", 101 | tracks: tracks, 102 | }; 103 | 104 | let output = { 105 | format: "mp4", 106 | resolution: "sd" 107 | }; 108 | 109 | let edit = { 110 | timeline: timeline, 111 | output: output 112 | }; 113 | 114 | request({ 115 | url: shotstackUrl + 'render', 116 | method: 'POST', 117 | headers: { 118 | 'x-api-key': shotstackApiKey 119 | }, 120 | json: true, 121 | body: edit 122 | }, function (error, response, body){ 123 | if (error) { 124 | console.log(error); 125 | return reject(error); 126 | } 127 | 128 | return resolve(body.response); 129 | }); 130 | }).catch(function(error) { 131 | console.log(error); 132 | return reject(error); 133 | }); 134 | }); 135 | }; 136 | 137 | module.exports.status = (id) => { 138 | const schema = { 139 | id: Joi.string().guid({ 140 | version: [ 141 | 'uuidv4', 142 | 'uuidv5' 143 | ] 144 | }) 145 | }; 146 | 147 | const valid = Joi.validate({ 148 | id: id 149 | }, schema); 150 | 151 | return new Promise((resolve, reject) => { 152 | if (valid.error) { 153 | return reject(valid.error); 154 | } 155 | 156 | request({ 157 | url: shotstackUrl + 'render/' + id, 158 | method: 'GET', 159 | headers: { 160 | 'x-api-key': shotstackApiKey 161 | }, 162 | json: true 163 | }, function (error, response, body) { 164 | if (error) { 165 | console.log(error); 166 | return reject(error); 167 | } 168 | 169 | return resolve(body.response); 170 | }); 171 | }); 172 | }; 173 | -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Shotstack Pexels Video Maker Demo 17 | 18 | 19 | 20 |
21 |
22 |
23 |
24 |
25 | 26 | 37 |
38 |
39 | 40 | 51 |
52 |
53 | 54 | 60 |
61 | 62 | 63 |
64 |
65 | 66 | Get the Source Code 67 |
68 |
69 |
70 |
71 |
72 |

Your video will display here

73 |
74 |
75 |
76 |
77 | 78 |

79 |
80 |
81 |
82 | Hold tight, rendering may take a minute... 83 |
84 |
85 | 86 |
87 |
88 |

89 | 92 |

93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /web/app.js: -------------------------------------------------------------------------------- 1 | var apiUrl = 'http://localhost:3000/demo/shotstack'; // 'https://3sd8oie0n1.execute-api.ap-southeast-2.amazonaws.com/demo/shotstack'; 2 | var progress = 0; 3 | var progressIncrement = 10; 4 | var pollIntervalSeconds = 10; 5 | var unknownError = 'An unknown error has occurred. Dispatching minions...'; 6 | var player; 7 | 8 | /** 9 | * Initialise and play the video 10 | * 11 | * @param {String} src the video URL 12 | */ 13 | function initialiseVideo(src) { 14 | player = new Plyr('#player'); 15 | 16 | player.source = { 17 | type: 'video', 18 | sources: [{ 19 | src: src, 20 | type: 'video/mp4', 21 | }] 22 | }; 23 | 24 | $('#status').removeClass('d-flex').addClass('d-none'); 25 | $('#player').show(); 26 | 27 | player.play(); 28 | } 29 | 30 | /** 31 | * Check the render status of the video 32 | * 33 | * @param {String} id the render job UUID 34 | */ 35 | function pollVideoStatus(id) { 36 | $.get(apiUrl + '/' + id, function(response) { 37 | updateStatus(response.data.status); 38 | if (!(response.data.status === 'done' || response.data.status === 'failed')) { 39 | setTimeout(function () { 40 | pollVideoStatus(id); 41 | }, pollIntervalSeconds * 1000); 42 | } else if (response.data.status === 'failed') { 43 | updateStatus(response.data.status); 44 | } else { 45 | initialiseVideo(response.data.url); 46 | initialiseJson(response.data.data); 47 | resetForm(); 48 | } 49 | }); 50 | } 51 | 52 | /** 53 | * Update status message and progress bar 54 | * 55 | * @param {String} status the status text 56 | */ 57 | function updateStatus(status) { 58 | if (progress <= 90) { 59 | progress += progressIncrement; 60 | } 61 | 62 | if (status === 'submitted') { 63 | $('#status .fas').attr('class', 'fas fa-spinner fa-spin fa-2x'); 64 | $('#status p').text('SUBMITTED'); 65 | } else if (status === 'queued') { 66 | $('#status .fas').attr('class', 'fas fa-history fa-2x'); 67 | $('#status p').text('QUEUED'); 68 | } else if (status === 'fetching') { 69 | $('#status .fas').attr('class', 'fas fa-cloud-download-alt fa-2x'); 70 | $('#status p').text('DOWNLOADING ASSETS'); 71 | } else if (status === 'rendering') { 72 | $('#status .fas').attr('class', 'fas fa-server fa-2x'); 73 | $('#status p').text('RENDERING VIDEO'); 74 | } else if (status === 'saving') { 75 | $('#status .fas').attr('class', 'fas fa-save fa-2x'); 76 | $('#status p').text('SAVING VIDEO'); 77 | } else if (status === 'done') { 78 | $('#status .fas').attr('class', 'fas fa-check-circle fa-2x'); 79 | $('#status p').text('READY'); 80 | progress = 100; 81 | } else { 82 | $('#status .fas').attr('class', 'fas fa-exclamation-triangle fa-2x'); 83 | $('#status p').text('SOMETHING WENT WRONG'); 84 | $('#submit-video').prop('disabled', false); 85 | progress = 0; 86 | } 87 | 88 | $('.progress-bar').css('width', progress + '%').attr('aria-valuenow', progress); 89 | } 90 | 91 | /** 92 | * Display form field and general errors returned by API 93 | * 94 | * @param error 95 | */ 96 | function displayError(error) { 97 | updateStatus(null); 98 | 99 | if (error.status === 400) { 100 | var response = error.responseJSON; 101 | 102 | if (response.data.isJoi) { 103 | $.each(response.data.details, function(index, error) { 104 | if (error.context.key === 'search') { 105 | $('#search-group label, #search').addClass('text-danger is-invalid'); 106 | $('#search-group').append('
Enter a subject keyword to create a video
').show(); 107 | } 108 | 109 | if (error.context.key === 'title') { 110 | $('#title-group label, #title').addClass('text-danger is-invalid'); 111 | $('#title-group').append('
Enter a title for your video
').show(); 112 | } 113 | 114 | if (error.context.key === 'soundtrack') { 115 | $('#soundtrack-group label, #soundtrack').addClass('text-danger is-invalid'); 116 | $('#soundtrack-group').append('
Please choose a soundtrack from the list
').show(); 117 | } 118 | }); 119 | } else if (typeof response.data === 'string') { 120 | $('#errors').text(response.data).removeClass('d-hide').addClass('d-block'); 121 | } else { 122 | $('#errors').text(unknownError).removeClass('d-hide').addClass('d-block'); 123 | } 124 | } else { 125 | $('#errors').text(unknownError).removeClass('d-hide').addClass('d-block'); 126 | } 127 | } 128 | 129 | /** 130 | * Reset errors 131 | */ 132 | function resetErrors() { 133 | $('input, label, select').removeClass('text-danger is-invalid'); 134 | $('.invalid-feedback').remove(); 135 | $('#errors').text('').removeClass('d-block').addClass('d-hide'); 136 | } 137 | 138 | /** 139 | * Reset form 140 | */ 141 | function resetForm() { 142 | $('form').trigger("reset"); 143 | $('#submit-video').prop('disabled', false); 144 | } 145 | 146 | /** 147 | * Reset and delete video 148 | */ 149 | function resetVideo() { 150 | if (player) { 151 | player.destroy(); 152 | player = undefined; 153 | } 154 | 155 | progress = 0; 156 | 157 | $('.json-container').html(''); 158 | $('#json').hide(); 159 | } 160 | 161 | /** 162 | * Submit the form with data to create a Shotstack edit 163 | */ 164 | function submitVideoEdit() { 165 | $('#submit-video').prop('disabled', true); 166 | $('#instructions').hide(); 167 | $('#status').removeClass('d-none').addClass('d-flex'); 168 | updateStatus('submitted'); 169 | 170 | var formData = { 171 | 'search': $('#search').val(), 172 | 'title': $('#title').val(), 173 | 'soundtrack': $('#soundtrack option:selected').val() 174 | }; 175 | 176 | $.ajax({ 177 | type: 'POST', 178 | url: apiUrl, 179 | data: JSON.stringify(formData), 180 | dataType: 'json', 181 | crossDomain: true, 182 | contentType: 'application/json' 183 | }).done(function(response) { 184 | if (response.status !== 'success') { 185 | displayError(response.message); 186 | $('#submit-video').prop('disabled', false); 187 | } else { 188 | pollVideoStatus(response.data.id); 189 | } 190 | }).fail(function(error) { 191 | displayError(error); 192 | $('#submit-video').prop('disabled', false); 193 | }); 194 | } 195 | 196 | /** 197 | * Colour and style JSON 198 | * 199 | * @param match 200 | * @param pIndent 201 | * @param pKey 202 | * @param pVal 203 | * @param pEnd 204 | * @returns {*} 205 | */ 206 | function styleJson(match, pIndent, pKey, pVal, pEnd) { 207 | var key = '"'; 208 | var val = ''; 209 | var str = ''; 210 | var r = pIndent || ''; 211 | if (pKey) 212 | r = r + key + pKey.replace(/[": ]/g, '') + '": '; 213 | if (pVal) 214 | r = r + (pVal[0] == '"' ? str : val) + pVal + ''; 215 | return r + (pEnd || ''); 216 | } 217 | 218 | /** 219 | * Pretty print JSON object on screen 220 | * 221 | * @param obj 222 | * @returns {string} 223 | */ 224 | function prettyPrintJson(obj) { 225 | var jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg; 226 | return JSON.stringify(obj, null, 3) 227 | .replace(/&/g, '&').replace(/\\"/g, '"') 228 | .replace(//g, '>') 229 | .replace(jsonLine, styleJson); 230 | } 231 | 232 | /** 233 | * Show the JSON display button 234 | * 235 | * @param json 236 | */ 237 | function initialiseJson(json) { 238 | $('.json-container').html(prettyPrintJson(json)); 239 | $('#json').show(); 240 | } 241 | 242 | $(document).ready(function() { 243 | $('form').submit(function(event) { 244 | resetErrors(); 245 | resetVideo(); 246 | submitVideoEdit(); 247 | 248 | event.preventDefault(); 249 | }); 250 | }); 251 | -------------------------------------------------------------------------------- /api/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-pexels-shotstack", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@hapi/address": { 8 | "version": "2.0.0", 9 | "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.0.0.tgz", 10 | "integrity": "sha512-mV6T0IYqb0xL1UALPFplXYQmR0twnXG0M6jUswpquqT2sD12BOiCiLy3EvMp/Fy7s3DZElC4/aPjEjo2jeZpvw==" 11 | }, 12 | "@hapi/hoek": { 13 | "version": "6.2.4", 14 | "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-6.2.4.tgz", 15 | "integrity": "sha512-HOJ20Kc93DkDVvjwHyHawPwPkX44sIrbXazAUDiUXaY2R9JwQGo2PhFfnQtdrsIe4igjG2fPgMra7NYw7qhy0A==" 16 | }, 17 | "@hapi/joi": { 18 | "version": "15.0.3", 19 | "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.0.3.tgz", 20 | "integrity": "sha512-z6CesJ2YBwgVCi+ci8SI8zixoj8bGFn/vZb9MBPbSyoxsS2PnWYjHcyTM17VLK6tx64YVK38SDIh10hJypB+ig==", 21 | "requires": { 22 | "@hapi/address": "2.x.x", 23 | "@hapi/hoek": "6.x.x", 24 | "@hapi/topo": "3.x.x" 25 | } 26 | }, 27 | "@hapi/topo": { 28 | "version": "3.1.0", 29 | "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.0.tgz", 30 | "integrity": "sha512-gZDI/eXOIk8kP2PkUKjWu9RW8GGVd2Hkgjxyr/S7Z+JF+0mr7bAlbw+DkTRxnD580o8Kqxlnba9wvqp5aOHBww==", 31 | "requires": { 32 | "@hapi/hoek": "6.x.x" 33 | } 34 | }, 35 | "accepts": { 36 | "version": "1.3.7", 37 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 38 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 39 | "dev": true, 40 | "requires": { 41 | "mime-types": "~2.1.24", 42 | "negotiator": "0.6.2" 43 | } 44 | }, 45 | "ajv": { 46 | "version": "6.10.0", 47 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", 48 | "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", 49 | "requires": { 50 | "fast-deep-equal": "^2.0.1", 51 | "fast-json-stable-stringify": "^2.0.0", 52 | "json-schema-traverse": "^0.4.1", 53 | "uri-js": "^4.2.2" 54 | } 55 | }, 56 | "ansi-styles": { 57 | "version": "3.2.1", 58 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 59 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 60 | "dev": true, 61 | "requires": { 62 | "color-convert": "^1.9.0" 63 | } 64 | }, 65 | "array-flatten": { 66 | "version": "1.1.1", 67 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 68 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", 69 | "dev": true 70 | }, 71 | "asn1": { 72 | "version": "0.2.4", 73 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 74 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 75 | "requires": { 76 | "safer-buffer": "~2.1.0" 77 | } 78 | }, 79 | "assert-plus": { 80 | "version": "1.0.0", 81 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 82 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 83 | }, 84 | "asynckit": { 85 | "version": "0.4.0", 86 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 87 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 88 | }, 89 | "aws-sign2": { 90 | "version": "0.7.0", 91 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 92 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 93 | }, 94 | "aws4": { 95 | "version": "1.8.0", 96 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 97 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" 98 | }, 99 | "bcrypt-pbkdf": { 100 | "version": "1.0.2", 101 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 102 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 103 | "requires": { 104 | "tweetnacl": "^0.14.3" 105 | } 106 | }, 107 | "body-parser": { 108 | "version": "1.19.0", 109 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 110 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 111 | "dev": true, 112 | "requires": { 113 | "bytes": "3.1.0", 114 | "content-type": "~1.0.4", 115 | "debug": "2.6.9", 116 | "depd": "~1.1.2", 117 | "http-errors": "1.7.2", 118 | "iconv-lite": "0.4.24", 119 | "on-finished": "~2.3.0", 120 | "qs": "6.7.0", 121 | "raw-body": "2.4.0", 122 | "type-is": "~1.6.17" 123 | }, 124 | "dependencies": { 125 | "iconv-lite": { 126 | "version": "0.4.24", 127 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 128 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 129 | "dev": true, 130 | "requires": { 131 | "safer-buffer": ">= 2.1.2 < 3" 132 | } 133 | } 134 | } 135 | }, 136 | "bytes": { 137 | "version": "3.1.0", 138 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 139 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", 140 | "dev": true 141 | }, 142 | "caseless": { 143 | "version": "0.12.0", 144 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 145 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 146 | }, 147 | "chalk": { 148 | "version": "2.4.2", 149 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 150 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 151 | "dev": true, 152 | "requires": { 153 | "ansi-styles": "^3.2.1", 154 | "escape-string-regexp": "^1.0.5", 155 | "supports-color": "^5.3.0" 156 | } 157 | }, 158 | "color-convert": { 159 | "version": "1.9.3", 160 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 161 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 162 | "dev": true, 163 | "requires": { 164 | "color-name": "1.1.3" 165 | } 166 | }, 167 | "color-name": { 168 | "version": "1.1.3", 169 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 170 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 171 | "dev": true 172 | }, 173 | "combined-stream": { 174 | "version": "1.0.8", 175 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 176 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 177 | "requires": { 178 | "delayed-stream": "~1.0.0" 179 | } 180 | }, 181 | "content-disposition": { 182 | "version": "0.5.3", 183 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 184 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 185 | "dev": true, 186 | "requires": { 187 | "safe-buffer": "5.1.2" 188 | } 189 | }, 190 | "content-type": { 191 | "version": "1.0.4", 192 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 193 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 194 | "dev": true 195 | }, 196 | "cookie": { 197 | "version": "0.4.0", 198 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 199 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", 200 | "dev": true 201 | }, 202 | "cookie-signature": { 203 | "version": "1.0.6", 204 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 205 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", 206 | "dev": true 207 | }, 208 | "core-util-is": { 209 | "version": "1.0.2", 210 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 211 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 212 | }, 213 | "dashdash": { 214 | "version": "1.14.1", 215 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 216 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 217 | "requires": { 218 | "assert-plus": "^1.0.0" 219 | } 220 | }, 221 | "debug": { 222 | "version": "2.6.9", 223 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 224 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 225 | "dev": true, 226 | "requires": { 227 | "ms": "2.0.0" 228 | } 229 | }, 230 | "delayed-stream": { 231 | "version": "1.0.0", 232 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 233 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 234 | }, 235 | "depd": { 236 | "version": "1.1.2", 237 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 238 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", 239 | "dev": true 240 | }, 241 | "destroy": { 242 | "version": "1.0.4", 243 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 244 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", 245 | "dev": true 246 | }, 247 | "dotenv": { 248 | "version": "4.0.0", 249 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", 250 | "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=", 251 | "dev": true 252 | }, 253 | "dotenv-expand": { 254 | "version": "4.2.0", 255 | "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.2.0.tgz", 256 | "integrity": "sha1-3vHxyl1gWdJKdm5YeULCEQbOEnU=", 257 | "dev": true 258 | }, 259 | "ecc-jsbn": { 260 | "version": "0.1.2", 261 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 262 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 263 | "requires": { 264 | "jsbn": "~0.1.0", 265 | "safer-buffer": "^2.1.0" 266 | } 267 | }, 268 | "ee-first": { 269 | "version": "1.1.1", 270 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 271 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", 272 | "dev": true 273 | }, 274 | "encodeurl": { 275 | "version": "1.0.2", 276 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 277 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 278 | "dev": true 279 | }, 280 | "encoding": { 281 | "version": "0.1.12", 282 | "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", 283 | "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", 284 | "requires": { 285 | "iconv-lite": "~0.4.13" 286 | } 287 | }, 288 | "escape-html": { 289 | "version": "1.0.3", 290 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 291 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", 292 | "dev": true 293 | }, 294 | "escape-string-regexp": { 295 | "version": "1.0.5", 296 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 297 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 298 | "dev": true 299 | }, 300 | "etag": { 301 | "version": "1.8.1", 302 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 303 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", 304 | "dev": true 305 | }, 306 | "express": { 307 | "version": "4.17.1", 308 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 309 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 310 | "dev": true, 311 | "requires": { 312 | "accepts": "~1.3.7", 313 | "array-flatten": "1.1.1", 314 | "body-parser": "1.19.0", 315 | "content-disposition": "0.5.3", 316 | "content-type": "~1.0.4", 317 | "cookie": "0.4.0", 318 | "cookie-signature": "1.0.6", 319 | "debug": "2.6.9", 320 | "depd": "~1.1.2", 321 | "encodeurl": "~1.0.2", 322 | "escape-html": "~1.0.3", 323 | "etag": "~1.8.1", 324 | "finalhandler": "~1.1.2", 325 | "fresh": "0.5.2", 326 | "merge-descriptors": "1.0.1", 327 | "methods": "~1.1.2", 328 | "on-finished": "~2.3.0", 329 | "parseurl": "~1.3.3", 330 | "path-to-regexp": "0.1.7", 331 | "proxy-addr": "~2.0.5", 332 | "qs": "6.7.0", 333 | "range-parser": "~1.2.1", 334 | "safe-buffer": "5.1.2", 335 | "send": "0.17.1", 336 | "serve-static": "1.14.1", 337 | "setprototypeof": "1.1.1", 338 | "statuses": "~1.5.0", 339 | "type-is": "~1.6.18", 340 | "utils-merge": "1.0.1", 341 | "vary": "~1.1.2" 342 | } 343 | }, 344 | "extend": { 345 | "version": "3.0.2", 346 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 347 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 348 | }, 349 | "extsprintf": { 350 | "version": "1.3.0", 351 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 352 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 353 | }, 354 | "fast-deep-equal": { 355 | "version": "2.0.1", 356 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 357 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" 358 | }, 359 | "fast-json-stable-stringify": { 360 | "version": "2.0.0", 361 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 362 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 363 | }, 364 | "finalhandler": { 365 | "version": "1.1.2", 366 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 367 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 368 | "dev": true, 369 | "requires": { 370 | "debug": "2.6.9", 371 | "encodeurl": "~1.0.2", 372 | "escape-html": "~1.0.3", 373 | "on-finished": "~2.3.0", 374 | "parseurl": "~1.3.3", 375 | "statuses": "~1.5.0", 376 | "unpipe": "~1.0.0" 377 | } 378 | }, 379 | "forever-agent": { 380 | "version": "0.6.1", 381 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 382 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 383 | }, 384 | "form-data": { 385 | "version": "2.3.3", 386 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 387 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 388 | "requires": { 389 | "asynckit": "^0.4.0", 390 | "combined-stream": "^1.0.6", 391 | "mime-types": "^2.1.12" 392 | } 393 | }, 394 | "forwarded": { 395 | "version": "0.1.2", 396 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 397 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", 398 | "dev": true 399 | }, 400 | "fresh": { 401 | "version": "0.5.2", 402 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 403 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", 404 | "dev": true 405 | }, 406 | "getpass": { 407 | "version": "0.1.7", 408 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 409 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 410 | "requires": { 411 | "assert-plus": "^1.0.0" 412 | } 413 | }, 414 | "har-schema": { 415 | "version": "2.0.0", 416 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 417 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 418 | }, 419 | "har-validator": { 420 | "version": "5.1.3", 421 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", 422 | "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", 423 | "requires": { 424 | "ajv": "^6.5.5", 425 | "har-schema": "^2.0.0" 426 | } 427 | }, 428 | "has-flag": { 429 | "version": "3.0.0", 430 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 431 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 432 | "dev": true 433 | }, 434 | "http-errors": { 435 | "version": "1.7.2", 436 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 437 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 438 | "dev": true, 439 | "requires": { 440 | "depd": "~1.1.2", 441 | "inherits": "2.0.3", 442 | "setprototypeof": "1.1.1", 443 | "statuses": ">= 1.5.0 < 2", 444 | "toidentifier": "1.0.0" 445 | } 446 | }, 447 | "http-signature": { 448 | "version": "1.2.0", 449 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 450 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 451 | "requires": { 452 | "assert-plus": "^1.0.0", 453 | "jsprim": "^1.2.2", 454 | "sshpk": "^1.7.0" 455 | } 456 | }, 457 | "iconv-lite": { 458 | "version": "0.4.23", 459 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", 460 | "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", 461 | "requires": { 462 | "safer-buffer": ">= 2.1.2 < 3" 463 | } 464 | }, 465 | "inherits": { 466 | "version": "2.0.3", 467 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 468 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 469 | "dev": true 470 | }, 471 | "ipaddr.js": { 472 | "version": "1.9.0", 473 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", 474 | "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", 475 | "dev": true 476 | }, 477 | "is-stream": { 478 | "version": "1.1.0", 479 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 480 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 481 | }, 482 | "is-typedarray": { 483 | "version": "1.0.0", 484 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 485 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 486 | }, 487 | "isstream": { 488 | "version": "0.1.2", 489 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 490 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 491 | }, 492 | "jsbn": { 493 | "version": "0.1.1", 494 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 495 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 496 | }, 497 | "json-schema": { 498 | "version": "0.2.3", 499 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 500 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 501 | }, 502 | "json-schema-traverse": { 503 | "version": "0.4.1", 504 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 505 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 506 | }, 507 | "json-stringify-safe": { 508 | "version": "5.0.1", 509 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 510 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 511 | }, 512 | "jsprim": { 513 | "version": "1.4.1", 514 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 515 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 516 | "requires": { 517 | "assert-plus": "1.0.0", 518 | "extsprintf": "1.3.0", 519 | "json-schema": "0.2.3", 520 | "verror": "1.10.0" 521 | } 522 | }, 523 | "media-typer": { 524 | "version": "0.3.0", 525 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 526 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", 527 | "dev": true 528 | }, 529 | "merge-descriptors": { 530 | "version": "1.0.1", 531 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 532 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", 533 | "dev": true 534 | }, 535 | "methods": { 536 | "version": "1.1.2", 537 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 538 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 539 | "dev": true 540 | }, 541 | "mime": { 542 | "version": "1.6.0", 543 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 544 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 545 | "dev": true 546 | }, 547 | "mime-db": { 548 | "version": "1.40.0", 549 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", 550 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" 551 | }, 552 | "mime-types": { 553 | "version": "2.1.24", 554 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", 555 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", 556 | "requires": { 557 | "mime-db": "1.40.0" 558 | } 559 | }, 560 | "ms": { 561 | "version": "2.0.0", 562 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 563 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 564 | "dev": true 565 | }, 566 | "negotiator": { 567 | "version": "0.6.2", 568 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 569 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", 570 | "dev": true 571 | }, 572 | "node-fetch": { 573 | "version": "1.7.3", 574 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", 575 | "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", 576 | "requires": { 577 | "encoding": "^0.1.11", 578 | "is-stream": "^1.0.1" 579 | } 580 | }, 581 | "oauth-sign": { 582 | "version": "0.9.0", 583 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 584 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 585 | }, 586 | "on-finished": { 587 | "version": "2.3.0", 588 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 589 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 590 | "dev": true, 591 | "requires": { 592 | "ee-first": "1.1.1" 593 | } 594 | }, 595 | "parseurl": { 596 | "version": "1.3.3", 597 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 598 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 599 | "dev": true 600 | }, 601 | "path-to-regexp": { 602 | "version": "0.1.7", 603 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 604 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", 605 | "dev": true 606 | }, 607 | "performance-now": { 608 | "version": "2.1.0", 609 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 610 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 611 | }, 612 | "pexels-api-wrapper": { 613 | "version": "1.1.1", 614 | "resolved": "https://registry.npmjs.org/pexels-api-wrapper/-/pexels-api-wrapper-1.1.1.tgz", 615 | "integrity": "sha512-vSjDN/4X/at+2io6AV2IYuZCdJZwJM36YHhx83CorUQYvrnbXkEK2Ve9tDqMUq1eAcr4jnja6eRpv10wOFWdcQ==", 616 | "requires": { 617 | "node-fetch": "^1.7.1" 618 | } 619 | }, 620 | "proxy-addr": { 621 | "version": "2.0.5", 622 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", 623 | "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", 624 | "dev": true, 625 | "requires": { 626 | "forwarded": "~0.1.2", 627 | "ipaddr.js": "1.9.0" 628 | } 629 | }, 630 | "psl": { 631 | "version": "1.1.32", 632 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.32.tgz", 633 | "integrity": "sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==" 634 | }, 635 | "punycode": { 636 | "version": "2.1.1", 637 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 638 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" 639 | }, 640 | "qs": { 641 | "version": "6.7.0", 642 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 643 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", 644 | "dev": true 645 | }, 646 | "range-parser": { 647 | "version": "1.2.1", 648 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 649 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 650 | "dev": true 651 | }, 652 | "raw-body": { 653 | "version": "2.4.0", 654 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 655 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 656 | "dev": true, 657 | "requires": { 658 | "bytes": "3.1.0", 659 | "http-errors": "1.7.2", 660 | "iconv-lite": "0.4.24", 661 | "unpipe": "1.0.0" 662 | }, 663 | "dependencies": { 664 | "iconv-lite": { 665 | "version": "0.4.24", 666 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 667 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 668 | "dev": true, 669 | "requires": { 670 | "safer-buffer": ">= 2.1.2 < 3" 671 | } 672 | } 673 | } 674 | }, 675 | "request": { 676 | "version": "2.88.0", 677 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 678 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 679 | "requires": { 680 | "aws-sign2": "~0.7.0", 681 | "aws4": "^1.8.0", 682 | "caseless": "~0.12.0", 683 | "combined-stream": "~1.0.6", 684 | "extend": "~3.0.2", 685 | "forever-agent": "~0.6.1", 686 | "form-data": "~2.3.2", 687 | "har-validator": "~5.1.0", 688 | "http-signature": "~1.2.0", 689 | "is-typedarray": "~1.0.0", 690 | "isstream": "~0.1.2", 691 | "json-stringify-safe": "~5.0.1", 692 | "mime-types": "~2.1.19", 693 | "oauth-sign": "~0.9.0", 694 | "performance-now": "^2.1.0", 695 | "qs": "~6.5.2", 696 | "safe-buffer": "^5.1.2", 697 | "tough-cookie": "~2.4.3", 698 | "tunnel-agent": "^0.6.0", 699 | "uuid": "^3.3.2" 700 | }, 701 | "dependencies": { 702 | "qs": { 703 | "version": "6.5.2", 704 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 705 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 706 | } 707 | } 708 | }, 709 | "safe-buffer": { 710 | "version": "5.1.2", 711 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 712 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 713 | }, 714 | "safer-buffer": { 715 | "version": "2.1.2", 716 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 717 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 718 | }, 719 | "send": { 720 | "version": "0.17.1", 721 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 722 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 723 | "dev": true, 724 | "requires": { 725 | "debug": "2.6.9", 726 | "depd": "~1.1.2", 727 | "destroy": "~1.0.4", 728 | "encodeurl": "~1.0.2", 729 | "escape-html": "~1.0.3", 730 | "etag": "~1.8.1", 731 | "fresh": "0.5.2", 732 | "http-errors": "~1.7.2", 733 | "mime": "1.6.0", 734 | "ms": "2.1.1", 735 | "on-finished": "~2.3.0", 736 | "range-parser": "~1.2.1", 737 | "statuses": "~1.5.0" 738 | }, 739 | "dependencies": { 740 | "ms": { 741 | "version": "2.1.1", 742 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 743 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 744 | "dev": true 745 | } 746 | } 747 | }, 748 | "serve-static": { 749 | "version": "1.14.1", 750 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 751 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 752 | "dev": true, 753 | "requires": { 754 | "encodeurl": "~1.0.2", 755 | "escape-html": "~1.0.3", 756 | "parseurl": "~1.3.3", 757 | "send": "0.17.1" 758 | } 759 | }, 760 | "serverless-dotenv-plugin": { 761 | "version": "1.2.1", 762 | "resolved": "https://registry.npmjs.org/serverless-dotenv-plugin/-/serverless-dotenv-plugin-1.2.1.tgz", 763 | "integrity": "sha512-gDzF/B1Ro7oEdaZ0pQ5eSxIU6Qng+uyTc6KquegQMChYrUKBCl0iHIoS7HqIYweGQt5Bo6FJFDJ4xq1cTEZO9A==", 764 | "dev": true, 765 | "requires": { 766 | "chalk": "^2.1.0", 767 | "dotenv": "^4.0.0", 768 | "dotenv-expand": "^4.0.1" 769 | } 770 | }, 771 | "setprototypeof": { 772 | "version": "1.1.1", 773 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 774 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", 775 | "dev": true 776 | }, 777 | "sshpk": { 778 | "version": "1.16.1", 779 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", 780 | "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", 781 | "requires": { 782 | "asn1": "~0.2.3", 783 | "assert-plus": "^1.0.0", 784 | "bcrypt-pbkdf": "^1.0.0", 785 | "dashdash": "^1.12.0", 786 | "ecc-jsbn": "~0.1.1", 787 | "getpass": "^0.1.1", 788 | "jsbn": "~0.1.0", 789 | "safer-buffer": "^2.0.2", 790 | "tweetnacl": "~0.14.0" 791 | } 792 | }, 793 | "statuses": { 794 | "version": "1.5.0", 795 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 796 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 797 | "dev": true 798 | }, 799 | "supports-color": { 800 | "version": "5.5.0", 801 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 802 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 803 | "dev": true, 804 | "requires": { 805 | "has-flag": "^3.0.0" 806 | } 807 | }, 808 | "toidentifier": { 809 | "version": "1.0.0", 810 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 811 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", 812 | "dev": true 813 | }, 814 | "tough-cookie": { 815 | "version": "2.4.3", 816 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 817 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 818 | "requires": { 819 | "psl": "^1.1.24", 820 | "punycode": "^1.4.1" 821 | }, 822 | "dependencies": { 823 | "punycode": { 824 | "version": "1.4.1", 825 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 826 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 827 | } 828 | } 829 | }, 830 | "tunnel-agent": { 831 | "version": "0.6.0", 832 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 833 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 834 | "requires": { 835 | "safe-buffer": "^5.0.1" 836 | } 837 | }, 838 | "tweetnacl": { 839 | "version": "0.14.5", 840 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 841 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 842 | }, 843 | "type-is": { 844 | "version": "1.6.18", 845 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 846 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 847 | "dev": true, 848 | "requires": { 849 | "media-typer": "0.3.0", 850 | "mime-types": "~2.1.24" 851 | } 852 | }, 853 | "unpipe": { 854 | "version": "1.0.0", 855 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 856 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 857 | "dev": true 858 | }, 859 | "uri-js": { 860 | "version": "4.2.2", 861 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 862 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 863 | "requires": { 864 | "punycode": "^2.1.0" 865 | } 866 | }, 867 | "utils-merge": { 868 | "version": "1.0.1", 869 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 870 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 871 | "dev": true 872 | }, 873 | "uuid": { 874 | "version": "3.3.2", 875 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 876 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 877 | }, 878 | "vary": { 879 | "version": "1.1.2", 880 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 881 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 882 | "dev": true 883 | }, 884 | "verror": { 885 | "version": "1.10.0", 886 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 887 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 888 | "requires": { 889 | "assert-plus": "^1.0.0", 890 | "core-util-is": "1.0.2", 891 | "extsprintf": "^1.2.0" 892 | } 893 | } 894 | } 895 | } 896 | --------------------------------------------------------------------------------