HW7: done task 5. All mandatory tasks are complete

This commit is contained in:
Claudio Maggioni 2019-11-14 10:55:43 +01:00
parent d13d2ac182
commit 6f2d820fdd
7 changed files with 191 additions and 9 deletions

View file

@ -89,4 +89,15 @@ eventBus.on('favorite.deleted', (event) => {
io.emit('favorite.deleted', event); io.emit('favorite.deleted', event);
}); });
const { exec } = require('child_process');
const client = '3710c666dbec94e';
const imgURL = `https://api.imgur.com/oauth2/authorize?client_id=${client}` +
"&response_type=token";
exec(`open '${imgURL}' || xdg-open ${imgURL}`, (err) => {
if (err) {
console.error(err);
}
});
module.exports = app; module.exports = app;

View file

@ -23,10 +23,12 @@
"debug": "^3.1.0", "debug": "^3.1.0",
"dustjs-linkedin": "^2.7.5", "dustjs-linkedin": "^2.7.5",
"express": "^4.16.2", "express": "^4.16.2",
"form-data": "^3.0.0",
"klei-dust": "^1.0.0", "klei-dust": "^1.0.0",
"method-override": "^3.0.0", "method-override": "^3.0.0",
"mongoose": "^5.7.7", "mongoose": "^5.7.7",
"morgan": "^1.9.0", "morgan": "^1.9.0",
"node-fetch": "^2.6.0",
"request": "^2.88.0", "request": "^2.88.0",
"socket.io": "^2.3.0", "socket.io": "^2.3.0",
"supertest": "^3.0.0" "supertest": "^3.0.0"

View file

