├── .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 |
69 |
70 |
71 |
72 |
Your video will display here
73 |
74 |
75 |
76 |
77 |
78 |
79 |
82 |
Hold tight, rendering may take a minute...
83 |
84 |
85 |
86 |
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 |
--------------------------------------------------------------------------------