@ -1,5 +1,6 @@
(function(dust){dust.register("favourites",body_0);function body_0(chk,ctx){return chk.w("<html><head><meta charset=\"utf-8\">").x(ctx.get(["bookmarked"], false),ctx,{"else":body_1,"block":body_2},{}).w("</head><body>").x(ctx.get(["bookmarked"], false),ctx,{"else":body_3,"block":body_4},{}).s(ctx.get(["favs"], false),ctx,{"else":body_5,"block":body_6},{}).w("</body></html>");}body_0.__dustBody=!0;function body_1(chk,ctx){return chk.w("<title>Favourites</title>");}body_1.__dustBody=!0;function body_2(chk,ctx){return chk.w("<title>Bookmarked</title>");}body_2.__dustBody=!0;function body_3(chk,ctx){return chk.w("<h1>Favourites</h1>");}body_3.__dustBody=!0;function body_4(chk,ctx){return chk.w("<h1>Bookmarked</h1>");}body_4.__dustBody=!0;function body_5(chk,ctx){return chk.w("<strong>No favourites.</strong>");}body_5.__dustBody=!0;function body_6(chk,ctx){return chk.w("<div>").p("favourite_partial",ctx,ctx,{"name":ctx.get(["name"], false),"dataURL":ctx.get(["dataURL"], false),"_id":ctx.get(["_id"], false),"bookmarked":ctx.get(["bookmarked"], false),"details":"true"}).w("</div>");}body_6.__dustBody=!0;return body_0}(dust));
(function(dust){dust.register("500",body_0);function body_0(chk,ctx){return chk.w("<html><head><meta charset='utf-8'></head><body><h1>Error 500</h1><pre>").f(ctx.get(["err"], false),ctx,"h").w("</pre></body></html>");}body_0.__dustBody=!0;return body_0}(dust)); (function(dust){dust.register("500",body_0);function body_0(chk,ctx){return chk.w("<html><head><meta charset='utf-8'></head><body><h1>Error 500</h1><pre>").f(ctx.get(["err"], false),ctx,"h").w("</pre></body></html>");}body_0.__dustBody=!0;return body_0}(dust));
(function(dust){dust.register("index",body_0);function body_0(chk,ctx){return chk.w("<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>OO-JS Exercise - Web Atelier 2017</title><link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css\"><link rel=\"stylesheet\" href=\"style.css\"></head><body onload=\"init()\"><h1>OO-JS Exercise: Canvas</h1><div id=\"app\"><div id=\"left-toolbar\" class=\"toolbar\"><button id=\"clear-btn\">Clear</button><button id=\"undo-btn\">Undo</button><button id=\"camera-btn\"><i class=\"fa fa-camera\" aria-hidden=\"true\"></i></button></div><canvas id=\"canvas\" width=\"600\" height=\"400\"></canvas><div id=\"brush-toolbar\" class=\"toolbar\"><!-- Brushes buttons go here (programmatically). Each button should be a <button> element --></div></div><div id=\"favourites\"></div><script src=\"dustjs-linkedin/dust-full.min.js\"></script><script src=\"js/views.js\"></script><script src=\"js/fetch.js\"></script><script src=\"scripts/brushes.js\"></script><script src=\"scripts/undo.js\"></script><!-- <script src=\"scripts/clock.js\"></script> --><script src=\"scripts/app.js\"></script><script src=\"main.js\"></script></body></html>");}body_0.__dustBody=!0;return body_0}(dust));
(function(dust){dust.register("favourite_partial",body_0);function body_0(chk,ctx){return chk.w("<h3>").f(ctx.get(["name"], false),ctx,"h").w("</h3><img src=\"").f(ctx.get(["dataURL"], false),ctx,"h").w("\" alt=\"").f(ctx.get(["name"], false),ctx,"h").w("\">").x(ctx.get(["b"], false),ctx,{"block":body_1},{}).x(ctx.get(["details"], false),ctx,{"else":body_2,"block":body_5},{});}body_0.__dustBody=!0;function body_1(chk,ctx){return chk.w("<p><strong>Bookmarked</strong></p>");}body_1.__dustBody=!0;function body_2(chk,ctx){return chk.w("<form id=\"favourite").f(ctx.get(["_id"], false),ctx,"h").w("\" method=\"POST\" action=\"/favorites/").f(ctx.get(["_id"], false),ctx,"h").w("?_method=PUT\"><input type=\"hidden\" name=\"dataURL\" value=\"").f(ctx.get(["dataURL"], false),ctx,"h").w("\"><label for=\"name\">Name:</label><input type=\"text\" name=\"name\" placeholder=\"Name\" value=\"").f(ctx.get(["name"], false),ctx,"h").w("\"><br><button data-update>Update</button><br><button data-delete formaction=\"/favorites/").f(ctx.get(["_id"], false),ctx,"h").w("?_method=DELETE\">Delete</button><br>").x(ctx.get(["bookmarked"], false),ctx,{"else":body_3,"block":body_4},{}).w("</form>");}body_2.__dustBody=!0;function body_3(chk,ctx){return chk.w("<button data-bookmark name=\"bookmarked\" value=\"true\"formaction=\"/favorites/").f(ctx.get(["_id"], false),ctx,"h").w("/bookmarked?_method=PUT\">Add bookmark</button>");}body_3.__dustBody=!0;function body_4(chk,ctx){return chk.w("<button data-del-bookmark name=\"bookmarked\" value=\"false\"formaction=\"/favorites/").f(ctx.get(["_id"], false),ctx,"h").w("/bookmarked?_method=PUT\">Remove bookmark</button>");}body_4.__dustBody=!0;function body_5(chk,ctx){return chk.w("<a href=\"/favorites/").f(ctx.get(["_id"], false),ctx,"h").w("\">Details</a>");}body_5.__dustBody=!0;return body_0}(dust));
(function(dust){dust.register("favourite",body_0);function body_0(chk,ctx){return chk.w("<html><head><meta charset=\"utf-8\"><title>").f(ctx.get(["name"], false),ctx,"h").w("</title></head><body>").p("favourite_partial",ctx,ctx,{}).w("<a href=\"/favorites\">Favourites list</a></body></html>");}body_0.__dustBody=!0;return body_0}(dust)); (function(dust){dust.register("favourite",body_0);function body_0(chk,ctx){return chk.w("<html><head><meta charset=\"utf-8\"><title>").f(ctx.get(["name"], false),ctx,"h").w("</title></head><body>").p("favourite_partial",ctx,ctx,{}).w("<a href=\"/favorites\">Favourites list</a></body></html>");}body_0.__dustBody=!0;return body_0}(dust));
(function(dust){dust.register("favourite_partial",body_0);function body_0(chk,ctx){return chk.w("<style>.hidden {display: none}</style><h3>").f(ctx.get(["name"], false),ctx,"h").w("</h3><img src=\"").f(ctx.get(["dataURL"], false),ctx,"h").w("\" alt=\"").f(ctx.get(["name"], false),ctx,"h").w("\">").x(ctx.get(["b"], false),ctx,{"block":body_1},{}).x(ctx.get(["details"], false),ctx,{"else":body_2,"block":body_5},{});}body_0.__dustBody=!0;function body_1(chk,ctx){return chk.w("<p><strong>Bookmarked</strong></p>");}body_1.__dustBody=!0;function body_2(chk,ctx){return chk.w("<form class=\"data\" id=\"favourite").f(ctx.get(["_id"], false),ctx,"h").w("\" method=\"POST\" action=\"/favorites/").f(ctx.get(["_id"], false),ctx,"h").w("?_method=PUT\"><input type=\"hidden\" name=\"dataURL\" value=\"").f(ctx.get(["dataURL"], false),ctx,"h").w("\"><label for=\"name\">Name:</label><input type=\"text\" name=\"name\" placeholder=\"Name\" value=\"").f(ctx.get(["name"], false),ctx,"h").w("\"><br><button type=\"button\" class=\"imgur\">Imgur options</button><hr><button data-update>Update</button><br><button data-delete formaction=\"/favorites/").f(ctx.get(["_id"], false),ctx,"h").w("?_method=DELETE\">Delete</button><br>").x(ctx.get(["bookmarked"], false),ctx,{"else":body_3,"block":body_4},{}).w("</form><form class=\"favorites hidden\"><hr><input type=\"hidden\" name=\"dataURL\" value=\"").f(ctx.get(["dataURL"], false),ctx,"h").w("\"><input type=\"text\" name=\"album\" placeholder=\"Imgur album name\"><br><input type=\"text\" name=\"tags\" placeholder=\"Imgur tags\"><br><label for=\"favorites\">Add in favorites</label><input type=\"checkbox\" name=\"favorites\"><button>Submit</button></form>");}body_2.__dustBody=!0;function body_3(chk,ctx){return chk.w("<button data-bookmark name=\"bookmarked\" value=\"true\"formaction=\"/favorites/").f(ctx.get(["_id"], false),ctx,"h").w("/bookmarked?_method=PUT\">Add bookmark</button>");}body_3.__dustBody=!0;function body_4(chk,ctx){return chk.w("<button data-del-bookmark name=\"bookmarked\" value=\"false\"formaction=\"/favorites/").f(ctx.get(["_id"], false),ctx,"h").w("/bookmarked?_method=PUT\">Remove bookmark</button>");}body_4.__dustBody=!0;function body_5(chk,ctx){return chk.w("<a href=\"/favorites/").f(ctx.get(["_id"], false),ctx,"h").w("\">Details</a>");}body_5.__dustBody=!0;return body_0}(dust));
(function(dust){dust.register("favourites",body_0);function body_0(chk,ctx){return chk.w("<html><head><meta charset=\"utf-8\">").x(ctx.get(["bookmarked"], false),ctx,{"else":body_1,"block":body_2},{}).w("</head><body>").x(ctx.get(["bookmarked"], false),ctx,{"else":body_3,"block":body_4},{}).s(ctx.get(["favs"], false),ctx,{"else":body_5,"block":body_6},{}).w("</body></html>");}body_0.__dustBody=!0;function body_1(chk,ctx){return chk.w("<title>Favourites</title>");}body_1.__dustBody=!0;function body_2(chk,ctx){return chk.w("<title>Bookmarked</title>");}body_2.__dustBody=!0;function body_3(chk,ctx){return chk.w("<h1>Favourites</h1>");}body_3.__dustBody=!0;function body_4(chk,ctx){return chk.w("<h1>Bookmarked</h1>");}body_4.__dustBody=!0;function body_5(chk,ctx){return chk.w("<strong>No favourites.</strong>");}body_5.__dustBody=!0;function body_6(chk,ctx){return chk.w("<div>").p("favourite_partial",ctx,ctx,{"name":ctx.get(["name"], false),"dataURL":ctx.get(["dataURL"], false),"_id":ctx.get(["_id"], false),"bookmarked":ctx.get(["bookmarked"], false),"details":"true"}).w("</div>");}body_6.__dustBody=!0;return body_0}(dust));
(function(dust){dust.register("index",body_0);function body_0(chk,ctx){return chk.w("<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>OO-JS Exercise - Web Atelier 2017</title><link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css\"><link rel=\"stylesheet\" href=\"style.css\"></head><body onload=\"init()\"><h1>OO-JS Exercise: Canvas</h1><div id=\"app\"><div id=\"left-toolbar\" class=\"toolbar\"><button id=\"clear-btn\">Clear</button><button id=\"undo-btn\">Undo</button><button id=\"camera-btn\"><i class=\"fa fa-camera\" aria-hidden=\"true\"></i></button></div><canvas id=\"canvas\" width=\"600\" height=\"400\"></canvas><div id=\"brush-toolbar\" class=\"toolbar\"><!-- Brushes buttons go here (programmatically). Each button should be a <button> element --></div></div><br><div><label for=\"name-filter\">By name search:</label><input id=\"name-filter\" type=\"text\" placeholder=\"Search by name\"><br><label for=\"bookmarked-filter\">Only bookmarked</label><input id=\"bookmarked-filter\" type=\"checkbox\"></div><div id=\"favourites\"></div><script src=\"dustjs-linkedin/dust-full.min.js\"></script><script src=\"js/views.js\"></script><script src=\"js/fetch.js\"></script><script src=\"/socket.io/socket.io.js\"></script><script src=\"scripts/brushes.js\"></script><script src=\"scripts/undo.js\"></script><!-- <script src=\"scripts/clock.js\"></script> --><script src=\"scripts/app.js\"></script><script src=\"main.js\"></script></body></html>");}body_0.__dustBody=!0;return body_0}(dust));
(function(dust){dust.register("server_side",body_0);function body_0(chk,ctx){return chk.s(ctx.get(["favs"], false),ctx,{"block":body_1},{});}body_0.__dustBody=!0;function body_1(chk,ctx){return chk.w("<div id=\"favorite_").f(ctx.get(["_id"], false),ctx,"h").w("\" class=\"").x(ctx.get(["bookmarked"], false),ctx,{"block":body_2},{}).w("\">").p("favourite_partial",ctx,ctx,{"name":ctx.get(["name"], false),"dataURL":ctx.get(["dataURL"], false),"_id":ctx.get(["_id"], false),"bookmarked":ctx.get(["bookmarked"], false)}).w("</div>");}body_1.__dustBody=!0;function body_2(chk,ctx){return chk.w("bookmarked");}body_2.__dustBody=!0;return body_0}(dust));

View file

@ -14,8 +14,41 @@ class App {
socketSessionId = null; socketSessionId = null;
registerFavoriteEvents(_id, dom) { registerFavoriteEvents(_id, dom) {
const form = dom.querySelector('form');
const imgurForm = dom.querySelector('form.favorites');
dom.querySelector('button.imgur').onclick = () => {
imgurForm.classList.toggle('hidden');
};
imgurForm.onsubmit = e => {
imgurForm.classList.remove('ok');
imgurForm.classList.remove('err');
e.preventDefault();
const data = new FormData(imgurForm);
const obj = {
dataURL: data.get('dataURL'),
name: dom.querySelector('form.data input[name=name]').value,
album: data.get('album'),
tags: data.get('tags'),
favorites: data.get('favorites')
};
doJSONRequest('POST', '/imgur/ordeal', {}, obj)
.then(e => {
if (e.ordealSuccess === true) {
imgurForm.classList.add('ok');
} else {
imgurForm.classList.add('err');
}
}).catch(e => {
console.error(e);
imgurForm.classList.add('err');
});
};
const form = dom.querySelector('form.data');
const delay = (f, ...args) => { const delay = (f, ...args) => {
const execute = (f, ...args) => { const execute = (f, ...args) => {
@ -224,8 +257,6 @@ class App {
nameFilter.onkeyup = onSearch; nameFilter.onkeyup = onSearch;
bookmarkFilter.onclick = onSearch; bookmarkFilter.onclick = onSearch;
if (typeof conf.buttons === 'object' && conf.buttons) { if (typeof conf.buttons === 'object' && conf.buttons) {
this.buttons = {} this.buttons = {}
for (const b of ['clear', 'undo', 'camera']) for (const b of ['clear', 'undo', 'camera'])

View file

@ -7,6 +7,8 @@ const router = express.Router();
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const Favorite = mongoose.model('Favorite'); const Favorite = mongoose.model('Favorite');
const fetch = require('node-fetch');
const querystring = require('querystring');
const { error } = require('../utils'); const { error } = require('../utils');
@ -15,10 +17,117 @@ router.get('/', (req, res) => {
if (err) { if (err) {
return error(err, res); return error(err, res);
} }
res.render('index.dust', { favs }); res.render('index.dust', { favs });
}); });
}); });
router.get('/imgur', (req, res) => {
if (req.query.access_token) {
req.app.locals.imgur = req.query;
res.redirect('/');
} else {
res.status(200, {'Content-Type': 'text/html'});
res.end(`<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>
<script>
console.log(window.location.href);
if (window.location.href.indexOf("#access") != -1) {
window.location.href = window.location.href.replace("#access",
"?access");
}
</script></body></html>`);
}
});
async function fetchImgur(req, res, method, url, body) {
const endpoint = 'https://api.imgur.com/3';
const uploadRes = await fetch(endpoint + url, {
method: method,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization' : 'Bearer ' + req.app.locals.imgur.access_token
},
body: querystring.stringify(body)
});
const uploadJson = await uploadRes.json();
if (Math.floor(uploadJson.status / 100) != 2) {
res.status(uploadJson.status).json(uploadJson);
return false;
}
console.log(url, uploadJson);
return uploadJson;
}
router.post('/imgur/ordeal', async (req, res) => {
try {
const uploadData = {
image: req.body.dataURL.substring('data:image/png;base64,'.length),
type: 'base64',
name: req.body.name + '.png',
};
const uploadJson = await fetchImgur(req, res, 'POST', '/upload', uploadData);
if (!uploadJson) {
return;
}
const imageId = uploadJson.data.id;
const albumData = {
'ids[]': imageId,
};
if (req.body.album) {
albumData.title = req.body.album;
}
const albumJson = await fetchImgur(req, res, 'POST', '/album', albumData);
if (!albumJson) {
return;
}
console.log(req.body.favorites);
if (req.body.favorites) {
if (!await fetchImgur(req, res, 'POST', '/album/' + albumJson.data.id +
'/favorite', {})) {
return;
}
}
if (!await fetchImgur(req, res, 'POST', '/gallery/album/' +
albumJson.data.id, { title: req.body.album ? req.body.album :
req.body.name })) {
return;
}
if (req.body.tags) {
const tagsData = {
'tags': req.body.tags
};
if (!await fetchImgur(req, res, 'POST', '/gallery/tags/' +
albumJson.data.id, tagsData)) {
return;
}
for (const tag of req.body.tags.split(',')) {
if (!await fetchImgur(req, res, 'POST', '/account/me/follow/tag/' + tag,
{})) {
return;
}
}
}
res.json({ordealSuccess: true});
} catch(e) {
console.error(e);
res.status(500).json(e);
}
});
/** router for /root */ /** router for /root */
module.exports = router; module.exports = router;

View file

@ -1,5 +1,9 @@
{! vim: set ts=2 sw=2 et tw=120: !} {! vim: set ts=2 sw=2 et tw=120: !}
<style>.hidden {display: none}
.ok {background-color: lightgreen}
.err {background-color: pink}</style>
<h3>{name}</h3> <h3>{name}</h3>
<img src="{dataURL}" alt="{name}"> <img src="{dataURL}" alt="{name}">
{?b} {?b}
@ -10,10 +14,11 @@
{?details} {?details}
<a href="/favorites/{_id}">Details</a> <a href="/favorites/{_id}">Details</a>
{:else} {:else}
<form id="favourite{_id}" method="POST" action="/favorites/{_id}?_method=PUT"> <form class="data" id="favourite{_id}" method="POST" action="/favorites/{_id}?_method=PUT">
<input type="hidden" name="dataURL" value="{dataURL}"> <input type="hidden" name="dataURL" value="{dataURL}">
<label for="name">Name:</label> <label for="name">Name:</label>
<input type="text" name="name" placeholder="Name" value="{name}"><br> <input type="text" name="name" placeholder="Name" value="{name}"><br>
<button type="button" class="imgur">Imgur options</button><hr>
<button data-update>Update</button><br> <button data-update>Update</button><br>
<button data-delete formaction="/favorites/{_id}?_method=DELETE">Delete</button><br> <button data-delete formaction="/favorites/{_id}?_method=DELETE">Delete</button><br>
{?bookmarked} {?bookmarked}
@ -24,4 +29,13 @@ formaction="/favorites/{_id}/bookmarked?_method=PUT">Remove bookmark</button>
formaction="/favorites/{_id}/bookmarked?_method=PUT">Add bookmark</button> formaction="/favorites/{_id}/bookmarked?_method=PUT">Add bookmark</button>
{/bookmarked} {/bookmarked}
</form> </form>
<form class="favorites hidden">
<hr>
<input type="hidden" name="dataURL" value="{dataURL}">
<input type="text" name="album" placeholder="Imgur album name"><br>
<input type="text" name="tags" placeholder="Imgur tags"><br>
<label for="favorites">Add in favorites</label>
<input type="checkbox" name="favorites">
<button>Submit</button>
</form>
{/details} {/details}

View file

@ -360,7 +360,7 @@ collection-visit@^1.0.0:
map-visit "^1.0.0" map-visit "^1.0.0"
object-visit "^1.0.0" object-visit "^1.0.0"
combined-stream@^1.0.6, combined-stream@~1.0.6: combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
version "1.0.8" version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
@ -816,6 +816,15 @@ form-data@^2.3.1:
combined-stream "^1.0.6" combined-stream "^1.0.6"
mime-types "^2.1.12" mime-types "^2.1.12"
form-data@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682"
integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@~2.3.2: form-data@~2.3.2:
version "2.3.3" version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@ -1610,6 +1619,11 @@ negotiator@0.6.2:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
node-fetch@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-pre-gyp@^0.12.0: node-pre-gyp@^0.12.0:
version "0.12.0" version "0.12.0"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149"