From d03acb8a3cbc05aea67ba4f40ea92cfd078d5db6 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 28 Jul 2023 21:46:20 +0100 Subject: [PATCH 01/94] Update API endpoints to read URL params from either option --- api/check-hsts.js | 2 +- api/check-ports.js | 2 +- api/dns-sec.js | 2 +- api/dns-server.js | 3 ++- api/find-url-ip.js | 2 +- api/follow-redirects.js | 2 +- api/get-carbon.js | 2 +- api/get-cookies.js | 2 +- api/get-dns.js | 2 +- api/get-headers.js | 2 +- api/get-txt.js | 10 +++++++++- api/lighthouse-report.js | 2 +- api/read-robots-txt.js | 2 +- api/screenshot.js | 2 +- api/security-txt.js | 2 +- api/server-status.js | 2 +- api/site-features.js | 2 +- api/sitemap.js | 5 +++-- api/ssl-check.js | 2 +- api/tech-stack.js | 2 +- api/trace-route.js | 2 +- api/whois-lookup.js | 2 +- 22 files changed, 33 insertions(+), 23 deletions(-) diff --git a/api/check-hsts.js b/api/check-hsts.js index 901b7c0..71382cb 100644 --- a/api/check-hsts.js +++ b/api/check-hsts.js @@ -1,7 +1,7 @@ const https = require('https'); exports.handler = async function(event, context) { - const siteURL = event.queryStringParameters.url; + const siteURL = (event.queryStringParameters || event.query).url; const errorResponse = (message, statusCode = 500) => { return { diff --git a/api/check-ports.js b/api/check-ports.js index 4e94c77..00cb266 100644 --- a/api/check-ports.js +++ b/api/check-ports.js @@ -34,7 +34,7 @@ async function checkPort(port, domain) { } exports.handler = async (event, context) => { - const domain = event.queryStringParameters.url; + const domain = (event.queryStringParameters || event.query).url; if (!domain) { return errorResponse('Missing domain parameter.'); diff --git a/api/dns-sec.js b/api/dns-sec.js index a8ff986..c4cf3f3 100644 --- a/api/dns-sec.js +++ b/api/dns-sec.js @@ -1,7 +1,7 @@ const https = require('https'); exports.handler = async function(event, context) { - let { url } = event.queryStringParameters; + const url = (event.queryStringParameters || event.query).url; if (!url) { return errorResponse('URL query parameter is required.'); diff --git a/api/dns-server.js b/api/dns-server.js index 084f104..3bcbe3b 100644 --- a/api/dns-server.js +++ b/api/dns-server.js @@ -4,7 +4,8 @@ const dnsPromises = dns.promises; const axios = require('axios'); exports.handler = async (event) => { - const domain = event.queryStringParameters.url.replace(/^(?:https?:\/\/)?/i, ""); + const url = (event.queryStringParameters || event.query).url; + const domain = url.replace(/^(?:https?:\/\/)?/i, ""); try { const addresses = await dnsPromises.resolve4(domain); const results = await Promise.all(addresses.map(async (address) => { diff --git a/api/find-url-ip.js b/api/find-url-ip.js index 7172b6a..30355c9 100644 --- a/api/find-url-ip.js +++ b/api/find-url-ip.js @@ -2,7 +2,7 @@ const dns = require('dns'); /* Lambda function to fetch the IP address of a given URL */ exports.handler = function (event, context, callback) { - const addressParam = event.queryStringParameters.url; + const addressParam = (event.queryStringParameters || event.query).url; if (!addressParam) { callback(null, errorResponse('Address parameter is missing.')); diff --git a/api/follow-redirects.js b/api/follow-redirects.js index 7810cd1..42b56db 100644 --- a/api/follow-redirects.js +++ b/api/follow-redirects.js @@ -1,5 +1,5 @@ exports.handler = async (event) => { - const { url } = event.queryStringParameters; + const url = (event.queryStringParameters || event.query).url; const redirects = [url]; try { diff --git a/api/get-carbon.js b/api/get-carbon.js index c11605b..d975753 100644 --- a/api/get-carbon.js +++ b/api/get-carbon.js @@ -1,7 +1,7 @@ const https = require('https'); exports.handler = async (event, context) => { - const { url } = event.queryStringParameters; + const url = (event.queryStringParameters || event.query).url; if (!url) { return { diff --git a/api/get-cookies.js b/api/get-cookies.js index 2b17dbe..e2c05f2 100644 --- a/api/get-cookies.js +++ b/api/get-cookies.js @@ -1,7 +1,7 @@ const axios = require('axios'); exports.handler = async function(event, context) { - const { url } = event.queryStringParameters; + const url = (event.queryStringParameters || event.query).url; if (!url) { return { diff --git a/api/get-dns.js b/api/get-dns.js index 6f80ae9..1be91a2 100644 --- a/api/get-dns.js +++ b/api/get-dns.js @@ -2,7 +2,7 @@ const dns = require('dns'); const util = require('util'); exports.handler = async function(event, context) { - let hostname = event.queryStringParameters.url; + let hostname = (event.queryStringParameters || event.query).url; // Handle URLs by extracting hostname if (hostname.startsWith('http://') || hostname.startsWith('https://')) { diff --git a/api/get-headers.js b/api/get-headers.js index 4006d55..00cf755 100644 --- a/api/get-headers.js +++ b/api/get-headers.js @@ -1,7 +1,7 @@ const axios = require('axios'); exports.handler = async function(event, context) { - const { url } = event.queryStringParameters; + const url = (event.queryStringParameters || event.query).url; if (!url) { return { diff --git a/api/get-txt.js b/api/get-txt.js index 08eebc2..cf3883b 100644 --- a/api/get-txt.js +++ b/api/get-txt.js @@ -1,7 +1,15 @@ const dns = require('dns').promises; exports.handler = async (event) => { - const url = new URL(event.queryStringParameters.url); + let url = (event.queryStringParameters || event.query).url; + try { + url = new URL(url); + } catch (error) { + return { + statusCode: 400, + body: JSON.stringify({ error: `Invalid URL ${error}` }), + }; + } try { const txtRecords = await dns.resolveTxt(url.hostname); diff --git a/api/lighthouse-report.js b/api/lighthouse-report.js index 7123cca..ab76aff 100644 --- a/api/lighthouse-report.js +++ b/api/lighthouse-report.js @@ -1,7 +1,7 @@ const axios = require('axios'); exports.handler = function(event, context, callback) { - const { url } = event.queryStringParameters; + const url = (event.queryStringParameters || event.query).url; if (!url) { callback(null, { diff --git a/api/read-robots-txt.js b/api/read-robots-txt.js index 05a084f..50b7449 100644 --- a/api/read-robots-txt.js +++ b/api/read-robots-txt.js @@ -1,7 +1,7 @@ const axios = require('axios'); exports.handler = async function(event, context) { - const siteURL = event.queryStringParameters.url; + const siteURL = (event.queryStringParameters || event.query).url; if (!siteURL) { return { diff --git a/api/screenshot.js b/api/screenshot.js index a581a70..75f1741 100644 --- a/api/screenshot.js +++ b/api/screenshot.js @@ -3,7 +3,7 @@ const chromium = require('chrome-aws-lambda'); exports.handler = async (event, context, callback) => { let browser = null; - let targetUrl = event.queryStringParameters.url; + let targetUrl = (event.queryStringParameters || event.query).url; if (!targetUrl) { callback(null, { diff --git a/api/security-txt.js b/api/security-txt.js index dd6e68b..78ded4c 100644 --- a/api/security-txt.js +++ b/api/security-txt.js @@ -38,7 +38,7 @@ const isPgpSigned = (result) => { }; exports.handler = async (event, context) => { - const urlParam = event.queryStringParameters.url; + const urlParam = (event.queryStringParameters || event.query).url; if (!urlParam) { return { statusCode: 400, diff --git a/api/server-status.js b/api/server-status.js index 6d0dbbf..242df31 100644 --- a/api/server-status.js +++ b/api/server-status.js @@ -2,7 +2,7 @@ const https = require('https'); const { performance, PerformanceObserver } = require('perf_hooks'); exports.handler = async function(event, context) { - const { url } = event.queryStringParameters; + const url = (event.queryStringParameters || event.query).url; if (!url) { return { diff --git a/api/site-features.js b/api/site-features.js index f38bb3a..d9b6486 100644 --- a/api/site-features.js +++ b/api/site-features.js @@ -1,7 +1,7 @@ const https = require('https'); exports.handler = async function (event, context) { - const { url } = event.queryStringParameters; + const url = (event.queryStringParameters || event.query).url; const apiKey = process.env.BUILT_WITH_API_KEY; const errorResponse = (message, statusCode = 500) => { diff --git a/api/sitemap.js b/api/sitemap.js index 8b57f01..149835f 100644 --- a/api/sitemap.js +++ b/api/sitemap.js @@ -2,8 +2,9 @@ const axios = require('axios'); const xml2js = require('xml2js'); exports.handler = async (event) => { - const baseUrl = event.queryStringParameters.url.replace(/^(?:https?:\/\/)?/i, ""); - const url = baseUrl.startsWith('http') ? baseUrl : `http://${baseUrl}`; + const url = (event.queryStringParameters || event.query).url; + // const baseUrl = event.queryStringParameters.url.replace(/^(?:https?:\/\/)?/i, ""); + // const url = baseUrl.startsWith('http') ? baseUrl : `http://${baseUrl}`; let sitemapUrl; try { diff --git a/api/ssl-check.js b/api/ssl-check.js index 8f139c0..f87b66a 100644 --- a/api/ssl-check.js +++ b/api/ssl-check.js @@ -1,7 +1,7 @@ const https = require('https'); exports.handler = async function (event, context) { - const { url } = event.queryStringParameters; + const url = (event.queryStringParameters || event.query).url; const errorResponse = (message, statusCode = 500) => { return { diff --git a/api/tech-stack.js b/api/tech-stack.js index 6b4e86a..788a8f6 100644 --- a/api/tech-stack.js +++ b/api/tech-stack.js @@ -34,7 +34,7 @@ exports.handler = async (event, context, callback) => { } // Get URL from param - let url = event.queryStringParameters.url; + let url = (event.queryStringParameters || event.query).url; if (!/^https?:\/\//i.test(url)) { url = 'http://' + url; } diff --git a/api/trace-route.js b/api/trace-route.js index 08f8cbf..8d8525e 100644 --- a/api/trace-route.js +++ b/api/trace-route.js @@ -2,7 +2,7 @@ const traceroute = require('traceroute'); const url = require('url'); exports.handler = async function(event, context) { - const urlString = event.queryStringParameters.url; + const urlString = (event.queryStringParameters || event.query).url; try { if (!urlString) { diff --git a/api/whois-lookup.js b/api/whois-lookup.js index 3bca51f..3b6ba3e 100644 --- a/api/whois-lookup.js +++ b/api/whois-lookup.js @@ -24,7 +24,7 @@ const getBaseDomain = (url) => { exports.handler = async function(event, context) { - let url = event.queryStringParameters.url; + const url = (event.queryStringParameters || event.query).url; if (!url) { return errorResponse('URL query parameter is required.', 400); From 4d698483505abe89f2f98a3f5bc00eb661ad1560 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 28 Jul 2023 21:46:47 +0100 Subject: [PATCH 02/94] Adds aws-serverlss-express to run without netlify cli --- package.json | 1 + yarn.lock | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 1471758..41bfb3d 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@types/react-router-dom": "^5.3.3", "@types/react-simple-maps": "^3.0.0", "@types/styled-components": "^5.1.26", + "aws-serverless-express": "^3.4.0", "axios": "^1.4.0", "chrome-aws-lambda": "^10.1.0", "flatted": "^3.2.7", diff --git a/yarn.lock b/yarn.lock index b035d7b..1812339 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3827,6 +3827,14 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" +"@vendia/serverless-express@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@vendia/serverless-express/-/serverless-express-3.4.0.tgz#156f47d364b067ae6fa678a914c51887f494321a" + integrity sha512-/UAAbi9qRjUtjRISt5MJ1sfhtrHb26hqQ0nvE5qhMLsAdR5H7ErBwPD8Q/v2OENKm0iWsGwErIZEg7ebUeFDjQ== + dependencies: + binary-case "^1.0.0" + type-is "^1.6.16" + "@vercel/nft@^0.22.0": version "0.22.6" resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.22.6.tgz#edb30d300bb809c0945ea4c7b87e56f634885541" @@ -4626,6 +4634,15 @@ avvio@^8.2.0: debug "^4.0.0" fastq "^1.6.1" +aws-serverless-express@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/aws-serverless-express/-/aws-serverless-express-3.4.0.tgz#74153b8cc80dbd2c6a32a51e6d353a325c2710d7" + integrity sha512-YG9ZjAOI9OpwqDDWzkRc3kKJYJuR7gTMjLa3kAWopO17myoprxskCUyCEee+RKe34tcR4UNrVtgAwW5yDe74bw== + dependencies: + "@vendia/serverless-express" "^3.4.0" + binary-case "^1.0.0" + type-is "^1.6.16" + axe-core@^4.6.2: version "4.7.2" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0" @@ -4866,6 +4883,11 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +binary-case@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/binary-case/-/binary-case-1.1.4.tgz#d687104d59e38f2b9e658d3a58936963c59ab931" + integrity sha512-9Kq8m6NZTAgy05Ryuh7U3Qc4/ujLQU1AZ5vMw4cr3igTdi5itZC6kCNrRr2X8NzPiDn2oUIFTfa71DKMnue/Zg== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -15031,7 +15053,7 @@ type-fest@^3.0.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.13.1.tgz#bb744c1f0678bea7543a2d1ec24e83e68e8c8706" integrity sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g== -type-is@~1.6.18: +type-is@^1.6.16, type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== From 22995995d02b4e1c53de81d3f1658f887d1a4576 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 28 Jul 2023 21:47:07 +0100 Subject: [PATCH 03/94] Writes a central server file, to serve up API endpoints --- server.js | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 server.js diff --git a/server.js b/server.js new file mode 100644 index 0000000..2dd156c --- /dev/null +++ b/server.js @@ -0,0 +1,63 @@ +const express = require('express'); +const awsServerlessExpress = require('aws-serverless-express'); +const fs = require('fs'); +const path = require('path'); + +const app = express(); + +// Read the '/api' directory and import each lambda function +const handlers = {}; +fs.readdirSync(path.join(__dirname, '/api')).forEach(file => { + const route = `/api/${file.split('.')[0]}`; // remove .js extension + const handler = require(path.join(__dirname, '/api', file)).handler; + handlers[route] = handler; + + app.get(route, async (req, res) => { + try { + const result = await new Promise((resolve, reject) => { + const cb = (err, response) => err ? reject(err) : resolve(response); + const promise = handler(req, {}, cb); + if (promise && typeof promise.then === 'function') { + promise.then(resolve).catch(reject); + } + }); + res.status(result.statusCode).json(JSON.parse(result.body)); + } catch (err) { + res.status(500).json({ error: err.message }); + } + }); +}); + +app.get('/api', async (req, res) => { + const results = {}; + const url = req.query.url; + const handlerPromises = Object.entries(handlers).map(async ([route, handler]) => { + try { + const result = await new Promise((resolve, reject) => { + const cb = (err, response) => err ? reject(err) : resolve(response); + const promise = handler({ query: { url } }, {}, cb); + if (promise && typeof promise.then === 'function') { + promise.then(resolve).catch(reject); + } + }); + results[route.slice(5)] = JSON.parse(result.body); // remove '/api/' prefix + } catch (err) { + results[route.slice(5)] = { error: err.message }; + } + }); + + await Promise.all(handlerPromises); + res.json(results); +}); + +// Create serverless express server +const server = awsServerlessExpress +.createServer(app) +.listen(3001, () => { + console.log('Listening on port 3001'); +}); + +exports.handler = (event, context) => { + console.log(`EVENT: ${JSON.stringify(event)}`); + awsServerlessExpress.proxy(server, event, context); +}; From df24445ac691a5da195f18a3ca3f214e5928e38a Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 29 Jul 2023 09:38:25 +0100 Subject: [PATCH 04/94] Re-wrote sitemap lambda function --- api/sitemap.js | 66 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/api/sitemap.js b/api/sitemap.js index 8b57f01..ba2453a 100644 --- a/api/sitemap.js +++ b/api/sitemap.js @@ -2,40 +2,60 @@ const axios = require('axios'); const xml2js = require('xml2js'); exports.handler = async (event) => { - const baseUrl = event.queryStringParameters.url.replace(/^(?:https?:\/\/)?/i, ""); - const url = baseUrl.startsWith('http') ? baseUrl : `http://${baseUrl}`; - let sitemapUrl; + const url = event.queryStringParameters.url; + let sitemapUrl = `${url}/sitemap.xml`; try { - // Fetch robots.txt - const robotsRes = await axios.get(`${url}/robots.txt`); - const robotsTxt = robotsRes.data.split('\n'); + // Try to fetch sitemap directly + let sitemapRes; + try { + sitemapRes = await axios.get(sitemapUrl, { timeout: 5000 }); + } catch (error) { + if (error.response && error.response.status === 404) { + // If sitemap not found, try to fetch it from robots.txt + const robotsRes = await axios.get(`${url}/robots.txt`, { timeout: 5000 }); + const robotsTxt = robotsRes.data.split('\n'); - for (let line of robotsTxt) { - if (line.startsWith('Sitemap:')) { - sitemapUrl = line.split(' ')[1]; + for (let line of robotsTxt) { + if (line.toLowerCase().startsWith('sitemap:')) { + sitemapUrl = line.split(' ')[1].trim(); + break; + } + } + + if (!sitemapUrl) { + return { + statusCode: 404, + body: JSON.stringify({ skipped: 'No sitemap found' }), + }; + } + + sitemapRes = await axios.get(sitemapUrl, { timeout: 5000 }); + } else { + throw error; // If other error, throw it } } - if (!sitemapUrl) { - return { - statusCode: 404, - body: JSON.stringify({ error: 'Sitemap not found in robots.txt' }), - }; - } - - // Fetch sitemap - const sitemapRes = await axios.get(sitemapUrl); - const sitemap = await xml2js.parseStringPromise(sitemapRes.data); + const parser = new xml2js.Parser(); + const sitemap = await parser.parseStringPromise(sitemapRes.data); return { statusCode: 200, body: JSON.stringify(sitemap), }; } catch (error) { - return { - statusCode: 500, - body: JSON.stringify({ error: error.message }), - }; + // If error occurs + console.log(error.message); + if (error.code === 'ECONNABORTED') { + return { + statusCode: 500, + body: JSON.stringify({ error: 'Request timed out' }), + }; + } else { + return { + statusCode: 500, + body: JSON.stringify({ error: error.message }), + }; + } } }; From 017a1f86a68f50fbab4e6c87783a67627596fa47 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 29 Jul 2023 09:40:21 +0100 Subject: [PATCH 05/94] Fixed link to license --- src/components/misc/Footer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/misc/Footer.tsx b/src/components/misc/Footer.tsx index 432d31a..dcf61f4 100644 --- a/src/components/misc/Footer.tsx +++ b/src/components/misc/Footer.tsx @@ -41,7 +41,7 @@ const Link = styled.a` `; const Footer = (props: { isFixed?: boolean }): JSX.Element => { - const licenseUrl = 'https://github.com/lissy93/web-check/blob/main/LICENSE'; + const licenseUrl = 'https://github.com/lissy93/web-check/blob/master/LICENSE'; const authorUrl = 'https://aliciasykes.com'; const githubUrl = 'https://github.com/lissy93/web-check'; return ( From dc651a7b1e90d825f422811967e6f6f11be1f913 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 29 Jul 2023 11:38:12 +0100 Subject: [PATCH 06/94] Adds card for fetching displaying social meta tags --- api/social-tags.js | 68 +++++++++++++++++++++++++++ src/components/Results/SocialTags.tsx | 44 +++++++++++++++++ src/pages/Results.tsx | 10 ++++ 3 files changed, 122 insertions(+) create mode 100644 api/social-tags.js create mode 100644 src/components/Results/SocialTags.tsx diff --git a/api/social-tags.js b/api/social-tags.js new file mode 100644 index 0000000..9b0af39 --- /dev/null +++ b/api/social-tags.js @@ -0,0 +1,68 @@ +const axios = require('axios'); +const cheerio = require('cheerio'); + +exports.handler = async (event, context) => { + let url = event.queryStringParameters.url; + + // Check if url includes protocol + if (!url.startsWith('http://') && !url.startsWith('https://')) { + url = 'http://' + url; + } + + try { + const response = await axios.get(url); + const html = response.data; + const $ = cheerio.load(html); + + const metadata = { + // Basic meta tags + title: $('head title').text(), + description: $('meta[name="description"]').attr('content'), + keywords: $('meta[name="keywords"]').attr('content'), + canonicalUrl: $('link[rel="canonical"]').attr('href'), + + // OpenGraph Protocol + ogTitle: $('meta[property="og:title"]').attr('content'), + ogType: $('meta[property="og:type"]').attr('content'), + ogImage: $('meta[property="og:image"]').attr('content'), + ogUrl: $('meta[property="og:url"]').attr('content'), + ogDescription: $('meta[property="og:description"]').attr('content'), + ogSiteName: $('meta[property="og:site_name"]').attr('content'), + + // Twitter Cards + twitterCard: $('meta[name="twitter:card"]').attr('content'), + twitterSite: $('meta[name="twitter:site"]').attr('content'), + twitterCreator: $('meta[name="twitter:creator"]').attr('content'), + twitterTitle: $('meta[name="twitter:title"]').attr('content'), + twitterDescription: $('meta[name="twitter:description"]').attr('content'), + twitterImage: $('meta[name="twitter:image"]').attr('content'), + + // Misc + themeColor: $('meta[name="theme-color"]').attr('content'), + robots: $('meta[name="robots"]').attr('content'), + googlebot: $('meta[name="googlebot"]').attr('content'), + generator: $('meta[name="generator"]').attr('content'), + viewport: $('meta[name="viewport"]').attr('content'), + author: $('meta[name="author"]').attr('content'), + publisher: $('link[rel="publisher"]').attr('href'), + favicon: $('link[rel="icon"]').attr('href') + }; + + if (Object.keys(metadata).length === 0) { + return { + statusCode: 200, + body: JSON.stringify({ skipped: 'No metadata found' }), + }; + } + + return { + statusCode: 200, + body: JSON.stringify(metadata), + }; + } catch (error) { + return { + statusCode: 500, + body: JSON.stringify({ error: 'Failed fetching data' }), + }; + } +}; diff --git a/src/components/Results/SocialTags.tsx b/src/components/Results/SocialTags.tsx new file mode 100644 index 0000000..d22dc0c --- /dev/null +++ b/src/components/Results/SocialTags.tsx @@ -0,0 +1,44 @@ + +import { Card } from 'components/Form/Card'; +import Row from 'components/Form/Row'; +import colors from 'styles/colors'; + +const cardStyles = ` + .banner-image img { + width: 100%; + border-radius: 4px; + margin: 0.5rem 0; + } + .color-field { + border-radius: 4px; + &:hover { + color: ${colors.primary}; + } + } +`; + +const SocialTagsCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => { + const tags = props.data; + return ( + + { tags.title && } + { tags.description && } + { tags.keywords && } + { tags.canonicalUrl && } + { tags.themeColor && + Theme Color + {tags.themeColor} + } + { tags.twitterSite && + Twitter Site + {tags.twitterSite} + } + { tags.author && } + { tags.publisher && } + { tags.generator && } + { tags.ogImage &&
Banner
} +
+ ); +} + +export default SocialTagsCard; diff --git a/src/pages/Results.tsx b/src/pages/Results.tsx index 0886a2c..4ba37c2 100644 --- a/src/pages/Results.tsx +++ b/src/pages/Results.tsx @@ -46,6 +46,7 @@ import DnsServerCard from 'components/Results/DnsServer'; import TechStackCard from 'components/Results/TechStack'; import SecurityTxtCard from 'components/Results/SecurityTxt'; import ContentLinksCard from 'components/Results/ContentLinks'; +import SocialTagsCard from 'components/Results/SocialTags'; import keys from 'utils/get-keys'; import { determineAddressType, AddressType } from 'utils/address-type-checker'; @@ -341,6 +342,14 @@ const Results = (): JSX.Element => { fetchRequest: () => fetch(`${api}/security-txt?url=${address}`).then(res => parseJson(res)), }); + // Get social media previews, from a sites social meta tags + const [socialTagResults, updateSocialTagResults] = useMotherHook({ + jobId: 'social-tags', + updateLoadingJobs, + addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, + fetchRequest: () => fetch(`${api}/social-tags?url=${address}`).then(res => parseJson(res)), + }); + // Get site features from BuiltWith const [siteFeaturesResults, updateSiteFeaturesResults] = useMotherHook({ jobId: 'features', @@ -435,6 +444,7 @@ const Results = (): JSX.Element => { { id: 'hsts', title: 'HSTS Check', result: hstsResults, Component: HstsCard, refresh: updateHstsResults }, { id: 'whois', title: 'Domain Info', result: whoIsResults, Component: WhoIsCard, refresh: updateWhoIsResults }, { id: 'dns-server', title: 'DNS Server', result: dnsServerResults, Component: DnsServerCard, refresh: updateDnsServerResults }, + { id: 'social-tags', title: 'Social Tags', result: socialTagResults, Component: SocialTagsCard, refresh: updateSocialTagResults }, { id: 'linked-pages', title: 'Linked Pages', result: linkedPagesResults, Component: ContentLinksCard, refresh: updateLinkedPagesResults }, { id: 'features', title: 'Site Features', result: siteFeaturesResults, Component: SiteFeaturesCard, refresh: updateSiteFeaturesResults }, { id: 'sitemap', title: 'Pages', result: sitemapResults, Component: SitemapCard, refresh: updateSitemapResults }, From 7422d22538c5ab57ae314dc0a38788517f7413e1 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 29 Jul 2023 11:40:03 +0100 Subject: [PATCH 07/94] Adds compatibility for skipped checks for server host reasons --- src/components/misc/ProgressBar.tsx | 11 +++++++++-- src/hooks/motherOfAllHooks.ts | 22 +++++++++++----------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/components/misc/ProgressBar.tsx b/src/components/misc/ProgressBar.tsx index 1d2be06..90d1a9f 100644 --- a/src/components/misc/ProgressBar.tsx +++ b/src/components/misc/ProgressBar.tsx @@ -167,6 +167,9 @@ p { } pre { color: ${colors.danger}; + &.info { + color: ${colors.warning}; + } } `; @@ -202,7 +205,9 @@ const jobNames = [ 'sitemap', 'hsts', 'security-txt', + 'social-tags', 'linked-pages', + 'mail-server', // 'whois', 'features', 'carbon', @@ -360,7 +365,7 @@ const ProgressLoader = (props: { loadStatus: LoadingJob[], showModal: (err: Reac } }; - const showErrorModal = (name: string, state: LoadingState, timeTaken: number | undefined, error: string) => { + const showErrorModal = (name: string, state: LoadingState, timeTaken: number | undefined, error: string, isInfo?: boolean) => { const errorContent = ( Error Details for {name} @@ -368,7 +373,8 @@ const ProgressLoader = (props: { loadStatus: LoadingJob[], showModal: (err: Reac The {name} job failed with an {state} state after {timeTaken} ms. The server responded with the following error:

-
{error}
+ { /* If isInfo == true, then add .info className to pre */} +
{error}
); props.showModal(errorContent); @@ -409,6 +415,7 @@ const ProgressLoader = (props: { loadStatus: LoadingJob[], showModal: (err: Reac {(timeTaken && state !== 'loading') ? ` Took ${timeTaken} ms` : '' } { (retry && state !== 'success' && state !== 'loading') && ↻ Retry } { (error && state === 'error') && showErrorModal(name, state, timeTaken, error)}>■ Show Error } + { (error && state === 'skipped') && showErrorModal(name, state, timeTaken, error, true)}>■ Show Reason } ); }) diff --git a/src/hooks/motherOfAllHooks.ts b/src/hooks/motherOfAllHooks.ts index 8ff5ff0..fae8b16 100644 --- a/src/hooks/motherOfAllHooks.ts +++ b/src/hooks/motherOfAllHooks.ts @@ -38,21 +38,20 @@ const useMotherOfAllHooks = (params: UseIpAddressProps { return fetchRequest() .then((res: any) => { - if (!res) { + if (!res) { // No response :( + updateLoadingJobs(jobId, 'error', res.error || 'No response', reset); + } else if (res.error) { // Response returned an error message updateLoadingJobs(jobId, 'error', res.error, reset); - throw new Error('No response'); + } else if (res.skipped) { // Response returned a skipped message + updateLoadingJobs(jobId, 'skipped', res.skipped, reset); + } else { // Yay, everything went to plan :) + setResult(res); + updateLoadingJobs(jobId, 'success', '', undefined, res); } - if (res.error) { - updateLoadingJobs(jobId, 'error', res.error, reset); - throw new Error(res.error); - } - // All went to plan, set results and mark as done - setResult(res); - updateLoadingJobs(jobId, 'success', '', undefined, res); }) .catch((err) => { - // Something fucked up, log the error - updateLoadingJobs(jobId, 'error', err.error || err.message, reset); + // Something fucked up + updateLoadingJobs(jobId, 'error', err.error || err.message || 'Unknown error', reset); throw err; }) } @@ -69,6 +68,7 @@ const useMotherOfAllHooks = (params: UseIpAddressProps {}); From e3541679c2e3ae634d65f7ccdd380e279dc4f3e0 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 29 Jul 2023 11:47:03 +0100 Subject: [PATCH 08/94] Skip check if no data returned from host --- api/get-carbon.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/api/get-carbon.js b/api/get-carbon.js index c11605b..2dc6d7c 100644 --- a/api/get-carbon.js +++ b/api/get-carbon.js @@ -41,6 +41,13 @@ exports.handler = async (event, context) => { }).on('error', reject); }); + if (!carbonData.statistics || (carbonData.statistics.adjustedBytes === 0 && carbonData.statistics.energy === 0)) { + return { + statusCode: 200, + body: JSON.stringify({ skipped: 'Not enough info to get carbon data' }), + }; + } + carbonData.scanUrl = url; return { statusCode: 200, From ae00af2e2430eabe25bc970298c364d8f11c0975 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 29 Jul 2023 19:18:10 +0100 Subject: [PATCH 09/94] Adds mail security config section --- api/mail-config.js | 79 +++++++++++++++++++++++++++ src/components/Results/MailConfig.tsx | 45 +++++++++++++++ src/components/misc/ProgressBar.tsx | 3 +- src/pages/Results.tsx | 10 ++++ 4 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 api/mail-config.js create mode 100644 src/components/Results/MailConfig.tsx diff --git a/api/mail-config.js b/api/mail-config.js new file mode 100644 index 0000000..f575d40 --- /dev/null +++ b/api/mail-config.js @@ -0,0 +1,79 @@ +const dns = require('dns').promises; +const URL = require('url-parse'); + +exports.handler = async (event, context) => { + try { + let domain = event.queryStringParameters.url; + const parsedUrl = new URL(domain); + domain = parsedUrl.hostname || parsedUrl.pathname; + + // Get MX records + const mxRecords = await dns.resolveMx(domain); + + // Get TXT records + const txtRecords = await dns.resolveTxt(domain); + + // Filter for only email related TXT records (SPF, DKIM, DMARC, and certain provider verifications) + const emailTxtRecords = txtRecords.filter(record => { + const recordString = record.join(''); + return ( + recordString.startsWith('v=spf1') || + recordString.startsWith('v=DKIM1') || + recordString.startsWith('v=DMARC1') || + recordString.startsWith('protonmail-verification=') || + recordString.startsWith('google-site-verification=') || // Google Workspace + recordString.startsWith('MS=') || // Microsoft 365 + recordString.startsWith('zoho-verification=') || // Zoho + recordString.startsWith('titan-verification=') || // Titan + recordString.includes('bluehost.com') // BlueHost + ); + }); + + // Identify specific mail services + const mailServices = emailTxtRecords.map(record => { + const recordString = record.join(''); + if (recordString.startsWith('protonmail-verification=')) { + return { provider: 'ProtonMail', value: recordString.split('=')[1] }; + } else if (recordString.startsWith('google-site-verification=')) { + return { provider: 'Google Workspace', value: recordString.split('=')[1] }; + } else if (recordString.startsWith('MS=')) { + return { provider: 'Microsoft 365', value: recordString.split('=')[1] }; + } else if (recordString.startsWith('zoho-verification=')) { + return { provider: 'Zoho', value: recordString.split('=')[1] }; + } else if (recordString.startsWith('titan-verification=')) { + return { provider: 'Titan', value: recordString.split('=')[1] }; + } else if (recordString.includes('bluehost.com')) { + return { provider: 'BlueHost', value: recordString }; + } else { + return null; + } + }).filter(record => record !== null); + + // Check MX records for Yahoo + const yahooMx = mxRecords.filter(record => record.exchange.includes('yahoodns.net')); + if (yahooMx.length > 0) { + mailServices.push({ provider: 'Yahoo', value: yahooMx[0].exchange }); + } + + return { + statusCode: 200, + body: JSON.stringify({ + mxRecords, + txtRecords: emailTxtRecords, + mailServices, + }), + }; + } catch (error) { + if (error.code === 'ENOTFOUND' || error.code === 'ENODATA') { + return { + statusCode: 200, + body: JSON.stringify({ skipped: 'No mail server in use on this domain' }), + }; + } else { + return { + statusCode: 500, + body: JSON.stringify({ error: error.message }), + }; + } + } +}; diff --git a/src/components/Results/MailConfig.tsx b/src/components/Results/MailConfig.tsx new file mode 100644 index 0000000..b69c16d --- /dev/null +++ b/src/components/Results/MailConfig.tsx @@ -0,0 +1,45 @@ + +import { Card } from 'components/Form/Card'; +import Row from 'components/Form/Row'; +import Heading from 'components/Form/Heading'; +import colors from 'styles/colors'; + +const cardStyles = ``; + +const MailConfigCard = (props: {data: any, title: string, actionButtons: any }): JSX.Element => { + const mailServer = props.data; + const txtRecords = (mailServer.txtRecords || []).join('').toLowerCase() || ''; + return ( + + Mail Security Checklist + + + + + + { mailServer.mxRecords && MX Records} + { mailServer.mxRecords && mailServer.mxRecords.map((record: any) => ( + + {record.exchange} + {record.priority ? `Priority: ${record.priority}` : ''} + + )) + } + { mailServer.mailServices.length > 0 && External Mail Services} + { mailServer.mailServices && mailServer.mailServices.map((service: any) => ( + + )) + } + + { mailServer.txtRecords && Mail-related TXT Records} + { mailServer.txtRecords && mailServer.txtRecords.map((record: any) => ( + + {record} + + )) + } + + ); +} + +export default MailConfigCard; diff --git a/src/components/misc/ProgressBar.tsx b/src/components/misc/ProgressBar.tsx index 90d1a9f..9803205 100644 --- a/src/components/misc/ProgressBar.tsx +++ b/src/components/misc/ProgressBar.tsx @@ -194,6 +194,7 @@ const jobNames = [ 'hosts', 'quality', 'cookies', + 'ssl', // 'server-info', 'redirects', 'robots-txt', @@ -207,7 +208,7 @@ const jobNames = [ 'security-txt', 'social-tags', 'linked-pages', - 'mail-server', + 'mail-config', // 'whois', 'features', 'carbon', diff --git a/src/pages/Results.tsx b/src/pages/Results.tsx index 4ba37c2..5042b91 100644 --- a/src/pages/Results.tsx +++ b/src/pages/Results.tsx @@ -47,6 +47,7 @@ import TechStackCard from 'components/Results/TechStack'; import SecurityTxtCard from 'components/Results/SecurityTxt'; import ContentLinksCard from 'components/Results/ContentLinks'; import SocialTagsCard from 'components/Results/SocialTags'; +import MailConfigCard from 'components/Results/MailConfig'; import keys from 'utils/get-keys'; import { determineAddressType, AddressType } from 'utils/address-type-checker'; @@ -397,6 +398,14 @@ const Results = (): JSX.Element => { fetchRequest: () => fetch(`${api}/content-links?url=${address}`).then(res => parseJson(res)), }); + // Get mail config for server, based on DNS records + const [mailConfigResults, updateMailConfigResults] = useMotherHook({ + jobId: 'mail-config', + updateLoadingJobs, + addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, + fetchRequest: () => fetch(`${api}/mail-config?url=${address}`).then(res => parseJson(res)), + }); + /* Cancel remaining jobs after 10 second timeout */ useEffect(() => { const checkJobs = () => { @@ -443,6 +452,7 @@ const Results = (): JSX.Element => { { id: 'txt-records', title: 'TXT Records', result: txtRecordResults, Component: TxtRecordCard, refresh: updateTxtRecordResults }, { id: 'hsts', title: 'HSTS Check', result: hstsResults, Component: HstsCard, refresh: updateHstsResults }, { id: 'whois', title: 'Domain Info', result: whoIsResults, Component: WhoIsCard, refresh: updateWhoIsResults }, + { id: 'mail-config', title: 'Email Configuration', result: mailConfigResults, Component: MailConfigCard, refresh: updateMailConfigResults }, { id: 'dns-server', title: 'DNS Server', result: dnsServerResults, Component: DnsServerCard, refresh: updateDnsServerResults }, { id: 'social-tags', title: 'Social Tags', result: socialTagResults, Component: SocialTagsCard, refresh: updateSocialTagResults }, { id: 'linked-pages', title: 'Linked Pages', result: linkedPagesResults, Component: ContentLinksCard, refresh: updateLinkedPagesResults }, From f41951a73426067a8a175f6dc925c5d53f3b280e Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 29 Jul 2023 19:18:28 +0100 Subject: [PATCH 10/94] Updates docs and about page --- src/pages/About.tsx | 15 ++++++-- src/utils/docs.ts | 84 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 87 insertions(+), 12 deletions(-) diff --git a/src/pages/About.tsx b/src/pages/About.tsx index 622b3f3..384770f 100644 --- a/src/pages/About.tsx +++ b/src/pages/About.tsx @@ -6,7 +6,7 @@ import Footer from 'components/misc/Footer'; import Nav from 'components/Form/Nav'; import Button from 'components/Form/Button'; import { StyledCard } from 'components/Form/Card'; -import docs, { about, license, fairUse } from 'utils/docs'; +import docs, { about, license, fairUse, supportUs } from 'utils/docs'; const AboutContainer = styled.div` @@ -16,6 +16,7 @@ margin: 2rem auto; padding-bottom: 1rem; header { margin 1rem 0; + width: auto; } `; @@ -75,7 +76,7 @@ const Section = styled(StyledCard)` float: right; break-inside: avoid; max-width: 300px; - max-height: 28rem; + // max-height: 28rem; border-radius: 6px; clear: both; } @@ -147,6 +148,11 @@ const About = (): JSX.Element => { ))} + Support Us +
+ {supportUs.map((para, index: number) => (

))} +

+ Terms & Info
License @@ -166,6 +172,11 @@ const About = (): JSX.Element => { Privacy

Analytics are used on the demo instance (via a self-hosted Plausible instance), this only records the URL you visited but no personal data. + There's also some basic error logging (via a self-hosted GlitchTip instance), this is only used to help me fix bugs. +
+
+ Neither your IP address, browser/OS/hardware info, nor any other data will ever be collected or logged. + (You may verify this yourself, either by inspecting the source code or the using developer tools)


Support diff --git a/src/utils/docs.ts b/src/utils/docs.ts index 9b6ca99..e56127f 100644 --- a/src/utils/docs.ts +++ b/src/utils/docs.ts @@ -210,12 +210,13 @@ const docs: Doc[] = [ "This task calculates the estimated carbon footprint of a website. It's based on the amount of data being transferred and processed, and the energy usage of the servers that host and deliver the website. The larger the website and the more complex its features, the higher its carbon footprint is likely to be.", use: "From an OSINT perspective, understanding a website's carbon footprint doesn't directly provide insights into its internal workings or the organization behind it. However, it can still be valuable data in broader analyses, especially in contexts where environmental impact is a consideration. For example, it can be useful for activists, researchers, or ethical hackers who are interested in the sustainability of digital infrastructure, and who want to hold organizations accountable for their environmental impact.", resources: [ - "https://www.websitecarbon.com/", - "https://www.thegreenwebfoundation.org/", - "https://www.nature.com/articles/s41598-020-76164-y", - "https://www.sciencedirect.com/science/article/pii/S0959652620307817", + { title: 'WebsiteCarbon - Carbon Calculator', link: 'https://www.websitecarbon.com/' }, + { title: 'The Green Web Foundation', link: 'https://www.thegreenwebfoundation.org/' }, + { title: 'The Eco Friendly Web Alliance', link: 'https://ecofriendlyweb.org/' }, + { title: 'Reset.org', link: 'https://en.reset.org/' }, + { title: 'Your website is killing the planet - via Wired', link: 'https://www.wired.co.uk/article/internet-carbon-footprint' }, ], - screenshot: 'https://i.ibb.co/dmbFxjN/wc-carbon.png', + screenshot: 'https://i.ibb.co/5v6fSyw/Screenshot-from-2023-07-29-19-07-50.png', }, { id: "server-info", @@ -261,7 +262,7 @@ const docs: Doc[] = [ id: "dnssec", title: "DNS Security Extensions", description: - "Without DNSSEC, it\'s possible for MITM attackers to spoof records and lead users to phishing sites. This is because the DNS system includes no built-in methods to verify that the response to the request was not forged, or that any other part of the process wasn’t interrupted by an attacker. The DNS Security Extensions (DNSSEC) secures DNS lookups by signing your DNS records using public keys, so browsers can detect if the response has been tampered with. Another solution to this issue is DoH (DNS over HTTPS) and DoT (DNS over TLD).", + "Without DNSSEC, it's possible for MITM attackers to spoof records and lead users to phishing sites. This is because the DNS system includes no built-in methods to verify that the response to the request was not forged, or that any other part of the process wasn’t interrupted by an attacker. The DNS Security Extensions (DNSSEC) secures DNS lookups by signing your DNS records using public keys, so browsers can detect if the response has been tampered with. Another solution to this issue is DoH (DNS over HTTPS) and DoT (DNS over TLD).", use: "DNSSEC information provides insight into an organization's level of cybersecurity maturity and potential vulnerabilities, particularly around DNS spoofing and cache poisoning. If no DNS secururity (DNSSEC, DoH, DoT, etc) is implemented, this may provide an entry point for an attacker.", resources: [ "https://dnssec-analyzer.verisignlabs.com/", @@ -288,7 +289,7 @@ const docs: Doc[] = [ +'mechanism that helps protect websites against protocol downgrade attacks and ' + 'cookie hijacking. A website can be included in the HSTS preload list by ' + 'conforming to a set of requirements and then submitting itself to the list.', - use: `There are several reasons why it\'s important for a site to be HSTS enabled: + use: `There are several reasons why it's important for a site to be HSTS enabled: 1. User bookmarks or manually types http://example.com and is subject to a man-in-the-middle attacker HSTS automatically redirects HTTP requests to HTTPS for the target domain 2. Web application that is intended to be purely HTTPS inadvertently contains HTTP links or serves content over HTTP @@ -309,6 +310,7 @@ const docs: Doc[] = [ description: 'This check takes a screenshot of webpage that the requested URL / IP resolves to, and displays it.', use: 'This may be useful to see what a given website looks like, free of the constraints of your browser, IP, or location.', resources: [], + screenshot: 'https://i.ibb.co/2F0x8kP/Screenshot-from-2023-07-29-18-34-48.png', }, { id: 'dns-server', @@ -362,6 +364,60 @@ const docs: Doc[] = [ ], screenshot: 'https://i.ibb.co/tq1FT5r/Screenshot-from-2023-07-24-20-31-21.png', }, + { + id: 'linked-pages', + title: 'Linked Pages', + description: 'Displays all internal and external links found on a site, identified by the href attributes attached to anchor elements.', + use: "For site owners, this is useful for diagnosing SEO issues, improving the site structure, understanding how content is inter-connected. External links can show partnerships, dependencies, and potential reputation risks. " + + "From a security standpoint, the outbound links can help identify any potential malicious or compromised sites the website is unknowingly linking to. Analyzing internal links can aid in understanding the site's structure and potentially uncover hidden or vulnerable pages which are not intended to be public. " + + "And for an OSINT investigator, it can aid in building a comprehensive understanding of the target, uncovering related entities, resources, or even potential hidden parts of the site.", + resources: [ + { title: 'W3C Link Checker', link: 'https://validator.w3.org/checklink'}, + ], + screenshot: 'https://i.ibb.co/LtK14XR/Screenshot-from-2023-07-29-11-16-44.png', + }, + { + id: 'social-tags', + title: 'Social Tags', + description: 'Websites can include certain meta tags, that tell search engines and social media platforms what info to display. This usually includes a title, description, thumbnail, keywords, author, social accounts, etc.', + use: 'Adding this data to your site will boost SEO, and as an OSINT researcher it can be useful to understand how a given web app describes itself', + resources: [ + { title: 'SocialSharePreview.com', link: 'https://socialsharepreview.com/'}, + { title: 'The guide to social meta tags', link: 'https://css-tricks.com/essential-meta-tags-social-media/'}, + { title: 'Web.dev metadata tags', link: 'https://web.dev/learn/html/metadata/'}, + { title: 'Open Graph Protocol', link: 'https://ogp.me/'}, + { title: 'Twitter Cards', link: 'https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards'}, + { title: 'Facebook Open Graph', link: 'https://developers.facebook.com/docs/sharing/webmasters'}, + ], + screenshot: 'https://i.ibb.co/4srTT1w/Screenshot-from-2023-07-29-11-15-27.png', + }, + { + id: 'mail-config', + title: 'Email Configuration', + description: "DMARC (Domain-based Message Authentication, Reporting & Conformance): DMARC is an email authentication protocol that works with SPF and DKIM to prevent email spoofing and phishing. It allows domain owners to specify how to handle unauthenticated mail via a published policy in DNS, and provides a way for receiving mail servers to send feedback about emails' compliance to the sender. " + + "BIMI (Brand Indicators for Message Identification): BIMI is an emerging email standard that enables organizations to display a logo in their customers' email clients automatically. BIMI ties the logo to the domain's DMARC record, providing another level of visual assurance to recipients that the email is legitimate. " + + "DKIM (DomainKeys Identified Mail): DKIM is an email security standard designed to make sure that messages were not altered in transit between the sending and recipient servers. It uses digital signatures linked to the domain of the sender to verify the sender and ensure message integrity. " + + "SPF (Sender Policy Framework): SPF is an email authentication method designed to prevent email spoofing. It specifies which mail servers are authorized to send email on behalf of a domain by creating a DNS record. This helps protect against spam by providing a way for receiving mail servers to check that incoming mail from a domain comes from a host authorized by that domain's administrators.", + use: "This information is helpful for researchers as it helps assess a domain's email security posture, uncover potential vulnerabilities, and verify the legitimacy of emails for phishing detection. These details can also provide insight into the hosting environment, potential service providers, and the configuration patterns of a target organization, assisting in investigative efforts.", + resources: [ + { title: 'Intro to DMARC, DKIM, and SPF (via Cloudflare)', link: 'https://www.cloudflare.com/learning/email-security/dmarc-dkim-spf/' }, + { title: 'EasyDMARC Domain Scanner', link: 'https://easydmarc.com/tools/domain-scanner' }, + { title: 'MX Toolbox', link: 'https://mxtoolbox.com/' }, + { title: 'RFC-7208 - SPF', link: 'https://datatracker.ietf.org/doc/html/rfc7208' }, + { title: 'RFC-6376 - DKIM', link: 'https://datatracker.ietf.org/doc/html/rfc6376' }, + { title: 'RFC-7489 - DMARC', link: 'https://datatracker.ietf.org/doc/html/rfc7489' }, + { title: 'BIMI Group', link: 'https://bimigroup.org/' }, + ], + screenshot: 'https://i.ibb.co/yqhwx5G/Screenshot-from-2023-07-29-18-22-20.png', + }, + // { + // id: '', + // title: '', + // description: '', + // use: '', + // resources: [], + // screenshot: '', + // }, ]; export const about = [ @@ -409,10 +465,18 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. `; +export const supportUs = [ + "The hosted app is free to use without restriction. All the code is open source, so you're also free to deploy your own instance, or make any modifications.", + "Running web-check does cost me a small amount of money each month, so if you're finding the app useful, consider sponsoring me on GitHub if you're able to. Even just $1 or $2/month would be a huge help in supporting the ongoing project running costs.", + "Otherwise, there are other ways you can help out, like submitting or reviewing a pull request to the GitHub repo, upvoting us on Product Hunt, or by sharing with your network.", + "But don't feel obliged to do anything, as this app (and all my other projects) will always remain 100% free and open source, and I will do my best to ensure the managed instances remain up and available for as long as possible :)", +]; + export const fairUse = [ - 'Please use this tool responsibly. Do not use it for hosts you do not have permission to scan. Do not use it to attack or disrupt services.', - 'Requests are rate-limited to prevent abuse. If you need to make more bandwidth, please deploy your own instance.', - 'The hosted instance is only for demo use, as excessive use will quickly deplete my lambda function credits, making it unavailable for others and/or costing me money.', + 'Please use this tool responsibly. Do not use it for hosts you do not have permission to scan. Do not use it as part of a scheme to attack or disrupt services.', + 'Requests may be rate-limited to prevent abuse. If you need to make more bandwidth, please deploy your own instance.', + 'There is no guarantee of uptime or availability. If you need to make sure the service is available, please deploy your own instance.', + 'Please use fairly, as excessive use will quickly deplete the lambda function credits, making the service unavailable for others (and/or empty my bank account!).', ]; export default docs; From d6da8e123ea22d51019f5d737d4b796c076998b0 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 29 Jul 2023 19:18:57 +0100 Subject: [PATCH 11/94] Updates the internal/external content links section --- api/content-links.js | 12 ++++++++++++ src/components/Results/ContentLinks.tsx | 16 ++-------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/api/content-links.js b/api/content-links.js index 34e4205..f125131 100644 --- a/api/content-links.js +++ b/api/content-links.js @@ -34,6 +34,18 @@ exports.handler = async (event, context) => { const internalLinks = [...internalLinksMap.entries()].sort((a, b) => b[1] - a[1]).map(entry => entry[0]); const externalLinks = [...externalLinksMap.entries()].sort((a, b) => b[1] - a[1]).map(entry => entry[0]); + if (internalLinks.length === 0 && externalLinks.length === 0) { + return { + statusCode: 400, + body: JSON.stringify({ + skipped: 'No internal or external links found. ' + + 'This may be due to the website being dynamically rendered, using a client-side framework (like React), and without SSR enabled. ' + + 'That would mean that the static HTML returned from the HTTP request doesn\'t contain any meaningful content for Web-Check to analyze. ' + + 'You can rectify this by using a headless browser to render the page instead.', + }), + }; + } + return { statusCode: 200, body: JSON.stringify({ internal: internalLinks, external: externalLinks }), diff --git a/src/components/Results/ContentLinks.tsx b/src/components/Results/ContentLinks.tsx index d2ea0a5..87df6c1 100644 --- a/src/components/Results/ContentLinks.tsx +++ b/src/components/Results/ContentLinks.tsx @@ -43,9 +43,8 @@ const getPathName = (link: string) => { }; const ContentLinksCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => { - const { internal, external} = props.data; - console.log('Internal Links', internal); - console.log('External Links', external); + const internal = props.data.internal || []; + const external = props.data.external || []; return ( Summary @@ -71,17 +70,6 @@ const ContentLinksCard = (props: { data: any, title: string, actionButtons: any ))} )} - {/* {portData.openPorts.map((port: any) => ( - - {port} - - ) - )} -
- - Unable to establish connections to:
- {portData.failedPorts.join(', ')} -
*/}
); } From db3322856b5baacc2869b9957ccc8903d8596fe7 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 29 Jul 2023 19:42:20 +0100 Subject: [PATCH 12/94] Update homepage and about page --- src/components/Form/Card.tsx | 2 +- src/components/Form/Heading.tsx | 9 +++++++-- src/components/misc/AdditionalResources.tsx | 4 ++-- src/pages/About.tsx | 14 +++++++++++++- src/pages/Home.tsx | 11 +++++++++-- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/components/Form/Card.tsx b/src/components/Form/Card.tsx index c178d92..1721e97 100644 --- a/src/components/Form/Card.tsx +++ b/src/components/Form/Card.tsx @@ -30,7 +30,7 @@ export const Card = (props: CardProps): JSX.Element => { { actionButtons && actionButtons } - { heading && {heading} } + { heading && {heading} } {children} diff --git a/src/components/Form/Heading.tsx b/src/components/Form/Heading.tsx index 49dd715..0dd18a5 100644 --- a/src/components/Form/Heading.tsx +++ b/src/components/Form/Heading.tsx @@ -10,6 +10,7 @@ interface HeadingProps { inline?: boolean; children: React.ReactNode; id?: string; + className?: string; }; const StyledHeading = styled.h1` @@ -47,10 +48,14 @@ const StyledHeading = styled.h1` ${props => props.inline ? 'display: inline;' : '' } `; +const makeAnchor = (title: string): string => { + return title.toLowerCase().replace(/[^\w\s]|_/g, "").replace(/\s+/g, "-"); +}; + const Heading = (props: HeadingProps): JSX.Element => { - const { children, as, size, align, color, inline, id } = props; + const { children, as, size, align, color, inline, id, className } = props; return ( - + {children} ); diff --git a/src/components/misc/AdditionalResources.tsx b/src/components/misc/AdditionalResources.tsx index 663fc8f..577b790 100644 --- a/src/components/misc/AdditionalResources.tsx +++ b/src/components/misc/AdditionalResources.tsx @@ -8,7 +8,7 @@ margin: 0; padding: 1rem; display: grid; gap: 0.5rem; -grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); +grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); li a.resource-wrap { display: flex; align-items: start; @@ -192,7 +192,7 @@ const resources = [ ]; const makeLink = (resource: any, scanUrl: string | undefined): string => { - return (scanUrl && resource.searchLink) ? resource.searchLink.replaceAll('{URL}', scanUrl.replace('https://', '')) : '#'; + return (scanUrl && resource.searchLink) ? resource.searchLink.replaceAll('{URL}', scanUrl.replace('https://', '')) : resource.link; }; const AdditionalResources = (props: { url?: string }): JSX.Element => { diff --git a/src/pages/About.tsx b/src/pages/About.tsx index 384770f..58938e0 100644 --- a/src/pages/About.tsx +++ b/src/pages/About.tsx @@ -5,6 +5,7 @@ import Heading from 'components/Form/Heading'; import Footer from 'components/misc/Footer'; import Nav from 'components/Form/Nav'; import Button from 'components/Form/Button'; +import AdditionalResources from 'components/misc/AdditionalResources'; import { StyledCard } from 'components/Form/Card'; import docs, { about, license, fairUse, supportUs } from 'utils/docs'; @@ -18,6 +19,10 @@ header { margin 1rem 0; width: auto; } +section { + width: auto; + .inner-heading { display: none; } +} `; const HeaderLinkContainer = styled.nav` @@ -86,7 +91,6 @@ const makeAnchor = (title: string): string => { return title.toLowerCase().replace(/[^\w\s]|_/g, "").replace(/\s+/g, "-"); }; - const About = (): JSX.Element => { return (
@@ -148,6 +152,14 @@ const About = (): JSX.Element => { ))}
+ API Documentation +
+

// Coming soon...

+
+ + Additional Resources + + Support Us
{supportUs.map((para, index: number) => (

))} diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 33be540..bf2afba 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -179,8 +179,15 @@ const Home = (): JSX.Element => {

From 507fade2f820646b1dfb93bcd2f64195e5190ac8 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 30 Jul 2023 01:41:49 +0100 Subject: [PATCH 13/94] Improves layout for additional resources section --- src/components/misc/AdditionalResources.tsx | 51 +++++++++++++-------- src/utils/docs.ts | 12 ++--- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/components/misc/AdditionalResources.tsx b/src/components/misc/AdditionalResources.tsx index 577b790..4f3b50c 100644 --- a/src/components/misc/AdditionalResources.tsx +++ b/src/components/misc/AdditionalResources.tsx @@ -11,9 +11,10 @@ gap: 0.5rem; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); li a.resource-wrap { display: flex; + flex-direction: column; align-items: start; gap: 0.25rem; - padding: 0.25rem; + padding: 0.25rem 0.5rem; background: ${colors.background}; border-radius: 8px; text-decoration: none; @@ -37,27 +38,32 @@ li a.resource-wrap { } } img { - width: 4rem; + width: 2.5rem; border-radius: 4px; margin: 0.25rem 0.1rem 0.1rem 0.1rem; } +p, a { + margin: 0; +} +a.resource-link { + color: ${colors.primary}; + opacity: 0.75; + font-size: 0.9rem; + transition: all 0.2s ease-in-out; +} +.resource-title { + font-weight: bold; +} +.resource-lower { + display: flex; + align-items: center; + gap: 0.5rem; +} .resource-details { max-width: 20rem; display: flex; flex-direction: column; gap: 0.1rem; - p, a { - margin: 0; - } - a.resource-link { - color: ${colors.primary}; - opacity: 0.75; - font-size: 0.9rem; - transition: all 0.2s ease-in-out; - } - .resource-title { - font-weight: bold; - } .resource-description { color: ${colors.textColorSecondary}; font-size: 0.9rem; @@ -155,6 +161,13 @@ const resources = [ description: 'Checks the performance, accessibility and SEO of a page on mobile + desktop.', searchLink: 'https://developers.google.com/speed/pagespeed/insights/?url={URL}', }, + { + title: 'Built With', + link: 'https://builtwith.com/', + icon: 'https://i.ibb.co/5LXBDfD/Built-with.png', + description: 'View the tech stack of a website', + searchLink: 'https://builtwith.com/{URL}', + }, { title: 'DNS Dumpster', link: 'https://dnsdumpster.com/', @@ -203,12 +216,14 @@ const AdditionalResources = (props: { url?: string }): JSX.Element => { return (
  • - - +
    + +
    +

    {resource.description}

    +
    +
  • ); diff --git a/src/utils/docs.ts b/src/utils/docs.ts index e56127f..fc735b2 100644 --- a/src/utils/docs.ts +++ b/src/utils/docs.ts @@ -322,14 +322,14 @@ const docs: Doc[] = [ { id: 'tech-stack', title: 'Tech Stack', - description: 'Checks what technologies a site is built with.' + description: 'Checks what technologies a site is built with. ' + 'This is done by fetching and parsing the site, then comparing it against a bit list of RegEx maintained by Wappalyzer to identify the unique fingerprints that different technologies leave.', use: 'Identifying a website\'s tech stack aids in evaluating its security by exposing potential vulnerabilities, ' + 'informs competitive analyses and development decisions, and can guide tailored marketing strategies. ' + 'Ethical application of this knowledge is crucial to avoid harmful activities like data theft or unauthorized intrusion.', resources: [ - 'https://builtwith.com/', - 'https://github.com/wappalyzer/wappalyzer/tree/master/src/technologies' + { title: 'Wappalyzer fingerprints', link: 'https://github.com/wappalyzer/wappalyzer/tree/master/src/technologies'}, + { title: 'BuiltWith - Check what tech a site is using', link: 'https://builtwith.com/'}, ], }, { @@ -338,9 +338,9 @@ const docs: Doc[] = [ description: 'This job finds and parses a site\'s listed sitemap. This file lists public sub-pages on the site, which the author wishes to be crawled by search engines. Sitemaps help with SEO, but are also useful for seeing all a sites public content at a glance.', use: 'Understand the structure of a site\'s public-facing content, and for site-owners, check that you\'re site\'s sitemap is accessible, parsable and contains everything you wish it to.', resources: [ - 'https://developers.google.com/search/docs/crawling-indexing/sitemaps/overview', - 'https://www.sitemaps.org/protocol.html', - 'https://www.conductor.com/academy/xml-sitemap/', + { title: 'Learn about Sitemaps', link: 'https://developers.google.com/search/docs/crawling-indexing/sitemaps/overview'}, + { title: 'Sitemap XML spec', link: 'https://www.sitemaps.org/protocol.html'}, + { title: 'Sitemap tutorial', link: 'https://www.conductor.com/academy/xml-sitemap/'}, ], screenshot: 'https://i.ibb.co/GtrCQYq/Screenshot-from-2023-07-21-12-28-38.png', }, From 57fadde151fea6c74c97a16c08969a1d4cfc7ed6 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 5 Aug 2023 10:32:53 +0100 Subject: [PATCH 14/94] Adds smoothe scroll --- src/index.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/index.css b/src/index.css index 5ab1c57..e0502ea 100644 --- a/src/index.css +++ b/src/index.css @@ -5,6 +5,10 @@ font-style: normal; } +html { + scroll-behavior: smooth; +} + body { margin: 0; font-family: 'PTMono', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', From c46fed5ebba6ed521560d49a1852bda5be270235 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 5 Aug 2023 10:33:05 +0100 Subject: [PATCH 15/94] Updates docs --- src/pages/About.tsx | 38 +++++++++---- src/utils/docs.ts | 136 +++++++++++++++++++++----------------------- 2 files changed, 92 insertions(+), 82 deletions(-) diff --git a/src/pages/About.tsx b/src/pages/About.tsx index 58938e0..922e00a 100644 --- a/src/pages/About.tsx +++ b/src/pages/About.tsx @@ -9,7 +9,6 @@ import AdditionalResources from 'components/misc/AdditionalResources'; import { StyledCard } from 'components/Form/Card'; import docs, { about, license, fairUse, supportUs } from 'utils/docs'; - const AboutContainer = styled.div` width: 95vw; max-width: 1000px; @@ -38,6 +37,9 @@ const Section = styled(StyledCard)` margin-bottom: 2rem; overflow: clip; max-height: 100%; + section { + clear: both; + } h3 { font-size: 1.5rem; } @@ -77,13 +79,25 @@ const Section = styled(StyledCard)` } } } - .screenshot { - float: right; - break-inside: avoid; - max-width: 300px; - // max-height: 28rem; - border-radius: 6px; + .example-screenshot { + float: right; + display: inline-flex; + flex-direction: column; clear: both; + max-width: 300px; + img { + float: right; + break-inside: avoid; + max-width: 300px; + // max-height: 30rem; + border-radius: 6px; + clear: both; + } + figcaption { + font-size: 0.8rem; + text-align: center; + opacity: 0.7; + } } `; @@ -123,9 +137,13 @@ const About = (): JSX.Element => { {docs.map((section, sectionIndex: number) => (
    + { sectionIndex > 0 &&
    } {section.title} - {section.screenshot && - {`Example + {section.screenshot && +
    + {`Example +
    Fig.{sectionIndex + 1} - Example of {section.title}
    +
    } {section.description && <> Description @@ -147,7 +165,7 @@ const About = (): JSX.Element => { ))} } - { sectionIndex < docs.length - 1 &&
    } + {/* { sectionIndex < docs.length - 1 &&
    } */}
    ))}
    diff --git a/src/utils/docs.ts b/src/utils/docs.ts index fc735b2..0913217 100644 --- a/src/utils/docs.ts +++ b/src/utils/docs.ts @@ -12,26 +12,26 @@ const docs: Doc[] = [ id: "get-ip", title: "IP Info", description: - "The IP Address task involves mapping the user provided URL to its corresponding IP address through a process known as Domain Name System (DNS) resolution. An IP address is a unique identifier given to every device on the Internet, and when paired with a domain name, it allows for accurate routing of online requests and responses.", - use: "Identifying the IP address of a domain can be incredibly valuable for OSINT purposes. This information can aid in creating a detailed map of a target's network infrastructure, pinpointing the physical location of a server, identifying the hosting service, and even discovering other domains that are hosted on the same IP address. In cybersecurity, it's also useful for tracking the sources of attacks or malicious activities.", + "An IP address (Internet Protocol address) is a numerical label assigned to each device connected to a network / the internet. The IP associated with a given domain can be found by querying the Domain Name System (DNS) for the domain's A (address) record.", + use: "Finding the IP of a given server is the first step to conducting further investigations, as it allows us to probe the server for additional info. Including creating a detailed map of a target's network infrastructure, pinpointing the physical location of a server, identifying the hosting service, and even discovering other domains that are hosted on the same IP address.", resources: [ - "https://en.wikipedia.org/wiki/IP_address", - "https://tools.ietf.org/html/rfc791", - "https://www.cloudflare.com/learning/dns/what-is-dns/", - "https://www.whois.com/whois-lookup", + { title: 'Understanding IP Addresses', link: 'https://www.digitalocean.com/community/tutorials/understanding-ip-addresses-subnets-and-cidr-notation-for-networking'}, + { title: 'IP Addresses - Wiki', link: 'https://en.wikipedia.org/wiki/IP_address'}, + { title: 'RFC-791 Internet Protocol', link: 'https://tools.ietf.org/html/rfc791'}, + { title: 'whatismyipaddress.com', link: 'https://whatismyipaddress.com/'}, ], }, { id: "ssl", title: "SSL Chain", description: - "The SSL task involves checking if the site has a valid Secure Sockets Layer (SSL) certificate. SSL is a protocol for establishing authenticated and encrypted links between networked computers. It's commonly used for securing communications over the internet, such as web browsing sessions, email transmissions, and more. In this task, we reach out to the server and initiate a SSL handshake. If successful, we gather details about the SSL certificate presented by the server.", + "SSL certificates are digital certificates that authenticate the identity of a website or server, enable secure encrypted communication (HTTPS), and establish trust between clients and servers. A valid SSL certificate is required for a website to be able to use the HTTPS protocol, and encrypt user + site data in transit. SSL certificates are issued by Certificate Authorities (CAs), which are trusted third parties that verify the identity and legitimacy of the certificate holder.", use: "SSL certificates not only provide the assurance that data transmission to and from the website is secure, but they also provide valuable OSINT data. Information from an SSL certificate can include the issuing authority, the domain name, its validity period, and sometimes even organization details. This can be useful for verifying the authenticity of a website, understanding its security setup, or even for discovering associated subdomains or other services.", resources: [ - "https://en.wikipedia.org/wiki/Transport_Layer_Security", - "https://tools.ietf.org/html/rfc8446", - "https://letsencrypt.org/docs/", - "https://www.sslshopper.com/ssl-checker.html", + { title: 'TLS - Wiki', link: 'https://en.wikipedia.org/wiki/Transport_Layer_Security'}, + { title: 'What is SSL (via Cloudflare learning)', link: 'https://www.cloudflare.com/learning/ssl/what-is-ssl/'}, + { title: 'RFC-8446 - TLS', link: 'https://tools.ietf.org/html/rfc8446'}, + { title: 'SSL Checker', link: 'https://www.sslshopper.com/ssl-checker.html'}, ], screenshot: 'https://i.ibb.co/kB7LsV1/wc-ssl.png', }, @@ -39,13 +39,13 @@ const docs: Doc[] = [ id: "dns", title: "DNS Records", description: - "The DNS Records task involves querying the Domain Name System (DNS) for records associated with the target domain. DNS is a system that translates human-readable domain names into IP addresses that computers use to communicate. Various types of DNS records exist, including A (address), MX (mail exchange), NS (name server), CNAME (canonical name), and TXT (text), among others.", + "This task involves looking up the DNS records associated with a specific domain. DNS is a system that translates human-readable domain names into IP addresses that computers use to communicate. Various types of DNS records exist, including A (address), MX (mail exchange), NS (name server), CNAME (canonical name), and TXT (text), among others.", use: "Extracting DNS records can provide a wealth of information in an OSINT investigation. For example, A and AAAA records can disclose IP addresses associated with a domain, potentially revealing the location of servers. MX records can give clues about a domain's email provider. TXT records are often used for various administrative purposes and can sometimes inadvertently leak internal information. Understanding a domain's DNS setup can also be useful in understanding how its online infrastructure is built and managed.", resources: [ - "https://en.wikipedia.org/wiki/List_of_DNS_record_types", - "https://tools.ietf.org/html/rfc1035", - "https://mxtoolbox.com/DNSLookup.aspx", - "https://www.dnswatch.info/", + { title: 'What are DNS records? (via Cloudflare learning)', link: 'https://www.cloudflare.com/learning/dns/dns-records/'}, + { title: 'DNS Record Types', link: 'https://en.wikipedia.org/wiki/List_of_DNS_record_types'}, + { title: 'RFC-1035 - DNS', link: 'https://tools.ietf.org/html/rfc1035'}, + { title: 'DNS Lookup (via MxToolbox)', link: 'https://mxtoolbox.com/DNSLookup.aspx'}, ], screenshot: 'https://i.ibb.co/7Q1kMwM/wc-dns.png', }, @@ -54,12 +54,12 @@ const docs: Doc[] = [ title: "Cookies", description: "The Cookies task involves examining the HTTP cookies set by the target website. Cookies are small pieces of data stored on the user's computer by the web browser while browsing a website. They hold a modest amount of data specific to a particular client and website, such as site preferences, the state of the user's session, or tracking information.", - use: "Cookies provide a wealth of information in an OSINT investigation. They can disclose information about how the website tracks and interacts with its users. For instance, session cookies can reveal how user sessions are managed, and tracking cookies can hint at what kind of tracking or analytics frameworks are being used. Additionally, examining cookie policies and practices can offer insights into the site's security settings and compliance with privacy regulations.", + use: "Cookies can disclose information about how the website tracks and interacts with its users. For instance, session cookies can reveal how user sessions are managed, and tracking cookies can hint at what kind of tracking or analytics frameworks are being used. Additionally, examining cookie policies and practices can offer insights into the site's security settings and compliance with privacy regulations.", resources: [ - "https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies", - "https://www.cookiepro.com/knowledge/what-is-a-cookie/", - "https://owasp.org/www-community/controls/SecureFlag", - "https://tools.ietf.org/html/rfc6265", + { title: 'HTTP Cookie Docs (Mozilla)', link: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies' }, + { title: 'What are Cookies (via Cloudflare Learning)', link: 'https://www.cloudflare.com/learning/privacy/what-are-cookies/' }, + { title: 'Testing for Cookie Attributes (OWASP)', link: 'https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/06-Session_Management_Testing/02-Testing_for_Cookies_Attributes' }, + { title: 'RFC-6265 - Coolies', link: 'https://tools.ietf.org/html/rfc6265' }, ], screenshot: 'https://i.ibb.co/TTQ6DtP/wc-cookies.png', }, @@ -67,13 +67,13 @@ const docs: Doc[] = [ id: "robots-txt", title: "Crawl Rules", description: - "The Crawl Rules task is focused on retrieving and interpreting the 'robots.txt' file from the target website. This text file is part of the Robots Exclusion Protocol (REP), a group of web standards that regulate how robots crawl the web, access and index content, and serve that content up to users. The file indicates which parts of the site the website owner doesn't want to be accessed by web crawler bots.", - use: "The 'robots.txt' file can provide valuable information for an OSINT investigation. It often discloses the directories and pages that the site owner doesn't want to be indexed, potentially because they contain sensitive information. Moreover, it might reveal the existence of otherwise hidden or unlinked directories. Additionally, understanding crawl rules may offer insights into a website's SEO strategies.", + "Robots.txt is a file found (usually) at the root of a domain, and is used to implement the Robots Exclusion Protocol (REP) to indicate which pages should be ignored by which crawlers and bots. It's good practice to avoid search engine crawlers from over-loading your site, but should not be used to keep pages out of search results (use the noindex meta tag or header instead).", + use: "It's often useful to check the robots.txt file during an investigation, as it can sometimes disclose the directories and pages that the site owner doesn't want to be indexed, potentially because they contain sensitive information, or reveal the existence of otherwise hidden or unlinked directories. Additionally, understanding crawl rules may offer insights into a website's SEO strategies.", resources: [ - "https://developers.google.com/search/docs/advanced/robots/intro", - "https://www.robotstxt.org/robotstxt.html", - "https://moz.com/learn/seo/robotstxt", - "https://en.wikipedia.org/wiki/Robots_exclusion_standard", + { title: 'Google Search Docs - Robots.txt', link: 'https://developers.google.com/search/docs/advanced/robots/intro' }, + { title: 'Learn about robots.txt (via Moz.com)', link: 'https://moz.com/learn/seo/robotstxt' }, + { title: 'RFC-9309 - Robots Exclusion Protocol', link: 'https://datatracker.ietf.org/doc/rfc9309/' }, + { title: 'Robots.txt - wiki', link: 'https://en.wikipedia.org/wiki/Robots_exclusion_standard' }, ], screenshot: 'https://i.ibb.co/KwQCjPf/wc-robots.png', }, @@ -84,10 +84,10 @@ const docs: Doc[] = [ "The Headers task involves extracting and interpreting the HTTP headers sent by the target website during the request-response cycle. HTTP headers are key-value pairs sent at the start of an HTTP response, or before the actual data. Headers contain important directives for how to handle the data being transferred, including cache policies, content types, encoding, server information, security policies, and more.", use: "Analyzing HTTP headers can provide significant insights in an OSINT investigation. Headers can reveal specific server configurations, chosen technologies, caching directives, and various security settings. This information can help to determine a website's underlying technology stack, server-side security measures, potential vulnerabilities, and general operational practices.", resources: [ - "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers", - "https://tools.ietf.org/html/rfc7231#section-3.2", - "https://www.w3schools.com/tags/ref_httpheaders.asp", - "https://owasp.org/www-project-secure-headers/", + { title: 'HTTP Headers - Docs', link: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers' }, + { title: 'RFC-7231 Section 7 - Headers', link: 'https://datatracker.ietf.org/doc/html/rfc7231#section-7' }, + { title: 'List of header response fields', link: 'https://en.wikipedia.org/wiki/List_of_HTTP_header_fields' }, + { title: 'OWASP Secure Headers Project', link: 'https://owasp.org/www-project-secure-headers/' }, ], screenshot: 'https://i.ibb.co/t3xcwP1/wc-headers.png', }, @@ -95,13 +95,15 @@ const docs: Doc[] = [ id: "quality", title: "Quality Metrics", description: - "The Headers task involves extracting and interpreting the HTTP headers sent by the target website during the request-response cycle. HTTP headers are key-value pairs sent at the start of an HTTP response, or before the actual data. Headers contain important directives for how to handle the data being transferred, including cache policies, content types, encoding, server information, security policies, and more.", - use: "Analyzing HTTP headers can provide significant insights in an OSINT investigation. Headers can reveal specific server configurations, chosen technologies, caching directives, and various security settings. This information can help to determine a website's underlying technology stack, server-side security measures, potential vulnerabilities, and general operational practices.", + "Using Lighthouse, the Quality Metrics task measures the performance, accessibility, best practices, and SEO of the target website. This returns a simple checklist of 100 core metrics, along with a score for each category, to gauge the overall quality of a given site.", + use: "Useful for assessing a site's technical health, SEO issues, identify vulnerabilities, and ensure compliance with standards.", resources: [ - "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers", - "https://tools.ietf.org/html/rfc7231#section-3.2", - "https://www.w3schools.com/tags/ref_httpheaders.asp", - "https://owasp.org/www-project-secure-headers/", + { title: 'Lighthouse Docs', link: 'https://developer.chrome.com/docs/lighthouse/' }, + { title: 'Google Page Speed Tools', link: 'https://developers.google.com/speed' }, + { title: 'W3 Accessibility Tools', link: 'https://www.w3.org/WAI/test-evaluate/' }, + { title: 'Google Search Console', link: 'https://search.google.com/search-console' }, + { title: 'SEO Checker', link: 'https://www.seobility.net/en/seocheck/' }, + { title: 'PWA Builder', link: 'https://www.pwabuilder.com/' }, ], screenshot: 'https://i.ibb.co/Kqg8rx7/wc-quality.png', }, @@ -109,13 +111,11 @@ const docs: Doc[] = [ id: "location", title: "Server Location", description: - "The Server Location task determines the physical location of a server hosting a website based on its IP address. The geolocation data typically includes the country, region, and often city where the server is located. The task also provides additional contextual information such as the official language, currency, and flag of the server's location country.", - use: "In the realm of OSINT, server location information can be very valuable. It can give an indication of the possible jurisdiction that laws the data on the server falls under, which can be important in legal or investigative contexts. The server location can also hint at the target audience of a website and reveal inconsistencies that could suggest the use of hosting or proxy services to disguise the actual location.", + "The Server Location task determines the physical location of the server hosting a given website based on its IP address. This is done by looking up the IP in a location database, which maps the IP to a lat + long of known data centers and ISPs. From the latitude and longitude, it's then possible to show additional contextual info, like a pin on the map, along with address, flag, time zone, currency, etc.", + use: "Knowing the server location is a good first step in better understanding a website. For site owners this aids in optimizing content delivery, ensuring compliance with data residency requirements, and identifying potential latency issues that may impact user experience in specific geographical regions. And for security researcher, assess the risk posed by specific regions or jurisdictions regarding cyber threats and regulations.", resources: [ - "https://en.wikipedia.org/wiki/Geolocation_software", - "https://www.iplocation.net/", - "https://www.cloudflare.com/learning/cdn/glossary/geolocation/", - "https://developers.google.com/maps/documentation/geolocation/intro", + { title: 'IP Locator', link: 'https://geobytes.com/iplocator/' }, + { title: 'Internet Geolocation - Wiki', link: 'https://en.wikipedia.org/wiki/Internet_geolocation' }, ], screenshot: 'https://i.ibb.co/cXH2hfR/wc-location.png', }, @@ -123,13 +123,13 @@ const docs: Doc[] = [ id: "hosts", title: "Associated Hosts", description: - "This task involves identifying and listing all domains and subdomains (hostnames) that are associated with the website's primary domain. This process often involves DNS enumeration to discover any linked domains and hostnames.", - use: "In OSINT investigations, understanding the full scope of a target's web presence is critical. Associated domains could lead to uncovering related projects, backup sites, development/test sites, or services linked to the main site. These can sometimes provide additional information or potential security vulnerabilities. A comprehensive list of associated domains and hostnames can also give an overview of the organization's structure and online footprint.", + "This task involves identifying and listing all domains and subdomains (hostnames) that are associated with the website's primary domain. This process often involves DNS enumeration to discover any linked domains and hostnames, as well as looking at known DNS records.", + use: "During an investigation, understanding the full scope of a target's web presence is critical. Associated domains could lead to uncovering related projects, backup sites, development/test sites, or services linked to the main site. These can sometimes provide additional information or potential security vulnerabilities. A comprehensive list of associated domains and hostnames can also give an overview of the organization's structure and online footprint.", resources: [ - "https://en.wikipedia.org/wiki/Domain_Name_System", - "https://resources.infosecinstitute.com/topic/dns-enumeration-pentest/", - "https://subdomainfinder.c99.nl/", - "https://securitytrails.com/blog/top-dns-enumeration-tools", + { title: 'DNS Enumeration - Wiki', link: 'https://en.wikipedia.org/wiki/DNS_enumeration' }, + { title: 'OWASP - Enumerate Applications on Webserver', link: 'https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/01-Information_Gathering/04-Enumerate_Applications_on_Webserver' }, + { title: 'DNS Enumeration - DNS Dumpster', link: 'https://dnsdumpster.com/' }, + { title: 'Subdomain Finder', link: 'https://subdomainfinder.c99.nl/' }, ], screenshot: 'https://i.ibb.co/25j1sT7/wc-hosts.png', }, @@ -138,12 +138,11 @@ const docs: Doc[] = [ title: "Redirect Chain", description: "This task traces the sequence of HTTP redirects that occur from the original URL to the final destination URL. An HTTP redirect is a response with a status code that advises the client to go to another URL. Redirects can occur for several reasons, such as URL normalization (directing to the www version of the site), enforcing HTTPS, URL shorteners, or forwarding users to a new site location.", - use: "Understanding the redirect chain can be crucial for several reasons. From a security perspective, long or complicated redirect chains can be a sign of potential security risks, such as unencrypted redirects in the chain. Additionally, redirects can impact website performance and SEO, as each redirect introduces additional round-trip-time (RTT). For OSINT, understanding the redirect chain can help identify relationships between different domains or reveal the use of certain technologies or hosting providers.", + use: "Understanding the redirect chain can be useful for several reasons. From a security perspective, long or complicated redirect chains can be a sign of potential security risks, such as unencrypted redirects in the chain. Additionally, redirects can impact website performance and SEO, as each redirect introduces additional round-trip-time (RTT). For OSINT, understanding the redirect chain can help identify relationships between different domains or reveal the use of certain technologies or hosting providers.", resources: [ - "https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections", - "https://en.wikipedia.org/wiki/URL_redirection", - "https://www.screamingfrog.co.uk/server-response-codes/", - "https://ahrefs.com/blog/301-redirects/", + { title: 'HTTP Redirects - MDN', link: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections' }, + { title: 'URL Redirection - Wiki', link: 'https://en.wikipedia.org/wiki/URL_redirection' }, + { title: '301 Redirects explained', link: 'https://ahrefs.com/blog/301-redirects/' }, ], screenshot: 'https://i.ibb.co/hVVrmwh/wc-redirects.png', }, @@ -151,27 +150,22 @@ const docs: Doc[] = [ id: "txt-records", title: "TXT Records", description: - "TXT records are a type of Domain Name Service (DNS) record that provides text information to sources outside your domain. They can be used for a variety of purposes, such as verifying domain ownership, ensuring email security, and even preventing unauthorized changes to your website.", - use: "In the context of OSINT, TXT records can be a valuable source of information. They may reveal details about the domain's email configuration, the use of specific services like Google Workspace or Microsoft 365, or security measures in place such as SPF and DKIM. Understanding these details can give an insight into the technologies used by the organization, their email security practices, and potential vulnerabilities.", + "TXT records are a type of DNS record that provides text information to sources outside your domain. They can be used for a variety of purposes, such as verifying domain ownership, ensuring email security, and even preventing unauthorized changes to your website.", + use: "The TXT records often reveal which external services and technologies are being used with a given domain. They may reveal details about the domain's email configuration, the use of specific services like Google Workspace or Microsoft 365, or security measures in place such as SPF and DKIM. Understanding these details can give an insight into the technologies used by the organization, their email security practices, and potential vulnerabilities.", resources: [ - "https://www.cloudflare.com/learning/dns/dns-records/dns-txt-record/", - "https://en.wikipedia.org/wiki/TXT_record", - "https://tools.ietf.org/html/rfc7208", - "https://dmarc.org/wiki/FAQ", + { title: 'TXT Records (via Cloudflare Learning)', link: 'https://www.cloudflare.com/learning/dns/dns-records/dns-txt-record/' }, + { title: 'TXT Records - Wiki', link: 'https://en.wikipedia.org/wiki/TXT_record' }, + { title: 'RFC-1464 - TXT Records', link: 'https://datatracker.ietf.org/doc/html/rfc1464' }, + { title: 'TXT Record Lookup (via MxToolbox)', link: 'https://mxtoolbox.com/TXTLookup.aspx' }, ], screenshot: 'https://i.ibb.co/wyt21QN/wc-txt-records.png', }, { id: "status", title: "Server Status", - description: - "TXT records are a type of Domain Name Service (DNS) record that provides text information to sources outside your domain. They can be used for a variety of purposes, such as verifying domain ownership, ensuring email security, and even preventing unauthorized changes to your website.", - use: "In the context of OSINT, TXT records can be a valuable source of information. They may reveal details about the domain's email configuration, the use of specific services like Google Workspace or Microsoft 365, or security measures in place such as SPF and DKIM. Understanding these details can give an insight into the technologies used by the organization, their email security practices, and potential vulnerabilities.", + description: "Checks if a server is online and responding to requests.", + use: "", resources: [ - "https://www.cloudflare.com/learning/dns/dns-records/dns-txt-record/", - "https://en.wikipedia.org/wiki/TXT_record", - "https://tools.ietf.org/html/rfc7208", - "https://dmarc.org/wiki/FAQ", ], screenshot: 'https://i.ibb.co/V9CNLBK/wc-status.png', }, @@ -180,12 +174,10 @@ const docs: Doc[] = [ title: "Open Ports", description: "Open ports on a server are endpoints of communication which are available for establishing connections with clients. Each port corresponds to a specific service or protocol, such as HTTP (port 80), HTTPS (port 443), FTP (port 21), etc. The open ports on a server can be determined using techniques such as port scanning.", - use: "In the context of OSINT, knowing which ports are open on a server can provide valuable information about the services running on that server. This information can be useful for understanding the potential vulnerabilities of the system, or for understanding the nature of the services the server is providing. For example, a server with port 22 open (SSH) might be used for remote administration, while a server with port 443 open is serving HTTPS traffic.", + use: "Knowing which ports are open on a server can provide information about the services running on that server, useful for understanding the potential vulnerabilities of the system, or for understanding the nature of the services the server is providing.", resources: [ - "https://www.netwrix.com/port_scanning.html", - "https://nmap.org/book/man-port-scanning-basics.html", - "https://www.cloudflare.com/learning/ddos/glossary/open-port/", - "https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers", + { title: 'List of TCP & UDP Port Numbers', link: 'https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers' }, + { title: 'NMAP - Port Scanning Basics', link: 'https://nmap.org/book/man-port-scanning-basics.html' }, ], screenshot: 'https://i.ibb.co/F8D1hmf/wc-ports.png', }, From 42eea33809ce832856e1ef1bf92e9f40f7621116 Mon Sep 17 00:00:00 2001 From: Mounir Date: Sun, 6 Aug 2023 16:36:26 +0200 Subject: [PATCH 16/94] fix ip adress docs --- .github/README.md | 2 +- .github/screenshots/wc_ip-adress.png | Bin 0 -> 74616 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 .github/screenshots/wc_ip-adress.png diff --git a/.github/README.md b/.github/README.md index 279685d..89165be 100644 --- a/.github/README.md +++ b/.github/README.md @@ -42,7 +42,7 @@ None of this is hard to find with a series of basic curl commands, or a combinat
    IP Address - + ###### Description The IP Address task involves mapping the user provided URL to its corresponding IP address through a process known as Domain Name System (DNS) resolution. An IP address is a unique identifier given to every device on the Internet, and when paired with a domain name, it allows for accurate routing of online requests and responses. diff --git a/.github/screenshots/wc_ip-adress.png b/.github/screenshots/wc_ip-adress.png new file mode 100644 index 0000000000000000000000000000000000000000..24104e54cc1c8b315c37c89311eb35a2b65a66e5 GIT binary patch literal 74616 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 AS^xk5 literal 0 HcmV?d00001 From 30c5dbb89867cae133d4e302d483038f09405401 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 6 Aug 2023 22:03:48 +0100 Subject: [PATCH 17/94] Adds dotenv for using environmental variables in the node server --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 1720e2f..2169a14 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "axios": "^1.4.0", "cheerio": "^1.0.0-rc.12", "chrome-aws-lambda": "^10.1.0", + "dotenv": "^16.3.1", "flatted": "^3.2.7", "follow-redirects": "^1.15.2", "got": "^13.0.0", From 127db45247ffc87419c7851bb186f70406e654af Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 6 Aug 2023 22:04:25 +0100 Subject: [PATCH 18/94] Ignore non-files, and use port from env var --- server.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/server.js b/server.js index 2dd156c..2973b91 100644 --- a/server.js +++ b/server.js @@ -2,13 +2,20 @@ const express = require('express'); const awsServerlessExpress = require('aws-serverless-express'); const fs = require('fs'); const path = require('path'); +require('dotenv').config(); const app = express(); -// Read the '/api' directory and import each lambda function const handlers = {}; -fs.readdirSync(path.join(__dirname, '/api')).forEach(file => { - const route = `/api/${file.split('.')[0]}`; // remove .js extension + +const dirPath = path.join(__dirname, '/api'); + +const fileNames = fs.readdirSync(dirPath, { withFileTypes: true }) + .filter(dirent => dirent.isFile() && dirent.name.endsWith('.js')) + .map(dirent => dirent.name); + +fileNames.forEach(file => { + const route = `/api/${file.split('.')[0]}`; const handler = require(path.join(__dirname, '/api', file)).handler; handlers[route] = handler; @@ -51,10 +58,11 @@ app.get('/api', async (req, res) => { }); // Create serverless express server +const port = process.env.API_PORT || 3001; const server = awsServerlessExpress .createServer(app) -.listen(3001, () => { - console.log('Listening on port 3001'); +.listen(port, () => { + console.log(`Server is running on port ${port}`); }); exports.handler = (event, context) => { From 65ff004b63b81b1df6c1178e3206757d0b4db893 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 6 Aug 2023 22:04:57 +0100 Subject: [PATCH 19/94] Fix missing url param when called by server direct --- api/tech-stack.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/tech-stack.js b/api/tech-stack.js index 788a8f6..596ba52 100644 --- a/api/tech-stack.js +++ b/api/tech-stack.js @@ -26,7 +26,7 @@ const analyze = async (url) => { exports.handler = async (event, context, callback) => { // Validate URL parameter - if (!event.queryStringParameters || !event.queryStringParameters.url) { + if (!(event.queryStringParameters || event.query).url) { return { statusCode: 400, body: JSON.stringify({ error: 'Missing url parameter' }), From f0ff33e081a5a24d1d470ea4d497b39f1ce6ebe9 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 6 Aug 2023 22:05:14 +0100 Subject: [PATCH 20/94] Starts making middleware functionality --- api/_common/middleware.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 api/_common/middleware.js diff --git a/api/_common/middleware.js b/api/_common/middleware.js new file mode 100644 index 0000000..61eca0e --- /dev/null +++ b/api/_common/middleware.js @@ -0,0 +1,29 @@ +const normalizeUrl = (url) => { + // Normalizing logic here + return url.startsWith('http') ? url : `http://${url}`; +}; + +const commonMiddleware = (handler) => { + return async (event, context, callback) => { + try { + const rawUrl = event.queryStringParameters.url; + const url = normalizeUrl(rawUrl); + + // Call the specific handler with the normalized URL + const response = await handler(url, event, context); + + callback(null, { + statusCode: 200, + body: JSON.stringify(response), + }); + } catch (error) { + console.log(error); + callback(null, { + statusCode: 500, + body: JSON.stringify({ error: error.message }), + }); + } + }; +}; + +module.exports = commonMiddleware; From 85af5f932702f513994aceff0776fad5fdfcbed6 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Wed, 9 Aug 2023 22:31:47 +0100 Subject: [PATCH 21/94] Updated middleware to handle various response shapes --- api/_common/middleware.js | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/api/_common/middleware.js b/api/_common/middleware.js index 61eca0e..434c498 100644 --- a/api/_common/middleware.js +++ b/api/_common/middleware.js @@ -1,21 +1,31 @@ const normalizeUrl = (url) => { - // Normalizing logic here - return url.startsWith('http') ? url : `http://${url}`; + return url.startsWith('http') ? url : `https://${url}`; }; const commonMiddleware = (handler) => { return async (event, context, callback) => { - try { - const rawUrl = event.queryStringParameters.url; - const url = normalizeUrl(rawUrl); - - // Call the specific handler with the normalized URL - const response = await handler(url, event, context); - + + const rawUrl = (event.queryStringParameters || event.query).url; + + if (!rawUrl) { callback(null, { - statusCode: 200, - body: JSON.stringify(response), + statusCode: 500, + body: JSON.stringify({ error: 'No URL specified' }), }); + } + + const url = normalizeUrl(rawUrl); + + try { + const response = await handler(url, event, context); + if (response.body && response.statusCode) { + callback(null, response); + } else { + callback(null, { + statusCode: 200, + body: typeof response === 'object' ? JSON.stringify(response) : response, + }); + } } catch (error) { console.log(error); callback(null, { From d2a56eb526d55842a7ed20ee9f9c09a730438782 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Wed, 9 Aug 2023 22:33:36 +0100 Subject: [PATCH 22/94] Updates all API endpoints to use common middleware --- api/check-hsts.js | 16 +++---- api/content-links.js | 67 +++++++++++----------------- api/dns-sec.js | 29 +++--------- api/dns-server.js | 27 +++++------ api/find-url-ip.js | 42 +++++++----------- api/follow-redirects.js | 20 +++------ api/get-carbon.js | 23 +++------- api/get-cookies.js | 24 +++------- api/get-dns.js | 35 +++++++-------- api/get-headers.js | 25 +++-------- api/get-txt.js | 34 ++++++-------- api/lighthouse-report.js | 42 +++++------------- api/screenshot.js | 35 ++++----------- api/security-txt.js | 45 ++++++------------- api/server-status.js | 27 ++++------- api/site-features.js | 24 ++++------ api/sitemap.js | 23 +++------- api/ssl-check.js | 33 +++++--------- api/tech-stack.js | 79 +++++++++------------------------ api/trace-route.js | 68 +++++++++------------------- api/whois-lookup.js | 96 ++++++++++++++++------------------------ 21 files changed, 264 insertions(+), 550 deletions(-) diff --git a/api/check-hsts.js b/api/check-hsts.js index 71382cb..9dfed13 100644 --- a/api/check-hsts.js +++ b/api/check-hsts.js @@ -1,8 +1,7 @@ const https = require('https'); +const middleware = require('./_common/middleware'); -exports.handler = async function(event, context) { - const siteURL = (event.queryStringParameters || event.query).url; - +exports.handler = middleware(async (url, event, context) => { const errorResponse = (message, statusCode = 500) => { return { statusCode: statusCode, @@ -16,15 +15,9 @@ exports.handler = async function(event, context) { }; }; - if (!siteURL) { - return { - statusCode: 400, - body: JSON.stringify({ error: 'URL parameter is missing!' }), - }; - } return new Promise((resolve, reject) => { - const req = https.request(siteURL, res => { + const req = https.request(url, res => { const headers = res.headers; const hstsHeader = headers['strict-transport-security']; @@ -60,4 +53,5 @@ exports.handler = async function(event, context) { req.end(); }); -}; +}); + diff --git a/api/content-links.js b/api/content-links.js index 34e4205..45c3f50 100644 --- a/api/content-links.js +++ b/api/content-links.js @@ -1,48 +1,35 @@ const axios = require('axios'); const cheerio = require('cheerio'); const urlLib = require('url'); +const commonMiddleware = require('./_common/middleware'); -exports.handler = async (event, context) => { - let url = event.queryStringParameters.url; - - // Check if url includes protocol - if (!url.startsWith('http://') && !url.startsWith('https://')) { - url = 'http://' + url; - } - - try { - const response = await axios.get(url); - const html = response.data; - const $ = cheerio.load(html); - const internalLinksMap = new Map(); - const externalLinksMap = new Map(); +const handler = async (url) => { + const response = await axios.get(url); + const html = response.data; + const $ = cheerio.load(html); + const internalLinksMap = new Map(); + const externalLinksMap = new Map(); - $('a[href]').each((i, link) => { - const href = $(link).attr('href'); - const absoluteUrl = urlLib.resolve(url, href); - - if (absoluteUrl.startsWith(url)) { - const count = internalLinksMap.get(absoluteUrl) || 0; - internalLinksMap.set(absoluteUrl, count + 1); - } else if (href.startsWith('http://') || href.startsWith('https://')) { - const count = externalLinksMap.get(absoluteUrl) || 0; - externalLinksMap.set(absoluteUrl, count + 1); - } - }); + // Get all links on the page + $('a[href]').each((i, link) => { + const href = $(link).attr('href'); + const absoluteUrl = urlLib.resolve(url, href); + + // Check if absolute / relative, append to appropriate map or increment occurrence count + if (absoluteUrl.startsWith(url)) { + const count = internalLinksMap.get(absoluteUrl) || 0; + internalLinksMap.set(absoluteUrl, count + 1); + } else if (href.startsWith('http://') || href.startsWith('https://')) { + const count = externalLinksMap.get(absoluteUrl) || 0; + externalLinksMap.set(absoluteUrl, count + 1); + } + }); - // Convert maps to sorted arrays - const internalLinks = [...internalLinksMap.entries()].sort((a, b) => b[1] - a[1]).map(entry => entry[0]); - const externalLinks = [...externalLinksMap.entries()].sort((a, b) => b[1] - a[1]).map(entry => entry[0]); + // Sort by most occurrences, remove supplicates, and convert to array + const internalLinks = [...internalLinksMap.entries()].sort((a, b) => b[1] - a[1]).map(entry => entry[0]); + const externalLinks = [...externalLinksMap.entries()].sort((a, b) => b[1] - a[1]).map(entry => entry[0]); - return { - statusCode: 200, - body: JSON.stringify({ internal: internalLinks, external: externalLinks }), - }; - } catch (error) { - console.log(error); - return { - statusCode: 500, - body: JSON.stringify({ error: 'Failed fetching data' }), - }; - } + return { internal: internalLinks, external: externalLinks }; }; + +exports.handler = commonMiddleware(handler); diff --git a/api/dns-sec.js b/api/dns-sec.js index c4cf3f3..5f04044 100644 --- a/api/dns-sec.js +++ b/api/dns-sec.js @@ -1,16 +1,7 @@ const https = require('https'); +const commonMiddleware = require('./_common/middleware'); // Make sure this path is correct -exports.handler = async function(event, context) { - const url = (event.queryStringParameters || event.query).url; - - if (!url) { - return errorResponse('URL query parameter is required.'); - } - - // Extract hostname from URL - const parsedUrl = new URL(url); - const domain = parsedUrl.hostname; - +const fetchDNSRecords = async (domain, event, context) => { const dnsTypes = ['DNSKEY', 'DS', 'RRSIG']; const records = {}; @@ -48,22 +39,14 @@ exports.handler = async function(event, context) { if (dnsResponse.Answer) { records[type] = { isFound: true, answer: dnsResponse.Answer, response: dnsResponse.Answer }; } else { - records[type] = { isFound: false, answer: null, response: dnsResponse}; + records[type] = { isFound: false, answer: null, response: dnsResponse }; } } catch (error) { - return errorResponse(`Error fetching ${type} record: ${error.message}`); + throw new Error(`Error fetching ${type} record: ${error.message}`); // This will be caught and handled by the commonMiddleware } } - return { - statusCode: 200, - body: JSON.stringify(records), - }; + return records; }; -const errorResponse = (message, statusCode = 444) => { - return { - statusCode: statusCode, - body: JSON.stringify({ error: message }), - }; -}; +exports.handler = commonMiddleware(fetchDNSRecords); diff --git a/api/dns-server.js b/api/dns-server.js index 3bcbe3b..5be9385 100644 --- a/api/dns-server.js +++ b/api/dns-server.js @@ -1,12 +1,11 @@ const dns = require('dns'); const dnsPromises = dns.promises; -// const https = require('https'); const axios = require('axios'); +const commonMiddleware = require('./_common/middleware'); -exports.handler = async (event) => { - const url = (event.queryStringParameters || event.query).url; - const domain = url.replace(/^(?:https?:\/\/)?/i, ""); +const handler = async (url) => { try { + const domain = url.replace(/^(?:https?:\/\/)?/i, ""); const addresses = await dnsPromises.resolve4(domain); const results = await Promise.all(addresses.map(async (address) => { const hostname = await dnsPromises.reverse(address).catch(() => null); @@ -23,6 +22,7 @@ exports.handler = async (event) => { dohDirectSupports, }; })); + // let dohMozillaSupport = false; // try { // const mozillaList = await axios.get('https://firefox.settings.services.mozilla.com/v1/buckets/security-state/collections/onecrl/records'); @@ -30,20 +30,15 @@ exports.handler = async (event) => { // } catch (error) { // console.error(error); // } + return { - statusCode: 200, - body: JSON.stringify({ - domain, - dns: results, - // dohMozillaSupport, - }), + domain, + dns: results, + // dohMozillaSupport, }; } catch (error) { - return { - statusCode: 500, - body: JSON.stringify({ - error: `An error occurred while resolving DNS. ${error.message}`, - }), - }; + throw new Error(`An error occurred while resolving DNS. ${error.message}`); // This will be caught and handled by the commonMiddleware } }; + +exports.handler = commonMiddleware(handler); diff --git a/api/find-url-ip.js b/api/find-url-ip.js index 30355c9..8df95bc 100644 --- a/api/find-url-ip.js +++ b/api/find-url-ip.js @@ -1,33 +1,21 @@ const dns = require('dns'); +const middleware = require('./_common/middleware'); -/* Lambda function to fetch the IP address of a given URL */ -exports.handler = function (event, context, callback) { - const addressParam = (event.queryStringParameters || event.query).url; - - if (!addressParam) { - callback(null, errorResponse('Address parameter is missing.')); - return; - } - - const address = decodeURIComponent(addressParam) - .replaceAll('https://', '') - .replaceAll('http://', ''); - - dns.lookup(address, (err, ip, family) => { - if (err) { - callback(null, errorResponse(err.message)); - } else { - callback(null, { - statusCode: 200, - body: JSON.stringify({ ip, family }), - }); - } +const lookupAsync = (address) => { + return new Promise((resolve, reject) => { + dns.lookup(address, (err, ip, family) => { + if (err) { + reject(err); + } else { + resolve({ ip, family }); + } + }); }); }; -const errorResponse = (message, statusCode = 444) => { - return { - statusCode: statusCode, - body: JSON.stringify({ error: message }), - }; +const handler = async (url) => { + const address = url.replaceAll('https://', '').replaceAll('http://', ''); + return await lookupAsync(address); }; + +exports.handler = middleware(handler); diff --git a/api/follow-redirects.js b/api/follow-redirects.js index 42b56db..9f53b02 100644 --- a/api/follow-redirects.js +++ b/api/follow-redirects.js @@ -1,9 +1,8 @@ -exports.handler = async (event) => { - const url = (event.queryStringParameters || event.query).url; +const handler = async (url) => { const redirects = [url]; + const got = await import('got'); try { - const got = await import('got'); await got.default(url, { followRedirect: true, maxRedirects: 12, @@ -17,19 +16,12 @@ exports.handler = async (event) => { }); return { - statusCode: 200, - body: JSON.stringify({ - redirects: redirects, - }), + redirects: redirects, }; } catch (error) { - return errorResponse(`Error: ${error.message}`); + throw new Error(`Error: ${error.message}`); } }; -const errorResponse = (message, statusCode = 444) => { - return { - statusCode: statusCode, - body: JSON.stringify({ error: message }), - }; -}; +const middleware = require('./_common/middleware'); +exports.handler = middleware(handler); diff --git a/api/get-carbon.js b/api/get-carbon.js index d975753..42dd6f8 100644 --- a/api/get-carbon.js +++ b/api/get-carbon.js @@ -1,14 +1,7 @@ const https = require('https'); +const middleware = require('./_common/middleware'); -exports.handler = async (event, context) => { - const url = (event.queryStringParameters || event.query).url; - - if (!url) { - return { - statusCode: 400, - body: JSON.stringify({ error: 'url query parameter is required' }), - }; - } +const handler = async (url) => { // First, get the size of the website's HTML const getHtmlSize = (url) => new Promise((resolve, reject) => { @@ -42,14 +35,10 @@ exports.handler = async (event, context) => { }); carbonData.scanUrl = url; - return { - statusCode: 200, - body: JSON.stringify(carbonData), - }; + return carbonData; } catch (error) { - return { - statusCode: 500, - body: JSON.stringify({ error: `Error: ${error.message}` }), - }; + throw new Error(`Error: ${error.message}`); } }; + +exports.handler = middleware(handler); diff --git a/api/get-cookies.js b/api/get-cookies.js index e2c05f2..f24d68a 100644 --- a/api/get-cookies.js +++ b/api/get-cookies.js @@ -1,26 +1,14 @@ const axios = require('axios'); +const middleware = require('./_common/middleware'); -exports.handler = async function(event, context) { - const url = (event.queryStringParameters || event.query).url; - - if (!url) { - return { - statusCode: 400, - body: JSON.stringify({ message: 'url query string parameter is required' }), - }; - } - +const handler = async (url, event, context) => { try { const response = await axios.get(url, {withCredentials: true}); const cookies = response.headers['set-cookie']; - return { - statusCode: 200, - body: JSON.stringify({ cookies }), - }; + return { cookies }; } catch (error) { - return { - statusCode: 500, - body: JSON.stringify({ error: error.message }), - }; + throw new Error(error.message); } }; + +exports.handler = middleware(handler); diff --git a/api/get-dns.js b/api/get-dns.js index 1be91a2..f7774a9 100644 --- a/api/get-dns.js +++ b/api/get-dns.js @@ -1,8 +1,9 @@ const dns = require('dns'); const util = require('util'); +const middleware = require('./_common/middleware'); -exports.handler = async function(event, context) { - let hostname = (event.queryStringParameters || event.query).url; +const handler = async (url) => { + let hostname = url; // Handle URLs by extracting hostname if (hostname.startsWith('http://') || hostname.startsWith('https://')) { @@ -35,25 +36,19 @@ exports.handler = async function(event, context) { ]); return { - statusCode: 200, - body: JSON.stringify({ - A: a, - AAAA: aaaa, - MX: mx, - TXT: txt, - NS: ns, - CNAME: cname, - SOA: soa, - SRV: srv, - PTR: ptr - }) + A: a, + AAAA: aaaa, + MX: mx, + TXT: txt, + NS: ns, + CNAME: cname, + SOA: soa, + SRV: srv, + PTR: ptr }; } catch (error) { - return { - statusCode: 500, - body: JSON.stringify({ - error: error.message - }) - }; + throw new Error(error.message); } }; + +exports.handler = middleware(handler); diff --git a/api/get-headers.js b/api/get-headers.js index 00cf755..79b4c4a 100644 --- a/api/get-headers.js +++ b/api/get-headers.js @@ -1,15 +1,7 @@ const axios = require('axios'); +const middleware = require('./_common/middleware'); -exports.handler = async function(event, context) { - const url = (event.queryStringParameters || event.query).url; - - if (!url) { - return { - statusCode: 400, - body: JSON.stringify({ error: 'url query string parameter is required' }), - }; - } - +const handler = async (url, event, context) => { try { const response = await axios.get(url, { validateStatus: function (status) { @@ -17,15 +9,10 @@ exports.handler = async function(event, context) { }, }); - return { - statusCode: 200, - body: JSON.stringify(response.headers), - }; + return response.headers; } catch (error) { - console.log(error); - return { - statusCode: 500, - body: JSON.stringify({ error: error.message }), - }; + throw new Error(error.message); } }; + +exports.handler = middleware(handler); diff --git a/api/get-txt.js b/api/get-txt.js index cf3883b..f397bc5 100644 --- a/api/get-txt.js +++ b/api/get-txt.js @@ -1,17 +1,11 @@ const dns = require('dns').promises; +const middleware = require('./_common/middleware'); -exports.handler = async (event) => { - let url = (event.queryStringParameters || event.query).url; +const handler = async (url, event, context) => { try { - url = new URL(url); - } catch (error) { - return { - statusCode: 400, - body: JSON.stringify({ error: `Invalid URL ${error}` }), - }; - } - try { - const txtRecords = await dns.resolveTxt(url.hostname); + const parsedUrl = new URL(url); + + const txtRecords = await dns.resolveTxt(parsedUrl.hostname); // Parsing and formatting TXT records into a single object const readableTxtRecords = txtRecords.reduce((acc, recordArray) => { @@ -24,15 +18,15 @@ exports.handler = async (event) => { return { ...acc, ...recordObject }; }, {}); - return { - statusCode: 200, - body: JSON.stringify(readableTxtRecords), - }; + return readableTxtRecords; + } catch (error) { - console.error('Error:', error); - return { - statusCode: 500, - body: JSON.stringify({ error: error.message }), - }; + if (error.code === 'ERR_INVALID_URL') { + throw new Error(`Invalid URL ${error}`); + } else { + throw error; + } } }; + +exports.handler = middleware(handler); diff --git a/api/lighthouse-report.js b/api/lighthouse-report.js index ab76aff..2c606db 100644 --- a/api/lighthouse-report.js +++ b/api/lighthouse-report.js @@ -1,40 +1,22 @@ const axios = require('axios'); +const middleware = require('./_common/middleware'); -exports.handler = function(event, context, callback) { - const url = (event.queryStringParameters || event.query).url; - - if (!url) { - callback(null, { - statusCode: 400, - body: JSON.stringify({ error: 'URL param is required'}), - }); - } - +const handler = async (url, event, context) => { const apiKey = process.env.GOOGLE_CLOUD_API_KEY; + if (!url) { + throw new Error('URL param is required'); + } + if (!apiKey) { - callback(null, { - statusCode: 500, - body: JSON.stringify({ error: 'API key (GOOGLE_CLOUD_API_KEY) not set'}), - }); + throw new Error('API key (GOOGLE_CLOUD_API_KEY) not set'); } const endpoint = `https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=${encodeURIComponent(url)}&category=PERFORMANCE&category=ACCESSIBILITY&category=BEST_PRACTICES&category=SEO&category=PWA&strategy=mobile&key=${apiKey}`; + + const response = await axios.get(endpoint); - axios.get(endpoint) - .then( - (response) => { - callback(null, { - statusCode: 200, - body: JSON.stringify(response.data), - }); - } - ).catch( - () => { - callback(null, { - statusCode: 500, - body: JSON.stringify({ error: 'Error running Lighthouse'}), - }); - } - ); + return response.data; }; + +exports.handler = middleware(handler); diff --git a/api/screenshot.js b/api/screenshot.js index 75f1741..49906f0 100644 --- a/api/screenshot.js +++ b/api/screenshot.js @@ -1,16 +1,11 @@ const puppeteer = require('puppeteer-core'); const chromium = require('chrome-aws-lambda'); +const middleware = require('./_common/middleware'); -exports.handler = async (event, context, callback) => { - let browser = null; - let targetUrl = (event.queryStringParameters || event.query).url; +const screenshotHandler = async (targetUrl) => { if (!targetUrl) { - callback(null, { - statusCode: 400, - body: JSON.stringify({ error: 'URL is missing from queryStringParameters' }), - }); - return; + throw new Error('URL is missing from queryStringParameters'); } if (!targetUrl.startsWith('http://') && !targetUrl.startsWith('https://')) { @@ -20,13 +15,10 @@ exports.handler = async (event, context, callback) => { try { new URL(targetUrl); } catch (error) { - callback(null, { - statusCode: 400, - body: JSON.stringify({ error: 'URL provided is invalid' }), - }); - return; + throw new Error('URL provided is invalid'); } + let browser = null; try { browser = await puppeteer.launch({ args: chromium.args, @@ -40,9 +32,7 @@ exports.handler = async (event, context, callback) => { let page = await browser.newPage(); await page.emulateMediaFeatures([{ name: 'prefers-color-scheme', value: 'dark' }]); - page.setDefaultNavigationTimeout(8000); - await page.goto(targetUrl, { waitUntil: 'domcontentloaded' }); await page.evaluate(() => { @@ -57,24 +47,15 @@ exports.handler = async (event, context, callback) => { }); const screenshotBuffer = await page.screenshot(); - const base64Screenshot = screenshotBuffer.toString('base64'); - const response = { - statusCode: 200, - body: JSON.stringify({ image: base64Screenshot }), - }; + return { image: base64Screenshot }; - callback(null, response); - } catch (error) { - console.log(error); - callback(null, { - statusCode: 500, - body: JSON.stringify({ error: `An error occurred: ${error.message}` }), - }); } finally { if (browser !== null) { await browser.close(); } } }; + +exports.handler = middleware(screenshotHandler); diff --git a/api/security-txt.js b/api/security-txt.js index 78ded4c..c2cd59c 100644 --- a/api/security-txt.js +++ b/api/security-txt.js @@ -1,5 +1,6 @@ const { https } = require('follow-redirects'); const { URL } = require('url'); +const middleware = require('./_common/middleware'); const SECURITY_TXT_PATHS = [ '/security.txt', @@ -37,59 +38,39 @@ const isPgpSigned = (result) => { return false; }; -exports.handler = async (event, context) => { - const urlParam = (event.queryStringParameters || event.query).url; - if (!urlParam) { - return { - statusCode: 400, - body: JSON.stringify({ error: 'Missing url parameter' }) - }; - } +const securityTxtHandler = async (urlParam) => { let url; try { url = new URL(urlParam.includes('://') ? urlParam : 'https://' + urlParam); } catch (error) { - return { - statusCode: 500, - body: JSON.stringify({ error: 'Invalid URL format' }), - }; + throw new Error('Invalid URL format'); } url.pathname = ''; for (let path of SECURITY_TXT_PATHS) { try { const result = await fetchSecurityTxt(url, path); - if (result && result.includes(' { const url = new URL(path, baseURL); diff --git a/api/server-status.js b/api/server-status.js index 242df31..ce4f478 100644 --- a/api/server-status.js +++ b/api/server-status.js @@ -1,14 +1,10 @@ const https = require('https'); const { performance, PerformanceObserver } = require('perf_hooks'); +const middleware = require('./_common/middleware'); -exports.handler = async function(event, context) { - const url = (event.queryStringParameters || event.query).url; - +const checkURLHandler = async (url) => { if (!url) { - return { - statusCode: 400, - body: JSON.stringify({ error: 'You must provide a URL query parameter!' }), - }; + throw new Error('You must provide a URL query parameter!'); } let dnsLookupTime; @@ -43,10 +39,7 @@ exports.handler = async function(event, context) { }); if (responseCode < 200 || responseCode >= 400) { - return { - statusCode: 200, - body: JSON.stringify({ error: `Received non-success response code: ${responseCode}` }), - }; + throw new Error(`Received non-success response code: ${responseCode}`); } performance.mark('B'); @@ -54,16 +47,12 @@ exports.handler = async function(event, context) { let responseTime = performance.now() - startTime; obs.disconnect(); - return { - statusCode: 200, - body: JSON.stringify({ isUp: true, dnsLookupTime, responseTime, responseCode }), - }; + return { isUp: true, dnsLookupTime, responseTime, responseCode }; } catch (error) { obs.disconnect(); - return { - statusCode: 200, - body: JSON.stringify({ error: `Error during operation: ${error.message}` }), - }; + throw error; } }; + +exports.handler = middleware(checkURLHandler); diff --git a/api/site-features.js b/api/site-features.js index d9b6486..ced8757 100644 --- a/api/site-features.js +++ b/api/site-features.js @@ -1,22 +1,15 @@ const https = require('https'); +const middleware = require('./_common/middleware'); -exports.handler = async function (event, context) { - const url = (event.queryStringParameters || event.query).url; +const builtWithHandler = async (url) => { const apiKey = process.env.BUILT_WITH_API_KEY; - const errorResponse = (message, statusCode = 500) => { - return { - statusCode: statusCode, - body: JSON.stringify({ error: message }), - }; - }; - if (!url) { - return errorResponse('URL query parameter is required', 400); + throw new Error('URL query parameter is required'); } if (!apiKey) { - return errorResponse('Missing BuiltWith API key in environment variables', 500); + throw new Error('Missing BuiltWith API key in environment variables'); } const apiUrl = `https://api.builtwith.com/free1/api.json?KEY=${apiKey}&LOOKUP=${encodeURIComponent(url)}`; @@ -46,11 +39,10 @@ exports.handler = async function (event, context) { req.end(); }); - return { - statusCode: 200, - body: response, - }; + return response; } catch (error) { - return errorResponse(`Error making request: ${error.message}`); + throw new Error(`Error making request: ${error.message}`); } }; + +exports.handler = middleware(builtWithHandler); diff --git a/api/sitemap.js b/api/sitemap.js index 149835f..f68cce0 100644 --- a/api/sitemap.js +++ b/api/sitemap.js @@ -1,10 +1,8 @@ const axios = require('axios'); const xml2js = require('xml2js'); +const middleware = require('./_common/middleware'); -exports.handler = async (event) => { - const url = (event.queryStringParameters || event.query).url; - // const baseUrl = event.queryStringParameters.url.replace(/^(?:https?:\/\/)?/i, ""); - // const url = baseUrl.startsWith('http') ? baseUrl : `http://${baseUrl}`; +const fetchSitemapHandler = async (url) => { let sitemapUrl; try { @@ -19,24 +17,17 @@ exports.handler = async (event) => { } if (!sitemapUrl) { - return { - statusCode: 404, - body: JSON.stringify({ error: 'Sitemap not found in robots.txt' }), - }; + throw new Error('Sitemap not found in robots.txt'); } // Fetch sitemap const sitemapRes = await axios.get(sitemapUrl); const sitemap = await xml2js.parseStringPromise(sitemapRes.data); - return { - statusCode: 200, - body: JSON.stringify(sitemap), - }; + return sitemap; } catch (error) { - return { - statusCode: 500, - body: JSON.stringify({ error: error.message }), - }; + throw new Error(error.message); } }; + +exports.handler = middleware(fetchSitemapHandler); diff --git a/api/ssl-check.js b/api/ssl-check.js index f87b66a..22d998f 100644 --- a/api/ssl-check.js +++ b/api/ssl-check.js @@ -1,43 +1,28 @@ const https = require('https'); +const middleware = require('./_common/middleware'); -exports.handler = async function (event, context) { - const url = (event.queryStringParameters || event.query).url; - - const errorResponse = (message, statusCode = 500) => { - return { - statusCode: statusCode, - body: JSON.stringify({ error: message }), - }; - }; - - if (!url) { - return errorResponse('URL query parameter is required', 400); - } - +const fetchSiteCertificateHandler = async (url) => { try { const response = await new Promise((resolve, reject) => { const req = https.request(url, res => { - + // Check if the SSL handshake was authorized if (!res.socket.authorized) { - resolve(errorResponse(`SSL handshake not authorized. Reason: ${res.socket.authorizationError}`)); + reject(new Error(`SSL handshake not authorized. Reason: ${res.socket.authorizationError}`)); } else { let cert = res.socket.getPeerCertificate(true); if (!cert || Object.keys(cert).length === 0) { - resolve(errorResponse("No certificate presented by the server.")); + reject(new Error("No certificate presented by the server.")); } else { // omit the raw and issuerCertificate fields const { raw, issuerCertificate, ...certWithoutRaw } = cert; - resolve({ - statusCode: 200, - body: JSON.stringify(certWithoutRaw), - }); + resolve(certWithoutRaw); } } }); req.on('error', error => { - resolve(errorResponse(`Error fetching site certificate: ${error.message}`)); + reject(new Error(`Error fetching site certificate: ${error.message}`)); }); req.end(); @@ -45,6 +30,8 @@ exports.handler = async function (event, context) { return response; } catch (error) { - return errorResponse(`Unexpected error occurred: ${error.message}`); + throw new Error(error.message); } }; + +exports.handler = middleware(fetchSiteCertificateHandler); diff --git a/api/tech-stack.js b/api/tech-stack.js index 596ba52..5820f6d 100644 --- a/api/tech-stack.js +++ b/api/tech-stack.js @@ -1,69 +1,30 @@ const Wappalyzer = require('wappalyzer'); +const middleware = require('./_common/middleware'); -const analyze = async (url) => { - +const analyzeSiteTechnologies = async (url) => { const options = {}; const wappalyzer = new Wappalyzer(options); - return (async function() { - try { - await wappalyzer.init() - const headers = {} - const storage = { - local: {}, - session: {}, - } - const site = await wappalyzer.open(url, headers, storage) - const results = await site.analyze() - return results; - } catch (error) { - return error; - } finally { - await wappalyzer.destroy() - } - })(); -} -exports.handler = async (event, context, callback) => { - // Validate URL parameter - if (!(event.queryStringParameters || event.query).url) { - return { - statusCode: 400, - body: JSON.stringify({ error: 'Missing url parameter' }), - }; - } - - // Get URL from param - let url = (event.queryStringParameters || event.query).url; - if (!/^https?:\/\//i.test(url)) { - url = 'http://' + url; - } - try { - return analyze(url).then( - (results) => { - if (!results.technologies || results.technologies.length === 0) { - return { - statusCode: 200, - body: JSON.stringify({ error: 'Unable to find any technologies for site' }), - }; - } - return { - statusCode: 200, - body: JSON.stringify(results), - } - } - ) - .catch((error) => { - return { - statusCode: 500, - body: JSON.stringify({ error: error.message }), - }; - }); - } catch (error) { - return { - statusCode: 500, - body: JSON.stringify({ error: error.message }), + await wappalyzer.init(); + const headers = {}; + const storage = { + local: {}, + session: {}, }; + const site = await wappalyzer.open(url, headers, storage); + const results = await site.analyze(); + + if (!results.technologies || results.technologies.length === 0) { + throw new Error('Unable to find any technologies for site'); + } + return results; + } catch (error) { + throw new Error(error.message); + } finally { + await wappalyzer.destroy(); } }; + +exports.handler = middleware(analyzeSiteTechnologies); diff --git a/api/trace-route.js b/api/trace-route.js index 8d8525e..8d7b10b 100644 --- a/api/trace-route.js +++ b/api/trace-route.js @@ -1,55 +1,31 @@ const traceroute = require('traceroute'); const url = require('url'); +const middleware = require('./_common/middleware'); -exports.handler = async function(event, context) { - const urlString = (event.queryStringParameters || event.query).url; +const executeTraceroute = async (urlString, context) => { + // Parse the URL and get the hostname + const urlObject = url.parse(urlString); + const host = urlObject.hostname; - try { - if (!urlString) { - throw new Error('URL parameter is missing!'); - } + if (!host) { + throw new Error('Invalid URL provided'); + } - // Parse the URL and get the hostname - const urlObject = url.parse(urlString); - const host = urlObject.hostname; - - if (!host) { - throw new Error('Invalid URL provided'); - } - - // Traceroute with callback - const result = await new Promise((resolve, reject) => { - traceroute.trace(host, (err, hops) => { - if (err || !hops) { - reject(err || new Error('No hops found')); - } else { - resolve(hops); - } - }); - - // Check if remaining time is less than 8.8 seconds, then reject promise - if (context.getRemainingTimeInMillis() < 8800) { - reject(new Error('Lambda is about to timeout')); + // Traceroute with callback + const result = await new Promise((resolve, reject) => { + traceroute.trace(host, (err, hops) => { + if (err || !hops) { + reject(err || new Error('No hops found')); + } else { + resolve(hops); } }); + }); - return { - statusCode: 200, - body: JSON.stringify({ - message: "Traceroute completed!", - result, - }), - }; - } catch (err) { - const message = err.code === 'ENOENT' - ? 'Traceroute command is not installed on the host.' - : err.message; - - return { - statusCode: 500, - body: JSON.stringify({ - error: message, - }), - }; - } + return { + message: "Traceroute completed!", + result, + }; }; + +exports.handler = middleware(executeTraceroute); diff --git a/api/whois-lookup.js b/api/whois-lookup.js index 3b6ba3e..69e5674 100644 --- a/api/whois-lookup.js +++ b/api/whois-lookup.js @@ -1,14 +1,6 @@ const net = require('net'); const psl = require('psl'); -// const { URL } = require('url'); - -const errorResponse = (message, statusCode = 444) => { - return { - statusCode: statusCode, - body: JSON.stringify({ error: message }), - }; -}; - +const middleware = require('./_common/middleware'); const getBaseDomain = (url) => { let protocol = ''; @@ -22,55 +14,7 @@ const getBaseDomain = (url) => { return protocol + parsed.domain; }; - -exports.handler = async function(event, context) { - const url = (event.queryStringParameters || event.query).url; - - if (!url) { - return errorResponse('URL query parameter is required.', 400); - } - - if (!url.startsWith('http://') && !url.startsWith('https://')) { - url = 'http://' + url; - } - - let hostname; - try { - hostname = getBaseDomain(new URL(url).hostname); - } catch (error) { - return errorResponse(`Unable to parse URL: ${error}`, 400); - } - - return new Promise((resolve, reject) => { - const client = net.createConnection({ port: 43, host: 'whois.internic.net' }, () => { - client.write(hostname + '\r\n'); - }); - - let data = ''; - client.on('data', (chunk) => { - data += chunk; - }); - - client.on('end', () => { - try { - const parsedData = parseWhoisData(data); - resolve({ - statusCode: 200, - body: JSON.stringify(parsedData), - }); - } catch (error) { - resolve(errorResponse(error.message)); - } - }); - - client.on('error', (err) => { - resolve(errorResponse(err.message, 500)); - }); - }); -}; - const parseWhoisData = (data) => { - if (data.includes('No match for')) { return { error: 'No matches found for domain in internic database'}; } @@ -100,3 +44,41 @@ const parseWhoisData = (data) => { return parsedData; }; +const fetchWhoisData = async (url) => { + if (!url.startsWith('http://') && !url.startsWith('https://')) { + url = 'http://' + url; + } + + let hostname; + try { + hostname = getBaseDomain(new URL(url).hostname); + } catch (error) { + throw new Error(`Unable to parse URL: ${error}`); + } + + return new Promise((resolve, reject) => { + const client = net.createConnection({ port: 43, host: 'whois.internic.net' }, () => { + client.write(hostname + '\r\n'); + }); + + let data = ''; + client.on('data', (chunk) => { + data += chunk; + }); + + client.on('end', () => { + try { + const parsedData = parseWhoisData(data); + resolve(parsedData); + } catch (error) { + reject(error); + } + }); + + client.on('error', (err) => { + reject(err); + }); + }); +}; + +exports.handler = middleware(fetchWhoisData); From af1689bd8536078fb78eafb77f0a1551d24310e5 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Wed, 9 Aug 2023 23:29:39 +0100 Subject: [PATCH 23/94] Adds support for history router --- package.json | 1 + yarn.lock | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2169a14..aa20991 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "axios": "^1.4.0", "cheerio": "^1.0.0-rc.12", "chrome-aws-lambda": "^10.1.0", + "connect-history-api-fallback": "^2.0.0", "dotenv": "^16.3.1", "flatted": "^3.2.7", "follow-redirects": "^1.15.2", diff --git a/yarn.lock b/yarn.lock index 115dd7c..5d101b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6754,7 +6754,7 @@ dotenv@^10.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== -dotenv@^16.0.2: +dotenv@^16.0.2, dotenv@^16.3.1: version "16.3.1" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.1.tgz#369034de7d7e5b120972693352a3bf112172cc3e" integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== From 976ca7d47a829ba6f2c94e2028cadf4a58fc4539 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Wed, 9 Aug 2023 23:29:58 +0100 Subject: [PATCH 24/94] Serves up compiled react app to base --- server.js | 84 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 27 deletions(-) diff --git a/server.js b/server.js index 2973b91..84f8649 100644 --- a/server.js +++ b/server.js @@ -2,54 +2,75 @@ const express = require('express'); const awsServerlessExpress = require('aws-serverless-express'); const fs = require('fs'); const path = require('path'); +const historyApiFallback = require('connect-history-api-fallback'); require('dotenv').config(); const app = express(); -const handlers = {}; +const API_DIR = '/api'; // Name of the dir containing the lambda functions +const dirPath = path.join(__dirname, API_DIR); // Path to the lambda functions dir -const dirPath = path.join(__dirname, '/api'); +// Execute the lambda function +const executeHandler = async (handler, req) => { + return new Promise((resolve, reject) => { + const callback = (err, response) => err ? reject(err) : resolve(response); + const promise = handler(req, {}, callback); + if (promise && typeof promise.then === 'function') { + promise.then(resolve).catch(reject); + } + }); +}; + +// Array of all the lambda function file names const fileNames = fs.readdirSync(dirPath, { withFileTypes: true }) .filter(dirent => dirent.isFile() && dirent.name.endsWith('.js')) .map(dirent => dirent.name); +const handlers = {}; + fileNames.forEach(file => { - const route = `/api/${file.split('.')[0]}`; - const handler = require(path.join(__dirname, '/api', file)).handler; + const routeName = file.split('.')[0]; + const route = `${API_DIR}/${routeName}`; + const handler = require(path.join(dirPath, file)).handler; + handlers[route] = handler; app.get(route, async (req, res) => { try { - const result = await new Promise((resolve, reject) => { - const cb = (err, response) => err ? reject(err) : resolve(response); - const promise = handler(req, {}, cb); - if (promise && typeof promise.then === 'function') { - promise.then(resolve).catch(reject); - } - }); - res.status(result.statusCode).json(JSON.parse(result.body)); + const { statusCode = 200, body = '' } = await executeHandler(handler, req); + res.status(statusCode).json(JSON.parse(body)); } catch (err) { res.status(500).json({ error: err.message }); } }); }); +const timeout = (ms, jobName = null) => { + return new Promise((_, reject) => { + setTimeout(() => { + reject(new Error(`Timed out after the ${ms}ms limit${jobName ? `, when executing the ${jobName} task` : ''}`)); + }, ms); + }); +} + app.get('/api', async (req, res) => { const results = {}; - const url = req.query.url; + const { url } = req.query; + const maxExecutionTime = process.env.API_TIMEOUT_LIMIT || 10000; + const handlerPromises = Object.entries(handlers).map(async ([route, handler]) => { + const routeName = route.replace(`${API_DIR}/`, ''); + try { - const result = await new Promise((resolve, reject) => { - const cb = (err, response) => err ? reject(err) : resolve(response); - const promise = handler({ query: { url } }, {}, cb); - if (promise && typeof promise.then === 'function') { - promise.then(resolve).catch(reject); - } - }); - results[route.slice(5)] = JSON.parse(result.body); // remove '/api/' prefix + const result = await Promise.race([ + executeHandler(handler, { query: { url } }), + timeout(maxExecutionTime, routeName) + ]); + results[routeName] = JSON.parse((result || {}).body); + } catch (err) { - results[route.slice(5)] = { error: err.message }; + results[routeName] = { error: err.message }; } }); @@ -57,15 +78,24 @@ app.get('/api', async (req, res) => { res.json(results); }); +// Handle SPA routing +app.use(historyApiFallback({ + rewrites: [ + { from: /^\/api\/.*$/, to: function(context) { return context.parsedUrl.path; } }, + ] +})); + +// Serve React App (static files from ./build) +app.use(express.static(path.join(__dirname, 'build'))); + + // Create serverless express server -const port = process.env.API_PORT || 3001; -const server = awsServerlessExpress -.createServer(app) -.listen(port, () => { +const port = process.env.API_PORT || 3000; +const server = awsServerlessExpress.createServer(app).listen(port, () => { console.log(`Server is running on port ${port}`); }); exports.handler = (event, context) => { - console.log(`EVENT: ${JSON.stringify(event)}`); + // console.log(`EVENT: ${JSON.stringify(event)}`); awsServerlessExpress.proxy(server, event, context); }; From 95b13240c7f3ba6fd8c6ca043b6768c4651d7e0f Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 10 Aug 2023 14:27:06 +0100 Subject: [PATCH 25/94] Makes some functions more robust --- api/check-ports.js | 13 ++++++------- api/mail-config.js | 20 ++++++++------------ api/social-tags.js | 7 +++++-- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/api/check-ports.js b/api/check-ports.js index 00cb266..7a15d9f 100644 --- a/api/check-ports.js +++ b/api/check-ports.js @@ -1,4 +1,5 @@ const net = require('net'); +const middleware = require('./_common/middleware'); // A list of commonly used ports. const PORTS = [ @@ -12,7 +13,7 @@ async function checkPort(port, domain) { return new Promise((resolve, reject) => { const socket = new net.Socket(); - socket.setTimeout(1500); // you may want to adjust the timeout + socket.setTimeout(1500); socket.once('connect', () => { socket.destroy(); @@ -33,13 +34,9 @@ async function checkPort(port, domain) { }); } -exports.handler = async (event, context) => { - const domain = (event.queryStringParameters || event.query).url; +const handler = async (url, event, context) => { + const domain = url.replace(/(^\w+:|^)\/\//, ''); - if (!domain) { - return errorResponse('Missing domain parameter.'); - } - const delay = ms => new Promise(res => setTimeout(res, ms)); const timeout = delay(9000); @@ -88,3 +85,5 @@ const errorResponse = (message, statusCode = 444) => { body: JSON.stringify({ error: message }), }; }; + +exports.handler = middleware(handler); diff --git a/api/mail-config.js b/api/mail-config.js index f575d40..16fb7e2 100644 --- a/api/mail-config.js +++ b/api/mail-config.js @@ -1,11 +1,11 @@ +const commonMiddleware = require('./_common/middleware'); + const dns = require('dns').promises; const URL = require('url-parse'); -exports.handler = async (event, context) => { +const handler = async (url, event, context) => { try { - let domain = event.queryStringParameters.url; - const parsedUrl = new URL(domain); - domain = parsedUrl.hostname || parsedUrl.pathname; + const domain = new URL(url).hostname || new URL(url).pathname; // Get MX records const mxRecords = await dns.resolveMx(domain); @@ -56,19 +56,13 @@ exports.handler = async (event, context) => { } return { - statusCode: 200, - body: JSON.stringify({ mxRecords, txtRecords: emailTxtRecords, mailServices, - }), - }; + }; } catch (error) { if (error.code === 'ENOTFOUND' || error.code === 'ENODATA') { - return { - statusCode: 200, - body: JSON.stringify({ skipped: 'No mail server in use on this domain' }), - }; + return { skipped: 'No mail server in use on this domain' }; } else { return { statusCode: 500, @@ -77,3 +71,5 @@ exports.handler = async (event, context) => { } } }; + +module.exports.handler = commonMiddleware(handler); diff --git a/api/social-tags.js b/api/social-tags.js index 9b0af39..8d15232 100644 --- a/api/social-tags.js +++ b/api/social-tags.js @@ -1,8 +1,9 @@ +const commonMiddleware = require('./_common/middleware'); + const axios = require('axios'); const cheerio = require('cheerio'); -exports.handler = async (event, context) => { - let url = event.queryStringParameters.url; +const handler = async (url) => { // Check if url includes protocol if (!url.startsWith('http://') && !url.startsWith('https://')) { @@ -66,3 +67,5 @@ exports.handler = async (event, context) => { }; } }; + +exports.handler = commonMiddleware(handler); From f552e5cb692705db77c06dc268c73f464fb681f0 Mon Sep 17 00:00:00 2001 From: Mounir Date: Thu, 10 Aug 2023 17:16:11 +0200 Subject: [PATCH 26/94] fix current warnings --- src/components/Form/Modal.tsx | 14 +++++++------- src/components/misc/FancyBackground.tsx | 6 +++--- src/pages/About.tsx | 1 + src/pages/Home.tsx | 5 +++++ src/pages/Results.tsx | 20 ++++++++++---------- 5 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/components/Form/Modal.tsx b/src/components/Form/Modal.tsx index 610436a..16a0b99 100644 --- a/src/components/Form/Modal.tsx +++ b/src/components/Form/Modal.tsx @@ -57,13 +57,13 @@ const Modal: React.FC = ({ children, isOpen, closeModal }) => { } }; - const handleEscPress = (e: KeyboardEvent) => { - if (e.key === 'Escape') { - closeModal(); - } - }; - React.useEffect(() => { + const handleEscPress = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + closeModal(); + } + }; + if (isOpen) { window.addEventListener('keydown', handleEscPress); } @@ -71,7 +71,7 @@ const Modal: React.FC = ({ children, isOpen, closeModal }) => { return () => { window.removeEventListener('keydown', handleEscPress); }; - }, [isOpen]); + }, [isOpen, closeModal]); if (!isOpen) { return null; diff --git a/src/components/misc/FancyBackground.tsx b/src/components/misc/FancyBackground.tsx index 626a578..cc963a8 100644 --- a/src/components/misc/FancyBackground.tsx +++ b/src/components/misc/FancyBackground.tsx @@ -1,4 +1,4 @@ -import { useEffect } from "react"; +import { useEffect, useMemo } from "react"; const FancyBackground = (): JSX.Element => { @@ -25,7 +25,7 @@ const FancyBackground = (): JSX.Element => { return result; }; - const App: any = {}; + const App: any = useMemo(() => [], []); App.setup = function () { @@ -335,7 +335,7 @@ const FancyBackground = (): JSX.Element => { requestAnimationFrame(frame); }; frame(); - }, []); + }, [App]); diff --git a/src/pages/About.tsx b/src/pages/About.tsx index 922e00a..da002d4 100644 --- a/src/pages/About.tsx +++ b/src/pages/About.tsx @@ -172,6 +172,7 @@ const About = (): JSX.Element => { API Documentation

    + {/* eslint-disable-next-line*/}

    // Coming soon...

    diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index bf2afba..be19c3c 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -38,6 +38,7 @@ const UserInputMain = styled.form` z-index: 2; `; +/* const FindIpButton = styled.a` margin: 0.5rem; cursor: pointer; @@ -46,6 +47,7 @@ const FindIpButton = styled.a` color: ${colors.primary}; text-decoration: underline; `; +*/ const ErrorMessage = styled.p` color: ${colors.danger}; @@ -126,6 +128,8 @@ const Home = (): JSX.Element => { if (!isError) setErrMsg(''); }; + + // eslint-disable-next-line const findIpAddress = () => { setUserInput(''); setPlaceholder('Looking up your IP...'); @@ -143,6 +147,7 @@ const Home = (): JSX.Element => { }); }; + const formSubmitEvent = (event: FormEvent) => { event.preventDefault(); submit(); diff --git a/src/pages/Results.tsx b/src/pages/Results.tsx index 5042b91..80d9ab9 100644 --- a/src/pages/Results.tsx +++ b/src/pages/Results.tsx @@ -132,7 +132,7 @@ const Results = (): JSX.Element => { } return newJobs; }); - }, []); + }, [startTime]); const parseJson = (response: Response): Promise => { return new Promise((resolve) => { @@ -147,15 +147,6 @@ const Results = (): JSX.Element => { }); }; - useEffect(() => { - if (!addressType || addressType === 'empt') { - setAddressType(determineAddressType(address || '')); - } - if (addressType === 'ipV4' && address) { - setIpAddress(address); - } - }, []); - const urlTypeOnly = ['url'] as AddressType[]; // Many jobs only run with these address types const api = '/api'; @@ -170,6 +161,15 @@ const Results = (): JSX.Element => { .then(res => res.ip), }); + useEffect(() => { + if (!addressType || addressType === 'empt') { + setAddressType(determineAddressType(address || '')); + } + if (addressType === 'ipV4' && address) { + setIpAddress(address); + } + }, [address, addressType, setIpAddress]); + // Fetch and parse SSL certificate info const [sslResults, updateSslResults] = useMotherHook({ jobId: 'ssl', From 9e426ed55e5e18de15b6272567ae0705623d57f7 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 10 Aug 2023 19:30:21 +0100 Subject: [PATCH 27/94] Rename endpoints to be the same as job IDs --- api/_common/middleware.js | 1 - api/{get-carbon.js => carbon.js} | 0 api/{get-cookies.js => cookies.js} | 0 api/{get-dns.js => dns.js} | 0 api/{dns-sec.js => dnssec.js} | 0 api/{site-features.js => features.js} | 0 api/{find-url-ip.js => get-ip.js} | 0 api/{get-headers.js => headers.js} | 0 api/{check-hsts.js => hsts.js} | 0 api/{content-links.js => linked-pages.js} | 0 api/{check-ports.js => ports.js} | 0 api/{lighthouse-report.js => quality.js} | 0 api/read-robots-txt.js | 45 ---------------- api/{follow-redirects.js => redirects.js} | 0 api/robots-txt.js | 66 +++++++++++++++++++++++ api/{ssl-check.js => ssl.js} | 0 api/{server-status.js => status.js} | 0 api/{get-txt.js => txt-records.js} | 0 api/{whois-lookup.js => whois.js} | 0 src/pages/Results.tsx | 37 +++++++------ 20 files changed, 84 insertions(+), 65 deletions(-) rename api/{get-carbon.js => carbon.js} (100%) rename api/{get-cookies.js => cookies.js} (100%) rename api/{get-dns.js => dns.js} (100%) rename api/{dns-sec.js => dnssec.js} (100%) rename api/{site-features.js => features.js} (100%) rename api/{find-url-ip.js => get-ip.js} (100%) rename api/{get-headers.js => headers.js} (100%) rename api/{check-hsts.js => hsts.js} (100%) rename api/{content-links.js => linked-pages.js} (100%) rename api/{check-ports.js => ports.js} (100%) rename api/{lighthouse-report.js => quality.js} (100%) delete mode 100644 api/read-robots-txt.js rename api/{follow-redirects.js => redirects.js} (100%) create mode 100644 api/robots-txt.js rename api/{ssl-check.js => ssl.js} (100%) rename api/{server-status.js => status.js} (100%) rename api/{get-txt.js => txt-records.js} (100%) rename api/{whois-lookup.js => whois.js} (100%) diff --git a/api/_common/middleware.js b/api/_common/middleware.js index 434c498..7c9c53e 100644 --- a/api/_common/middleware.js +++ b/api/_common/middleware.js @@ -27,7 +27,6 @@ const commonMiddleware = (handler) => { }); } } catch (error) { - console.log(error); callback(null, { statusCode: 500, body: JSON.stringify({ error: error.message }), diff --git a/api/get-carbon.js b/api/carbon.js similarity index 100% rename from api/get-carbon.js rename to api/carbon.js diff --git a/api/get-cookies.js b/api/cookies.js similarity index 100% rename from api/get-cookies.js rename to api/cookies.js diff --git a/api/get-dns.js b/api/dns.js similarity index 100% rename from api/get-dns.js rename to api/dns.js diff --git a/api/dns-sec.js b/api/dnssec.js similarity index 100% rename from api/dns-sec.js rename to api/dnssec.js diff --git a/api/site-features.js b/api/features.js similarity index 100% rename from api/site-features.js rename to api/features.js diff --git a/api/find-url-ip.js b/api/get-ip.js similarity index 100% rename from api/find-url-ip.js rename to api/get-ip.js diff --git a/api/get-headers.js b/api/headers.js similarity index 100% rename from api/get-headers.js rename to api/headers.js diff --git a/api/check-hsts.js b/api/hsts.js similarity index 100% rename from api/check-hsts.js rename to api/hsts.js diff --git a/api/content-links.js b/api/linked-pages.js similarity index 100% rename from api/content-links.js rename to api/linked-pages.js diff --git a/api/check-ports.js b/api/ports.js similarity index 100% rename from api/check-ports.js rename to api/ports.js diff --git a/api/lighthouse-report.js b/api/quality.js similarity index 100% rename from api/lighthouse-report.js rename to api/quality.js diff --git a/api/read-robots-txt.js b/api/read-robots-txt.js deleted file mode 100644 index 50b7449..0000000 --- a/api/read-robots-txt.js +++ /dev/null @@ -1,45 +0,0 @@ -const axios = require('axios'); - -exports.handler = async function(event, context) { - const siteURL = (event.queryStringParameters || event.query).url; - - if (!siteURL) { - return { - statusCode: 400, - body: JSON.stringify({ error: 'Missing url query parameter' }), - }; - } - - let parsedURL; - try { - parsedURL = new URL(siteURL); - } catch (error) { - return { - statusCode: 400, - body: JSON.stringify({ error: 'Invalid url query parameter' }), - }; - } - - const robotsURL = `${parsedURL.protocol}//${parsedURL.hostname}/robots.txt`; - - try { - const response = await axios.get(robotsURL); - - if (response.status === 200) { - return { - statusCode: 200, - body: response.data, - }; - } else { - return { - statusCode: response.status, - body: JSON.stringify({ error: 'Failed to fetch robots.txt', statusCode: response.status }), - }; - } - } catch (error) { - return { - statusCode: 500, - body: JSON.stringify({ error: `Error fetching robots.txt: ${error.message}` }), - }; - } -}; diff --git a/api/follow-redirects.js b/api/redirects.js similarity index 100% rename from api/follow-redirects.js rename to api/redirects.js diff --git a/api/robots-txt.js b/api/robots-txt.js new file mode 100644 index 0000000..c5007ba --- /dev/null +++ b/api/robots-txt.js @@ -0,0 +1,66 @@ +const axios = require('axios'); +const middleware = require('./_common/middleware'); + +const parseRobotsTxt = (content) => { + const lines = content.split('\n'); + const rules = []; + + lines.forEach(line => { + line = line.trim(); // This removes trailing and leading whitespaces + + let match = line.match(/^(Allow|Disallow):\s*(\S*)$/i); + if (match) { + const rule = { + lbl: match[1], + val: match[2], + }; + + rules.push(rule); + } else { + match = line.match(/^(User-agent):\s*(\S*)$/i); + if (match) { + const rule = { + lbl: match[1], + val: match[2], + }; + + rules.push(rule); + } + } + }); + return { robots: rules }; +} + +const handler = async function(url) { + let parsedURL; + try { + parsedURL = new URL(url); + } catch (error) { + return { + statusCode: 400, + body: JSON.stringify({ error: 'Invalid url query parameter' }), + }; + } + + const robotsURL = `${parsedURL.protocol}//${parsedURL.hostname}/robots.txt`; + + try { + const response = await axios.get(robotsURL); + + if (response.status === 200) { + return parseRobotsTxt(response.data); + } else { + return { + statusCode: response.status, + body: JSON.stringify({ error: 'Failed to fetch robots.txt', statusCode: response.status }), + }; + } + } catch (error) { + return { + statusCode: 500, + body: JSON.stringify({ error: `Error fetching robots.txt: ${error.message}` }), + }; + } +}; + +exports.handler = middleware(handler); diff --git a/api/ssl-check.js b/api/ssl.js similarity index 100% rename from api/ssl-check.js rename to api/ssl.js diff --git a/api/server-status.js b/api/status.js similarity index 100% rename from api/server-status.js rename to api/status.js diff --git a/api/get-txt.js b/api/txt-records.js similarity index 100% rename from api/get-txt.js rename to api/txt-records.js diff --git a/api/whois-lookup.js b/api/whois.js similarity index 100% rename from api/whois-lookup.js rename to api/whois.js diff --git a/src/pages/Results.tsx b/src/pages/Results.tsx index 5042b91..f025289 100644 --- a/src/pages/Results.tsx +++ b/src/pages/Results.tsx @@ -165,7 +165,7 @@ const Results = (): JSX.Element => { jobId: 'get-ip', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/find-url-ip?url=${address}`) + fetchRequest: () => fetch(`${api}/get-ip?url=${address}`) .then(res => parseJson(res)) .then(res => res.ip), }); @@ -175,7 +175,7 @@ const Results = (): JSX.Element => { jobId: 'ssl', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/ssl-check?url=${address}`).then((res) => parseJson(res)), + fetchRequest: () => fetch(`${api}/ssl?url=${address}`).then((res) => parseJson(res)), }); // Fetch and parse cookies info @@ -183,7 +183,7 @@ const Results = (): JSX.Element => { jobId: 'cookies', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/get-cookies?url=${address}`) + fetchRequest: () => fetch(`${api}/cookies?url=${address}`) .then(res => parseJson(res)) .then(res => parseCookies(res.cookies)), }); @@ -193,9 +193,8 @@ const Results = (): JSX.Element => { jobId: 'robots-txt', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/read-robots-txt?url=${address}`) - .then(res => res.text()) - .then(res => parseRobotsTxt(res)), + fetchRequest: () => fetch(`${api}/robots-txt?url=${address}`) + .then(res => parseJson(res)), }); // Fetch and parse headers @@ -203,7 +202,7 @@ const Results = (): JSX.Element => { jobId: 'headers', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/get-headers?url=${address}`).then(res => parseJson(res)), + fetchRequest: () => fetch(`${api}/headers?url=${address}`).then(res => parseJson(res)), }); // Fetch and parse DNS records @@ -211,7 +210,7 @@ const Results = (): JSX.Element => { jobId: 'dns', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/get-dns?url=${address}`).then(res => parseJson(res)), + fetchRequest: () => fetch(`${api}/dns?url=${address}`).then(res => parseJson(res)), }); // Fetch and parse Lighthouse performance data @@ -219,7 +218,7 @@ const Results = (): JSX.Element => { jobId: 'quality', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/lighthouse-report?url=${address}`) + fetchRequest: () => fetch(`${api}/quality?url=${address}`) .then(res => parseJson(res)) .then(res => res?.lighthouseResult || { error: 'No Data'}), }); @@ -249,7 +248,7 @@ const Results = (): JSX.Element => { jobId: 'ports', updateLoadingJobs, addressInfo: { address: ipAddress, addressType: 'ipV4', expectedAddressTypes: ['ipV4', 'ipV6'] }, - fetchRequest: () => fetch(`${api}/check-ports?url=${ipAddress}`) + fetchRequest: () => fetch(`${api}/ports?url=${ipAddress}`) .then(res => parseJson(res)), }); @@ -268,7 +267,7 @@ const Results = (): JSX.Element => { jobId: 'txt-records', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/get-txt?url=${address}`).then(res => parseJson(res)), + fetchRequest: () => fetch(`${api}/txt-records?url=${address}`).then(res => parseJson(res)), }); // Fetches URL redirects @@ -276,7 +275,7 @@ const Results = (): JSX.Element => { jobId: 'redirects', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/follow-redirects?url=${address}`).then(res => parseJson(res)), + fetchRequest: () => fetch(`${api}/redirects?url=${address}`).then(res => parseJson(res)), }); // Get current status and response time of server @@ -284,7 +283,7 @@ const Results = (): JSX.Element => { jobId: 'status', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/server-status?url=${address}`).then(res => parseJson(res)), + fetchRequest: () => fetch(`${api}/status?url=${address}`).then(res => parseJson(res)), }); // Get current status and response time of server @@ -308,7 +307,7 @@ const Results = (): JSX.Element => { jobId: 'carbon', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/get-carbon?url=${address}`).then(res => parseJson(res)), + fetchRequest: () => fetch(`${api}/carbon?url=${address}`).then(res => parseJson(res)), }); // Check if a site is on the HSTS preload list @@ -316,7 +315,7 @@ const Results = (): JSX.Element => { jobId: 'hsts', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/check-hsts?url=${address}`).then(res => parseJson(res)), + fetchRequest: () => fetch(`${api}/hsts?url=${address}`).then(res => parseJson(res)), }); // Get a websites listed pages, from sitemap @@ -356,7 +355,7 @@ const Results = (): JSX.Element => { jobId: 'features', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/site-features?url=${address}`) + fetchRequest: () => fetch(`${api}/features?url=${address}`) .then(res => parseJson(res)) .then(res => { if (res.Errors && res.Errors.length > 0) { @@ -371,7 +370,7 @@ const Results = (): JSX.Element => { jobId: 'dnssec', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/dns-sec?url=${address}`).then(res => parseJson(res)), + fetchRequest: () => fetch(`${api}/dnssec?url=${address}`).then(res => parseJson(res)), }); // Run a manual whois lookup on the domain @@ -379,7 +378,7 @@ const Results = (): JSX.Element => { jobId: 'domain', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/whois-lookup?url=${address}`).then(res => parseJson(res)), + fetchRequest: () => fetch(`${api}/whois?url=${address}`).then(res => parseJson(res)), }); // Get the DNS server(s) for a domain, and test DoH/DoT support @@ -395,7 +394,7 @@ const Results = (): JSX.Element => { jobId: 'linked-pages', updateLoadingJobs, addressInfo: { address, addressType, expectedAddressTypes: urlTypeOnly }, - fetchRequest: () => fetch(`${api}/content-links?url=${address}`).then(res => parseJson(res)), + fetchRequest: () => fetch(`${api}/linked-pages?url=${address}`).then(res => parseJson(res)), }); // Get mail config for server, based on DNS records From ca5d43cea15f9e19f7ba2b631c71aee999693edb Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 10 Aug 2023 19:30:44 +0100 Subject: [PATCH 28/94] Increase default execution timeout limit --- server.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index 84f8649..730114b 100644 --- a/server.js +++ b/server.js @@ -49,7 +49,7 @@ fileNames.forEach(file => { const timeout = (ms, jobName = null) => { return new Promise((_, reject) => { setTimeout(() => { - reject(new Error(`Timed out after the ${ms}ms limit${jobName ? `, when executing the ${jobName} task` : ''}`)); + reject(new Error(`Timed out after the ${ms/1000} second limit${jobName ? `, when executing the ${jobName} task` : ''}`)); }, ms); }); } @@ -57,7 +57,7 @@ const timeout = (ms, jobName = null) => { app.get('/api', async (req, res) => { const results = {}; const { url } = req.query; - const maxExecutionTime = process.env.API_TIMEOUT_LIMIT || 10000; + const maxExecutionTime = process.env.API_TIMEOUT_LIMIT || 15000; const handlerPromises = Object.entries(handlers).map(async ([route, handler]) => { const routeName = route.replace(`${API_DIR}/`, ''); @@ -96,6 +96,5 @@ const server = awsServerlessExpress.createServer(app).listen(port, () => { }); exports.handler = (event, context) => { - // console.log(`EVENT: ${JSON.stringify(event)}`); awsServerlessExpress.proxy(server, event, context); }; From 6cb133a46a77858a9059b09cb91e82ab3692622f Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 10 Aug 2023 19:31:15 +0100 Subject: [PATCH 29/94] Fix header width on 404 page --- src/pages/NotFound.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/NotFound.tsx b/src/pages/NotFound.tsx index d916f6c..5a9906b 100644 --- a/src/pages/NotFound.tsx +++ b/src/pages/NotFound.tsx @@ -20,6 +20,10 @@ const AboutContainer = styled.div` color: ${colors.primary}; } .im-drink { font-size: 6rem; } + header { + width: auto; + margin: 1rem; + } `; const HeaderLinkContainer = styled.nav` From 20cc52a304bedc5f646c9c65548d7e6a981e8533 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 10 Aug 2023 21:24:24 +0100 Subject: [PATCH 30/94] Server also serves up app to root / path (if enabled) --- server.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/server.js b/server.js index 730114b..13e5aee 100644 --- a/server.js +++ b/server.js @@ -9,6 +9,7 @@ const app = express(); const API_DIR = '/api'; // Name of the dir containing the lambda functions const dirPath = path.join(__dirname, API_DIR); // Path to the lambda functions dir +const guiPath = path.join(__dirname, 'build'); // Execute the lambda function const executeHandler = async (handler, req) => { @@ -85,12 +86,27 @@ app.use(historyApiFallback({ ] })); -// Serve React App (static files from ./build) -app.use(express.static(path.join(__dirname, 'build'))); - +// Serve up the GUI - if build dir exists, and GUI feature enabled +if (process.env.DISABLE_GUI && process.env.DISABLE_GUI !== 'false') { + app.get('*', (req, res) => { + res.status(500).send( + 'Welcome to Web-Check!
    Access the API endpoints at ' + +'/api' + ); + }); +} else if (!fs.existsSync(guiPath)) { + app.get('*', (req, res) => { + res.status(500).send( + 'Welcome to Web-Check!
    Looks like the GUI app has not yet been compiled, ' + +'run yarn build to continue, then restart the server.' + ); +}); +} else { // GUI enabled, and build files present, let's go!! + app.use(express.static(guiPath)); +} // Create serverless express server -const port = process.env.API_PORT || 3000; +const port = process.env.PORT || 3000; const server = awsServerlessExpress.createServer(app).listen(port, () => { console.log(`Server is running on port ${port}`); }); From 0fd0e537f7b74f2ce75dbb3c02d820152d8d7dae Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Thu, 10 Aug 2023 21:24:52 +0100 Subject: [PATCH 31/94] Dockerfile has updated build command, and uses global start --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 15cb5cd..33c3df7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,7 @@ RUN apt-get update && \ chmod 755 /usr/bin/chromium && \ rm -rf /var/lib/apt/lists/* RUN npm install --force -EXPOSE 8888 +RUN npm run build +EXPOSE ${PORT:-3000} ENV CHROME_PATH='/usr/bin/chromium' -CMD ["npm", "run", "serve"] +CMD ["npm", "start"] From 5f3a99f2b9ced825bb9ed9a5b14852e59c0f4028 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 11 Aug 2023 22:50:37 +0100 Subject: [PATCH 32/94] Safe fallback when no event query params present --- api/_common/middleware.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/_common/middleware.js b/api/_common/middleware.js index 7c9c53e..362db17 100644 --- a/api/_common/middleware.js +++ b/api/_common/middleware.js @@ -4,8 +4,8 @@ const normalizeUrl = (url) => { const commonMiddleware = (handler) => { return async (event, context, callback) => { - - const rawUrl = (event.queryStringParameters || event.query).url; + const queryParams = event.queryStringParameters || event.query || {}; + const rawUrl = queryParams.url; if (!rawUrl) { callback(null, { From c5d8cd1641e70bb75c351fcb1ea564ab4dc4b190 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 11 Aug 2023 22:50:55 +0100 Subject: [PATCH 33/94] Update .gitignore to ignore AWS crap --- .gitignore | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 5f3caba..490b66c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -# Keys +# keys .env # dependencies @@ -7,22 +7,21 @@ /.pnp .pnp.js +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* + # testing /coverage # production /build -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Local Netlify folder +# Random AWS and Netlify crap .netlify +.serverless +.webpack + +# OS generated files +.DS_Store From e1d9b1304501270e7bdc95353456ee588d8df85e Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 11 Aug 2023 22:51:23 +0100 Subject: [PATCH 34/94] Make API location configurable --- src/pages/Results.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Results.tsx b/src/pages/Results.tsx index f025289..be6ee5f 100644 --- a/src/pages/Results.tsx +++ b/src/pages/Results.tsx @@ -158,7 +158,7 @@ const Results = (): JSX.Element => { const urlTypeOnly = ['url'] as AddressType[]; // Many jobs only run with these address types - const api = '/api'; + const api = process.env.REACT_APP_API_ENDPOINT || '/api'; // Where is the API hosted? // Fetch and parse IP address for given URL const [ipAddress, setIpAddress] = useMotherHook({ From 18faeb631bac03dccc05d77a732b74a57e507f50 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 11 Aug 2023 22:51:56 +0100 Subject: [PATCH 35/94] Adds compatibility for deploying direct to AWS lambda --- api/_common/aws-webpack.config.js | 51 + package.json | 16 +- serverless.yml | 179 ++ yarn.lock | 2971 ++++++++++++++++++++++++++++- 4 files changed, 3159 insertions(+), 58 deletions(-) create mode 100644 api/_common/aws-webpack.config.js create mode 100644 serverless.yml diff --git a/api/_common/aws-webpack.config.js b/api/_common/aws-webpack.config.js new file mode 100644 index 0000000..4e10b8e --- /dev/null +++ b/api/_common/aws-webpack.config.js @@ -0,0 +1,51 @@ +const path = require('path'); +const nodeExternals = require('webpack-node-externals'); + +module.exports = { + target: 'node', + mode: 'production', + entry: { + 'carbon': './api/carbon.js', + 'cookies': './api/cookies.js', + 'dns-server': './api/dns-server.js', + 'dns': './api/dns.js', + 'dnssec': './api/dnssec.js', + 'features': './api/features.js', + 'get-ip': './api/get-ip.js', + 'headers': './api/headers.js', + 'hsts': './api/hsts.js', + 'linked-pages': './api/linked-pages.js', + 'mail-config': './api/mail-config.js', + 'ports': './api/ports.js', + 'quality': './api/quality.js', + 'redirects': './api/redirects.js', + 'robots-txt': './api/robots-txt.js', + 'screenshot': './api/screenshot.js', + 'security-txt': './api/security-txt.js', + 'sitemap': './api/sitemap.js', + 'social-tags': './api/social-tags.js', + 'ssl': './api/ssl.js', + 'status': './api/status.js', + 'tech-stack': './api/tech-stack.js', + 'trace-route': './api/trace-route.js', + 'txt-records': './api/txt-records.js', + 'whois': './api/whois.js', + }, + externals: [nodeExternals()], + output: { + filename: '[name].js', + path: path.resolve(__dirname, '.webpack'), + libraryTarget: 'commonjs2' + }, + module: { + rules: [ + { + test: /\.js$/, + use: { + loader: 'babel-loader' + }, + exclude: /node_modules/, + } + ] + } +}; diff --git a/package.json b/package.json index aa20991..9ce96a8 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "scripts": { "dev": "netlify dev", "serve": "netlify serve --offline", - "start": "react-scripts start", + "start": "node server", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" @@ -39,6 +39,7 @@ "axios": "^1.4.0", "cheerio": "^1.0.0-rc.12", "chrome-aws-lambda": "^10.1.0", + "chromium": "^3.0.3", "connect-history-api-fallback": "^2.0.0", "dotenv": "^16.3.1", "flatted": "^3.2.7", @@ -49,7 +50,7 @@ "perf_hooks": "^0.0.1", "psl": "^1.9.0", "puppeteer": "^20.9.0", - "puppeteer-core": "^20.9.0", + "puppeteer-core": "^21.0.3", "react": "^18.2.0", "react-dom": "^18.2.0", "react-masonry-css": "^1.0.16", @@ -60,9 +61,9 @@ "styled-components": "^6.0.5", "traceroute": "^1.0.0", "typescript": "^5.1.6", - "wappalyzer": "^6.10.63", + "wappalyzer": "^6.10.65", "web-vitals": "^3.4.0", - "xml2js": "^0.6.0" + "xml2js": "^0.6.2" }, "eslintConfig": { "extends": [ @@ -85,5 +86,12 @@ "compilerOptions": { "allowJs": true, "outDir": "./dist" + }, + "devDependencies": { + "serverless-domain-manager": "^7.1.1", + "serverless-offline": "^12.0.4", + "serverless-webpack": "^5.13.0", + "webpack": "^5.88.2", + "webpack-node-externals": "^3.0.0" } } diff --git a/serverless.yml b/serverless.yml new file mode 100644 index 0000000..45854e8 --- /dev/null +++ b/serverless.yml @@ -0,0 +1,179 @@ +service: web-check-api + +provider: + name: aws + runtime: nodejs14.x + region: us-east-1 + +functions: + dnssec: + handler: api/dnssec.handler + events: + - http: + path: api/dnssec + method: get + linkedPages: + handler: api/linked-pages.handler + events: + - http: + path: api/linked-pages + method: get + robotsTxt: + handler: api/robots-txt.handler + events: + - http: + path: api/robots-txt + method: get + ssl: + handler: api/ssl.handler + events: + - http: + path: api/ssl + method: get + whois: + handler: api/whois.handler + events: + - http: + path: api/whois + method: get + carbon: + handler: api/carbon.handler + events: + - http: + path: api/carbon + method: get + features: + handler: api/features.handler + events: + - http: + path: api/features + method: get + mailConfig: + handler: api/mail-config.handler + events: + - http: + path: api/mail-config + method: get + screenshot: + handler: api/screenshot.handler + events: + - http: + path: api/screenshot + method: get + status: + handler: api/status.handler + events: + - http: + path: api/status + method: get + cookies: + handler: api/cookies.handler + events: + - http: + path: api/cookies + method: get + getIp: + handler: api/get-ip.handler + events: + - http: + path: api/get-ip + method: get + ports: + handler: api/ports.handler + events: + - http: + path: api/ports + method: get + securityTxt: + handler: api/security-txt.handler + events: + - http: + path: api/security-txt + method: get + techStack: + handler: api/tech-stack.handler + events: + - http: + path: api/tech-stack + method: get + dnsServer: + handler: api/dns-server.handler + events: + - http: + path: api/dns-server + method: get + headers: + handler: api/headers.handler + events: + - http: + path: api/headers + method: get + quality: + handler: api/quality.handler + events: + - http: + path: api/quality + method: get + sitemap: + handler: api/sitemap.handler + events: + - http: + path: api/sitemap + method: get + traceRoute: + handler: api/trace-route.handler + events: + - http: + path: api/trace-route + method: get + dns: + handler: api/dns.handler + events: + - http: + path: api/dns + method: get + hsts: + handler: api/hsts.handler + events: + - http: + path: api/hsts + method: get + redirects: + handler: api/redirects.handler + events: + - http: + path: api/redirects + method: get + socialTags: + handler: api/social-tags.handler + events: + - http: + path: api/social-tags + method: get + txtRecords: + handler: api/txt-records.handler + events: + - http: + path: api/txt-records + method: get + + +plugins: + # - serverless-webpack + - serverless-domain-manager + - serverless-offline + +custom: + webpack: + webpackConfig: 'api/_common/aws-webpack.config.js' + includeModules: true + + customDomain: + domainName: example.com + basePath: 'api' + stage: ${self:provider.stage} + createRoute53Record: true + + serverless-offline: + prefix: '' + httpPort: 3000 diff --git a/yarn.lock b/yarn.lock index 5d101b6..d19f470 100644 --- a/yarn.lock +++ b/yarn.lock @@ -34,6 +34,939 @@ jsonpointer "^5.0.0" leven "^3.1.0" +"@aws-crypto/crc32@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa" + integrity sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/crc32c@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz#016c92da559ef638a84a245eecb75c3e97cb664f" + integrity sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/ie11-detection@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz#640ae66b4ec3395cee6a8e94ebcd9f80c24cd688" + integrity sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q== + dependencies: + tslib "^1.11.1" + +"@aws-crypto/sha1-browser@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz#f9083c00782b24714f528b1a1fef2174002266a3" + integrity sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw== + dependencies: + "@aws-crypto/ie11-detection" "^3.0.0" + "@aws-crypto/supports-web-crypto" "^3.0.0" + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-crypto/sha256-browser@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz#05f160138ab893f1c6ba5be57cfd108f05827766" + integrity sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ== + dependencies: + "@aws-crypto/ie11-detection" "^3.0.0" + "@aws-crypto/sha256-js" "^3.0.0" + "@aws-crypto/supports-web-crypto" "^3.0.0" + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-crypto/sha256-js@3.0.0", "@aws-crypto/sha256-js@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz#f06b84d550d25521e60d2a0e2a90139341e007c2" + integrity sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ== + dependencies: + "@aws-crypto/util" "^3.0.0" + "@aws-sdk/types" "^3.222.0" + tslib "^1.11.1" + +"@aws-crypto/supports-web-crypto@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz#5d1bf825afa8072af2717c3e455f35cda0103ec2" + integrity sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg== + dependencies: + tslib "^1.11.1" + +"@aws-crypto/util@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-3.0.0.tgz#1c7ca90c29293f0883468ad48117937f0fe5bfb0" + integrity sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-utf8-browser" "^3.0.0" + tslib "^1.11.1" + +"@aws-sdk/client-acm@^3.370.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-acm/-/client-acm-3.388.0.tgz#565d8cda99004f65f0fd32c0e1c84cf497e3cdde" + integrity sha512-GO/wwAiH2/9InZ9kOR9ppHYMoz8lSt6aldgdymE3ygenlpvixh3F1fMiDlGeeefHwesouU1Xc8DHvc81T0AkxA== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.388.0" + "@aws-sdk/credential-provider-node" "3.388.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-signing" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-utf8" "^2.0.0" + "@smithy/util-waiter" "^2.0.2" + tslib "^2.5.0" + +"@aws-sdk/client-api-gateway@^3.370.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-api-gateway/-/client-api-gateway-3.388.0.tgz#b84a1e2d62f0314a5a1bf710b03215845dde4944" + integrity sha512-AE9R7BX2mnV2OzOH2+erkbDtTEEzYNBxAQhVQtQ/NtNvYoWLZIJhCUhfC936+zZTywFNFjj+aoiorFb4SvP5lQ== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.388.0" + "@aws-sdk/credential-provider-node" "3.388.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-sdk-api-gateway" "3.387.0" + "@aws-sdk/middleware-signing" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-stream" "^2.0.2" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-apigatewayv2@^3.370.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-apigatewayv2/-/client-apigatewayv2-3.388.0.tgz#335e019a62faf700ad246169a2f0a4f85de19b69" + integrity sha512-yj/zUx1wvzCWWqjyhhMt+jmR2JCIcOED/ohW5p3R7hqbcOhxq8I1Z80eTn6LyMBhD4G/XBzYC3XgMManlY53pg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.388.0" + "@aws-sdk/credential-provider-node" "3.388.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-signing" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-stream" "^2.0.2" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-cloudformation@^3.370.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudformation/-/client-cloudformation-3.388.0.tgz#de95d38b6b363e9ea9ce8dc93270448b7c204925" + integrity sha512-8YjdSi7jwhfavR1sRtoWtqTQ6GNVLARmOjGiVVytidJQVtj9Ryt9/53q1ENE34NOnmiPti0JyIXru6fGJKteXg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.388.0" + "@aws-sdk/credential-provider-node" "3.388.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-signing" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-utf8" "^2.0.0" + "@smithy/util-waiter" "^2.0.2" + fast-xml-parser "4.2.5" + tslib "^2.5.0" + uuid "^8.3.2" + +"@aws-sdk/client-cognito-identity@3.388.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.388.0.tgz#619aea0cdade15aa6d13d44a0a5b8d711a990a29" + integrity sha512-5sCogMJ1utRlwLQiameyOrrcyhueknbsC2YK1G9Y7pgmgUl2zzUo7htQS2luW71SeBHiwkTQa3OZjbmGsotJvg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.388.0" + "@aws-sdk/credential-provider-node" "3.388.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-signing" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-lambda@^3.241.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-lambda/-/client-lambda-3.388.0.tgz#168101fea0c8434916418ada260218ce43921841" + integrity sha512-Xqkp87s9S1hFURZqHCUqHuvV5NQw2jm9H53fJRZIFLFb1HRRbAKHKlKLASw5BgD1qq3TlMscHh8KRCM8a5vwPA== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.388.0" + "@aws-sdk/credential-provider-node" "3.388.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-signing" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/eventstream-serde-browser" "^2.0.2" + "@smithy/eventstream-serde-config-resolver" "^2.0.2" + "@smithy/eventstream-serde-node" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-stream" "^2.0.2" + "@smithy/util-utf8" "^2.0.0" + "@smithy/util-waiter" "^2.0.2" + tslib "^2.5.0" + +"@aws-sdk/client-route-53@^3.370.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-route-53/-/client-route-53-3.388.0.tgz#38648a8c05b573cc925a027bc207ac92e634d21b" + integrity sha512-XuSFs3K0na0zfLpbK01Qd0xtx5W+wAM6ZjWF5yMl8zcRblq/nCxBaK+E+2LmfrLrIsp+EKCA1YMD2fWhSGYspA== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.388.0" + "@aws-sdk/credential-provider-node" "3.388.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-sdk-route53" "3.387.0" + "@aws-sdk/middleware-signing" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@aws-sdk/xml-builder" "3.310.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-utf8" "^2.0.0" + "@smithy/util-waiter" "^2.0.2" + fast-xml-parser "4.2.5" + tslib "^2.5.0" + +"@aws-sdk/client-s3@^3.370.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.388.0.tgz#d9b091d8670583233145a5c4991470c688840790" + integrity sha512-9UN8gtr/4e4YnHb3Kb4VsxGTDe6olkL90ivK09jKwG2SX8m5OY2fIHSjtyqUHDuFb67JOk3WVEMbZEfxfx46+w== + dependencies: + "@aws-crypto/sha1-browser" "3.0.0" + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/client-sts" "3.388.0" + "@aws-sdk/credential-provider-node" "3.388.0" + "@aws-sdk/middleware-bucket-endpoint" "3.387.0" + "@aws-sdk/middleware-expect-continue" "3.387.0" + "@aws-sdk/middleware-flexible-checksums" "3.387.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-location-constraint" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-sdk-s3" "3.387.0" + "@aws-sdk/middleware-signing" "3.387.0" + "@aws-sdk/middleware-ssec" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/signature-v4-multi-region" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@aws-sdk/xml-builder" "3.310.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/eventstream-serde-browser" "^2.0.2" + "@smithy/eventstream-serde-config-resolver" "^2.0.2" + "@smithy/eventstream-serde-node" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-blob-browser" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/hash-stream-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/md5-js" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-stream" "^2.0.2" + "@smithy/util-utf8" "^2.0.0" + "@smithy/util-waiter" "^2.0.2" + fast-xml-parser "4.2.5" + tslib "^2.5.0" + +"@aws-sdk/client-sso@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.387.0.tgz#d2182c09ad8d75a1a8896c2765e6f8729118660f" + integrity sha512-E7uKSvbA0XMKSN5KLInf52hmMpe9/OKo6N9OPffGXdn3fNEQlvyQq3meUkqG7Is0ldgsQMz5EUBNtNybXzr3tQ== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@aws-sdk/client-sts@3.388.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.388.0.tgz#df4363f89de34bd02533056fc335ec8e785f788c" + integrity sha512-y9FAcAYHT8O6T/jqhgsIQUb4gLiSTKD3xtzudDvjmFi8gl0oRIY1npbeckSiK6k07VQugm2s64I0nDnDxtWsBg== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/credential-provider-node" "3.388.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-sdk-sts" "3.387.0" + "@aws-sdk/middleware-signing" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-utf8" "^2.0.0" + fast-xml-parser "4.2.5" + tslib "^2.5.0" + +"@aws-sdk/config-resolver@^3.370.0": + version "3.374.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/config-resolver/-/config-resolver-3.374.0.tgz#753dd47066365be611755a74515235d54e72e10b" + integrity sha512-eTSbmpcgZ97o7PuFls8pH1344OS03nfqq1NO9HxxvoYoZ6DFfUO7kqKeNUhP9LxOF7slyHXajDT7eoPclGnTuw== + dependencies: + "@smithy/config-resolver" "^1.0.1" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-cognito-identity@3.388.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.388.0.tgz#eef13de274198e592b516cdf6f906d2df5a00971" + integrity sha512-j1oyBc0/O76YouOC2wMZuQUfHOjfrKWgBibIwrwqEqacYWMx/IBxZkk9j2fFerIVaKhhMNkZHAGb+qBx0urR/Q== + dependencies: + "@aws-sdk/client-cognito-identity" "3.388.0" + "@aws-sdk/types" "3.387.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-env@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.387.0.tgz#7323eada10228c0157195a922d10638cd65c293c" + integrity sha512-PVqNk7XPIYe5CMYNvELkcALtkl/pIM8/uPtqEtTg+mgnZBeL4fAmgXZiZMahQo1DxP5t/JaK384f6JG+A0qDjA== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-ini@3.388.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.388.0.tgz#284b6dd2da4f3f8f53b2fa1838085148a478b936" + integrity sha512-3dg3A8AiZ5vXkSAYyyI3V/AW3Eo6KQJyE/glA+Nr2M0oAjT4z3vHhS3pf2B+hfKGZBTuKKgxusrrhrQABd/Diw== + dependencies: + "@aws-sdk/credential-provider-env" "3.387.0" + "@aws-sdk/credential-provider-process" "3.387.0" + "@aws-sdk/credential-provider-sso" "3.388.0" + "@aws-sdk/credential-provider-web-identity" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@smithy/credential-provider-imds" "^2.0.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/shared-ini-file-loader" "^2.0.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-node@3.388.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.388.0.tgz#4c1599e2fdd94cff61f1d5568cade8e595cf4da2" + integrity sha512-BqWAkIG08gj/wevpesaZhAjALjfUNVjseHQRk+DNUoHIfyibW7Ahf3q/GIPs11dA2o8ECwR9/fo68Sq+sK799A== + dependencies: + "@aws-sdk/credential-provider-env" "3.387.0" + "@aws-sdk/credential-provider-ini" "3.388.0" + "@aws-sdk/credential-provider-process" "3.387.0" + "@aws-sdk/credential-provider-sso" "3.388.0" + "@aws-sdk/credential-provider-web-identity" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@smithy/credential-provider-imds" "^2.0.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/shared-ini-file-loader" "^2.0.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-process@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.387.0.tgz#114acfbcf9bd289e549fb3fd48acc1a71d7c75b7" + integrity sha512-tQScLHmDlqkQN+mqw4s3cxepEUeHYDhFl5eH+J8puvPqWjXMYpCEdY79SAtWs6SZd4CWiZ0VLeYU6xQBZengbQ== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/shared-ini-file-loader" "^2.0.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-sso@3.388.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.388.0.tgz#39868ebd160d24348287c8a8e57908f6a5d86046" + integrity sha512-RH02+rntaO0UhnSBr42n+7q8HOztc+Dets/hh6cWovf3Yi9s9ghLgYLN9FXpSosfot3XkmT/HOCa+CphAmGN9A== + dependencies: + "@aws-sdk/client-sso" "3.387.0" + "@aws-sdk/token-providers" "3.388.0" + "@aws-sdk/types" "3.387.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/shared-ini-file-loader" "^2.0.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/credential-provider-web-identity@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.387.0.tgz#f15431ce00dbfe4f937b4afc706254759a096396" + integrity sha512-6ueMPl+J3KWv6ZaAWF4Z138QCuBVFZRVAgwbtP3BNqWrrs4Q6TPksOQJ79lRDMpv0EUoyVl04B6lldNlhN8RdA== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/credential-providers@^3.370.0": + version "3.389.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-providers/-/credential-providers-3.389.0.tgz#6e40de6726822904ae73a3df24c43afa0d512179" + integrity sha512-BwGDVg4o/GO7Ql1OeiPThfrG4Y8AYNNYznxepOs3972gvTCOW8mmrmeCkpMi50g3LEDz2emny2kWqEjCaXly+w== + dependencies: + "@aws-sdk/client-cognito-identity" "3.388.0" + "@aws-sdk/client-sso" "3.387.0" + "@aws-sdk/client-sts" "3.388.0" + "@aws-sdk/credential-provider-cognito-identity" "3.388.0" + "@aws-sdk/credential-provider-env" "3.387.0" + "@aws-sdk/credential-provider-ini" "3.388.0" + "@aws-sdk/credential-provider-node" "3.388.0" + "@aws-sdk/credential-provider-process" "3.387.0" + "@aws-sdk/credential-provider-sso" "3.388.0" + "@aws-sdk/credential-provider-web-identity" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@smithy/credential-provider-imds" "^2.0.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-bucket-endpoint@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.387.0.tgz#edcfa94beaec51317de84bf7e12e341a5981b8f7" + integrity sha512-o7Dsq0YTUHFcKXD6+30/fXv/Wzdxqz9WonhCu3ZFPwTDLZgOM4QDDKW8EcC1SplKP1IUyaEli8Affodag9T1cQ== + dependencies: + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-arn-parser" "3.310.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/util-config-provider" "^2.0.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-expect-continue@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.387.0.tgz#2ac9c1f7845b5b266ac8c3cf3210d462a7012733" + integrity sha512-w415a4tjQc6a7isq0AEDWFBC0HWUCHXEDjDl94UACxfMmS9bVabuf04t9CQ+nBBVs6HdiNdfdc/pBR2pRwx2Yg== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-flexible-checksums@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.387.0.tgz#40957a4bae83208ad047053094757cfce9478fc9" + integrity sha512-QlH97rrKlcMyLG+2ps7+DtBHfPyRIpi7sD3y0iko2u3PGXk+PoLPK8wWyGql9sFopOYTl6/Jh2Rb1b6z6NbjEA== + dependencies: + "@aws-crypto/crc32" "3.0.0" + "@aws-crypto/crc32c" "3.0.0" + "@aws-sdk/types" "3.387.0" + "@smithy/is-array-buffer" "^2.0.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-host-header@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.387.0.tgz#17c4948b83bb42ed04bdc2346fce4e4f980691e5" + integrity sha512-EWm9PXSr8dSp7hnRth1U7OfelXQp9dLf1yS1kUL+UhppYDJpjhdP7ql3NI4xJKw8e76sP2FuJYEuzWnJHuWoyQ== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-location-constraint@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.387.0.tgz#e563fd37fb9ba2dd4f929450f38026fd2a633789" + integrity sha512-Ipdry2V58CpDcWD0ZTz6yFtpTASEBxbuWdqUUYW7pOkZ/5GPGH8NhBky7M38iGqAO6FNysvWEVCUpIqNGkI1lw== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-logger@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.387.0.tgz#bbc05eb087989d6addecc58f1baeb39334851e6e" + integrity sha512-FjAvJr1XyaInT81RxUwgifnbXoFJrRBFc64XeFJgFanGIQCWLYxRrK2HV9eBpao/AycbmuoHgLd/f0sa4hZFoQ== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-recursion-detection@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.387.0.tgz#34beba7dc436dcf13065f5ad99cc239f2f6175b9" + integrity sha512-ZF45T785ru8OwvYZw6awD9Z76OwSMM1eZzj2eY+FDz1cHfkpLjxEiti2iIH1FxbyK7n9ZqDUx29lVlCv238YyQ== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-sdk-api-gateway@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-api-gateway/-/middleware-sdk-api-gateway-3.387.0.tgz#dc8fae72bfa7f55630918a453e974bbb1cfddd9c" + integrity sha512-sqpBtnNW6uDWrOGf/7HwV2GHgMWbmG8ZTCAWfoZziIrekSUYeODLcSqRuQQyeRicPW3mjRVwcyZLGZquv070yg== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-sdk-route53@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-route53/-/middleware-sdk-route53-3.387.0.tgz#22af74bcb873c45ea944dd34270e46cd3d8ebbcf" + integrity sha512-ZDr/O6t6zsgwRzXwfEOl8LensB61i5lkIAzaizBurt7N0dNZJZ/bMb+Z/aAfMwlOgPchAfCk6PadFY7lrpPhHw== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-sdk-s3@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.387.0.tgz#35a71ff4d5e38a3cc588a77c7f7a98706f24d30e" + integrity sha512-OIUBDzGhglI6KjXVwPLh7hRbrfCpSTwWRkbXbLrPgZZuzWMoJJ3q59RVkpLnAV9Mdkg6+YA6JTw4k4hcmJblVw== + dependencies: + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-arn-parser" "3.310.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-sdk-sts@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.387.0.tgz#6bd1e4eb17acc7387fa4231da52378ef77e10b1b" + integrity sha512-7ZzRKOJ4V/JDQmKz9z+FjZqw59mrMATEMLR6ff0H0JHMX0Uk5IX8TQB058ss+ar14qeJ4UcteYzCqHNI0O1BHw== + dependencies: + "@aws-sdk/middleware-signing" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-signing@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.387.0.tgz#74bf5a9cf35239b5745a384a9d8f6f92afbd8328" + integrity sha512-oJXlE0MES8gxNLo137PPNNiOICQGOaETTvq3kBSJgb/gtEAxQajMIlaNT7s1wsjOAruFHt4975nCXuY4lpx7GQ== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/property-provider" "^2.0.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/signature-v4" "^2.0.0" + "@smithy/types" "^2.1.0" + "@smithy/util-middleware" "^2.0.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-ssec@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.387.0.tgz#b61c6fa63b25335e408c673201822d6864a7aa34" + integrity sha512-Jtie1gqqcs7ZuYDlz/kuI3CKCXoCL5Ov/Gj5X8/XmwrQJEpuB6z0KY5H1qY0xo+jtAhC8nDPv0GnuLoOfn85hw== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/middleware-user-agent@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.387.0.tgz#aa5f9eb4f3cb4d6e0df879d8d84ccaf4f8baf8e5" + integrity sha512-hTfFTwDtp86xS98BKa+RFuLfcvGftxwzrbZeisZV8hdb4ZhvNXjSxnvM3vetW0GUEnY9xHPSGyp2ERRTinPKFQ== + dependencies: + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/node-config-provider@^3.370.0": + version "3.374.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-config-provider/-/node-config-provider-3.374.0.tgz#4f49f6d1050482c9bae546632de1d6578eae3ec5" + integrity sha512-RsUeDTtslQ9b/slyjAuVqEVZLnZ/jVdNbLaY30oF6FhvZnKpoiN8m7z4oiDjGQ6K2lVuQNdSRGjzI22W+mLwug== + dependencies: + "@smithy/node-config-provider" "^1.0.1" + tslib "^2.5.0" + +"@aws-sdk/signature-v4-multi-region@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.387.0.tgz#f0fab615dd7cff320ba5500611b968ab0581dc44" + integrity sha512-SGuUbEFi8BXYVv4M7Hc0488I7uZbTVBW19j/B7bnyfbKFrndBXM366s/mChx4iELtESQ61AAstyafx5nGj5tIg== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/signature-v4" "^2.0.0" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/smithy-client@^3.370.0": + version "3.374.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/smithy-client/-/smithy-client-3.374.0.tgz#e00e7d9bbf478846c0ac384e22c95159de5eab33" + integrity sha512-YQBdO/Nv5EXBg/qfMF4GgYYLNN3Y/06MyuVBYILC1TKAnMoLy2FV0VOYyediagepAcWPdJqyUq4MCNNBy0CPRg== + dependencies: + "@smithy/smithy-client" "^1.0.3" + tslib "^2.5.0" + +"@aws-sdk/token-providers@3.388.0": + version "3.388.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.388.0.tgz#50000f5ca32b58614542a6e25918bc32585535cb" + integrity sha512-2lo1gFJl624kfjo/YdU6zW+k6dEwhoqjNkDNbOZEFgS1KDofHe9GX8W4/ReKb0Ggho5/EcjzZ53/1CjkzUq4tA== + dependencies: + "@aws-crypto/sha256-browser" "3.0.0" + "@aws-crypto/sha256-js" "3.0.0" + "@aws-sdk/middleware-host-header" "3.387.0" + "@aws-sdk/middleware-logger" "3.387.0" + "@aws-sdk/middleware-recursion-detection" "3.387.0" + "@aws-sdk/middleware-user-agent" "3.387.0" + "@aws-sdk/types" "3.387.0" + "@aws-sdk/util-endpoints" "3.387.0" + "@aws-sdk/util-user-agent-browser" "3.387.0" + "@aws-sdk/util-user-agent-node" "3.387.0" + "@smithy/config-resolver" "^2.0.2" + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/hash-node" "^2.0.2" + "@smithy/invalid-dependency" "^2.0.2" + "@smithy/middleware-content-length" "^2.0.2" + "@smithy/middleware-endpoint" "^2.0.2" + "@smithy/middleware-retry" "^2.0.2" + "@smithy/middleware-serde" "^2.0.2" + "@smithy/middleware-stack" "^2.0.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/property-provider" "^2.0.0" + "@smithy/protocol-http" "^2.0.2" + "@smithy/shared-ini-file-loader" "^2.0.0" + "@smithy/smithy-client" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-body-length-browser" "^2.0.0" + "@smithy/util-body-length-node" "^2.0.0" + "@smithy/util-defaults-mode-browser" "^2.0.2" + "@smithy/util-defaults-mode-node" "^2.0.2" + "@smithy/util-retry" "^2.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@aws-sdk/types@3.387.0", "@aws-sdk/types@^3.222.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.387.0.tgz#15a968344956b2587dbab1224718d72329e050f4" + integrity sha512-YTjFabNwjTF+6yl88f0/tWff018qmmgMmjlw45s6sdVKueWxdxV68U7gepNLF2nhaQPZa6FDOBoA51NaviVs0Q== + dependencies: + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/util-arn-parser@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.310.0.tgz#861ff8810851be52a320ec9e4786f15b5fc74fba" + integrity sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/util-endpoints@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.387.0.tgz#86d7611527ce916c39dfc02641b8be6e0ad8f1f4" + integrity sha512-g7kvuCXehGXHHBw9PkSQdwVyDFmNUZLmfrRmqMyrMDG9QLQrxr4pyWcSaYgTE16yUzhQQOR+QSey+BL6W9/N6g== + dependencies: + "@aws-sdk/types" "3.387.0" + tslib "^2.5.0" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz#b071baf050301adee89051032bd4139bba32cc40" + integrity sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w== + dependencies: + tslib "^2.5.0" + +"@aws-sdk/util-retry@^3.370.0": + version "3.374.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-retry/-/util-retry-3.374.0.tgz#7fd819d5857609b65a1bf06c39701fe5de5ad6cd" + integrity sha512-0p/trhYU+Ys8j3vMnWCvAkSOL6JRMooV9dVlQ+o7EHbQs9kDtnyucMUHU09ahHSIPTA/n/013hv7bzIt3MyKQg== + dependencies: + "@smithy/util-retry" "^1.0.3" + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-browser@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.387.0.tgz#a59409a168a73a3ce08c0ac831593f864490078e" + integrity sha512-lpgSVvDqx+JjHZCTYs/yQSS7J71dPlJeAlvxc7bmx5m+vfwKe07HAnIs+929DngS0QbAp/VaXbTiMFsInLkO4Q== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/types" "^2.1.0" + bowser "^2.11.0" + tslib "^2.5.0" + +"@aws-sdk/util-user-agent-node@3.387.0": + version "3.387.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.387.0.tgz#54ae2e17fb3738c018891bdb67ab4e4cce219e6f" + integrity sha512-r9OVkcWpRYatjLhJacuHFgvO2T5s/Nu5DDbScMrkUD8b4aGIIqsrdZji0vZy9FCjsUFQMM92t9nt4SejrGjChA== + dependencies: + "@aws-sdk/types" "3.387.0" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@aws-sdk/util-utf8-browser@^3.0.0": + version "3.259.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz#3275a6f5eb334f96ca76635b961d3c50259fd9ff" + integrity sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw== + dependencies: + tslib "^2.3.1" + +"@aws-sdk/xml-builder@3.310.0": + version "3.310.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.310.0.tgz#f0236f2103b438d16117e0939a6305ad69b7ff76" + integrity sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw== + dependencies: + tslib "^2.5.0" + "@babel/cli@^7.21.0": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.22.9.tgz#501b3614aeda7399371f6d5991404f069b059986" @@ -1506,6 +2439,266 @@ protobufjs "^7.2.4" yargs "^17.7.2" +"@hapi/accept@^6.0.1": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@hapi/accept/-/accept-6.0.2.tgz#1d3120601b26136f340a73cefa918c7d5324cb07" + integrity sha512-xaTLf29Zeph/B32hekmgxLFsEPuX1xQYyZu0gJ4ZCHKU6nXmBRXfBymtWNEK0souOJcX2XHWUaZU6JzccuuMpg== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/hoek" "^11.0.2" + +"@hapi/ammo@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@hapi/ammo/-/ammo-6.0.1.tgz#1bc9f7102724ff288ca03b721854fc5393ad123a" + integrity sha512-pmL+nPod4g58kXrMcsGLp05O2jF4P2Q3GiL8qYV7nKYEh3cGf+rV4P5Jyi2Uq0agGhVU63GtaSAfBEZOlrJn9w== + dependencies: + "@hapi/hoek" "^11.0.2" + +"@hapi/b64@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@hapi/b64/-/b64-6.0.1.tgz#786b47dc070e14465af49e2428c1025bd06ed3df" + integrity sha512-ZvjX4JQReUmBheeCq+S9YavcnMMHWqx3S0jHNXWIM1kQDxB9cyfSycpVvjfrKcIS8Mh5N3hmu/YKo4Iag9g2Kw== + dependencies: + "@hapi/hoek" "^11.0.2" + +"@hapi/boom@^10.0.0", "@hapi/boom@^10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-10.0.1.tgz#ebb14688275ae150aa6af788dbe482e6a6062685" + integrity sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA== + dependencies: + "@hapi/hoek" "^11.0.2" + +"@hapi/bounce@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@hapi/bounce/-/bounce-3.0.1.tgz#25a51bf95733749c557c6bf948048bffa66435e4" + integrity sha512-G+/Pp9c1Ha4FDP+3Sy/Xwg2O4Ahaw3lIZFSX+BL4uWi64CmiETuZPxhKDUD4xBMOUZbBlzvO8HjiK8ePnhBadA== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/hoek" "^11.0.2" + +"@hapi/bourne@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-3.0.0.tgz#f11fdf7dda62fe8e336fa7c6642d9041f30356d7" + integrity sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w== + +"@hapi/call@^9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@hapi/call/-/call-9.0.1.tgz#569b87d5b67abf0e58fb82a3894a61aaed3ca92e" + integrity sha512-uPojQRqEL1GRZR4xXPqcLMujQGaEpyVPRyBlD8Pp5rqgIwLhtveF9PkixiKru2THXvuN8mUrLeet5fqxKAAMGg== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/hoek" "^11.0.2" + +"@hapi/catbox-memory@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@hapi/catbox-memory/-/catbox-memory-6.0.1.tgz#8f6b04c0cf2ce25da470324df360bd4e8d68b6ec" + integrity sha512-sVb+/ZxbZIvaMtJfAbdyY+QJUQg9oKTwamXpEg/5xnfG5WbJLTjvEn4kIGKz9pN3ENNbIL/bIdctmHmqi/AdGA== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/hoek" "^11.0.2" + +"@hapi/catbox@^12.1.1": + version "12.1.1" + resolved "https://registry.yarnpkg.com/@hapi/catbox/-/catbox-12.1.1.tgz#9339dca0a5b18b3ca0a825ac5dfc916dbc5bab83" + integrity sha512-hDqYB1J+R0HtZg4iPH3LEnldoaBsar6bYp0EonBmNQ9t5CO+1CqgCul2ZtFveW1ReA5SQuze9GPSU7/aecERhw== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/hoek" "^11.0.2" + "@hapi/podium" "^5.0.0" + "@hapi/validate" "^2.0.1" + +"@hapi/content@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@hapi/content/-/content-6.0.0.tgz#2427af3bac8a2f743512fce2a70cbdc365af29df" + integrity sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA== + dependencies: + "@hapi/boom" "^10.0.0" + +"@hapi/cryptiles@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@hapi/cryptiles/-/cryptiles-6.0.1.tgz#7868a9d4233567ed66f0a9caf85fdcc56e980621" + integrity sha512-9GM9ECEHfR8lk5ASOKG4+4ZsEzFqLfhiryIJ2ISePVB92OHLp/yne4m+zn7z9dgvM98TLpiFebjDFQ0UHcqxXQ== + dependencies: + "@hapi/boom" "^10.0.1" + +"@hapi/file@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@hapi/file/-/file-3.0.0.tgz#f1fd824493ac89a6fceaf89c824afc5ae2121c09" + integrity sha512-w+lKW+yRrLhJu620jT3y+5g2mHqnKfepreykvdOcl9/6up8GrQQn+l3FRTsjHTKbkbfQFkuksHpdv2EcpKcJ4Q== + +"@hapi/h2o2@^10.0.0": + version "10.0.3" + resolved "https://registry.yarnpkg.com/@hapi/h2o2/-/h2o2-10.0.3.tgz#558400016ffe3411fb2e1dbd451e819e6ca26ca0" + integrity sha512-+WWG9lG7rpCHq5h+mYRKwsdLC0ZbJ1zxzPvy++OZvk96geunHGZ8eOAVFy4uVz6Vy5AbftNauQwyUAQLVdF4IA== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/hoek" "^11.0.2" + "@hapi/validate" "^2.0.1" + "@hapi/wreck" "^18.0.1" + +"@hapi/hapi@^21.1.0": + version "21.3.2" + resolved "https://registry.yarnpkg.com/@hapi/hapi/-/hapi-21.3.2.tgz#f9f94c1c28ccad1444c838d04070fa1cd0409b33" + integrity sha512-tbm0zmsdUj8iw4NzFV30FST/W4qzh/Lsw6Q5o5gAhOuoirWvxm8a4G3o60bqBw8nXvRNJ8uLtE0RKLlZINxHcQ== + dependencies: + "@hapi/accept" "^6.0.1" + "@hapi/ammo" "^6.0.1" + "@hapi/boom" "^10.0.1" + "@hapi/bounce" "^3.0.1" + "@hapi/call" "^9.0.1" + "@hapi/catbox" "^12.1.1" + "@hapi/catbox-memory" "^6.0.1" + "@hapi/heavy" "^8.0.1" + "@hapi/hoek" "^11.0.2" + "@hapi/mimos" "^7.0.1" + "@hapi/podium" "^5.0.1" + "@hapi/shot" "^6.0.1" + "@hapi/somever" "^4.1.1" + "@hapi/statehood" "^8.1.1" + "@hapi/subtext" "^8.1.0" + "@hapi/teamwork" "^6.0.0" + "@hapi/topo" "^6.0.1" + "@hapi/validate" "^2.0.1" + +"@hapi/heavy@^8.0.1": + version "8.0.1" + resolved "https://registry.yarnpkg.com/@hapi/heavy/-/heavy-8.0.1.tgz#e2be4a6a249005b5a587f7604aafa8ed02461fb6" + integrity sha512-gBD/NANosNCOp6RsYTsjo2vhr5eYA3BEuogk6cxY0QdhllkkTaJFYtTXv46xd6qhBVMbMMqcSdtqey+UQU3//w== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/hoek" "^11.0.2" + "@hapi/validate" "^2.0.1" + +"@hapi/hoek@^11.0.2": + version "11.0.2" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-11.0.2.tgz#cb3ea547daac7de5c9cf1d960c3f35c34f065427" + integrity sha512-aKmlCO57XFZ26wso4rJsW4oTUnrgTFw2jh3io7CAtO9w4UltBNwRXvXIVzzyfkaaLRo3nluP/19msA8vDUUuKw== + +"@hapi/iron@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@hapi/iron/-/iron-7.0.1.tgz#f74bace8dad9340c7c012c27c078504f070f14b5" + integrity sha512-tEZnrOujKpS6jLKliyWBl3A9PaE+ppuL/+gkbyPPDb/l2KSKQyH4lhMkVb+sBhwN+qaxxlig01JRqB8dk/mPxQ== + dependencies: + "@hapi/b64" "^6.0.1" + "@hapi/boom" "^10.0.1" + "@hapi/bourne" "^3.0.0" + "@hapi/cryptiles" "^6.0.1" + "@hapi/hoek" "^11.0.2" + +"@hapi/mimos@^7.0.1": + version "7.0.1" + resolved "https://registry.yarnpkg.com/@hapi/mimos/-/mimos-7.0.1.tgz#5b65c76bb9da28ba34b0092215891f2c72bc899d" + integrity sha512-b79V+BrG0gJ9zcRx1VGcCI6r6GEzzZUgiGEJVoq5gwzuB2Ig9Cax8dUuBauQCFKvl2YWSWyOc8mZ8HDaJOtkew== + dependencies: + "@hapi/hoek" "^11.0.2" + mime-db "^1.52.0" + +"@hapi/nigel@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@hapi/nigel/-/nigel-5.0.1.tgz#a6dfe357e9d48d944e2ffc552bd95cb701d79ee9" + integrity sha512-uv3dtYuB4IsNaha+tigWmN8mQw/O9Qzl5U26Gm4ZcJVtDdB1AVJOwX3X5wOX+A07qzpEZnOMBAm8jjSqGsU6Nw== + dependencies: + "@hapi/hoek" "^11.0.2" + "@hapi/vise" "^5.0.1" + +"@hapi/pez@^6.1.0": + version "6.1.0" + resolved "https://registry.yarnpkg.com/@hapi/pez/-/pez-6.1.0.tgz#64d9f95580fc7d8f1d13437ee4a8676709954fda" + integrity sha512-+FE3sFPYuXCpuVeHQ/Qag1b45clR2o54QoonE/gKHv9gukxQ8oJJZPR7o3/ydDTK6racnCJXxOyT1T93FCJMIg== + dependencies: + "@hapi/b64" "^6.0.1" + "@hapi/boom" "^10.0.1" + "@hapi/content" "^6.0.0" + "@hapi/hoek" "^11.0.2" + "@hapi/nigel" "^5.0.1" + +"@hapi/podium@^5.0.0", "@hapi/podium@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@hapi/podium/-/podium-5.0.1.tgz#f292b4c0ca3118747394a102c6c3340bda96662f" + integrity sha512-eznFTw6rdBhAijXFIlBOMJJd+lXTvqbrBIS4Iu80r2KTVIo4g+7fLy4NKp/8+UnSt5Ox6mJtAlKBU/Sf5080TQ== + dependencies: + "@hapi/hoek" "^11.0.2" + "@hapi/teamwork" "^6.0.0" + "@hapi/validate" "^2.0.1" + +"@hapi/shot@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@hapi/shot/-/shot-6.0.1.tgz#ea84d1810b7c8599d5517c23b4ec55a529d7dc16" + integrity sha512-s5ynMKZXYoDd3dqPw5YTvOR/vjHvMTxc388+0qL0jZZP1+uwXuUD32o9DuuuLsmTlyXCWi02BJl1pBpwRuUrNA== + dependencies: + "@hapi/hoek" "^11.0.2" + "@hapi/validate" "^2.0.1" + +"@hapi/somever@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@hapi/somever/-/somever-4.1.1.tgz#b492c78408303c72cd1a39c5060f35d18a404b27" + integrity sha512-lt3QQiDDOVRatS0ionFDNrDIv4eXz58IibQaZQDOg4DqqdNme8oa0iPWcE0+hkq/KTeBCPtEOjDOBKBKwDumVg== + dependencies: + "@hapi/bounce" "^3.0.1" + "@hapi/hoek" "^11.0.2" + +"@hapi/statehood@^8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@hapi/statehood/-/statehood-8.1.1.tgz#db4bd14c90810a1389763cb0b0b8f221aa4179c1" + integrity sha512-YbK7PSVUA59NArAW5Np0tKRoIZ5VNYUicOk7uJmWZF6XyH5gGL+k62w77SIJb0AoAJ0QdGQMCQ/WOGL1S3Ydow== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/bounce" "^3.0.1" + "@hapi/bourne" "^3.0.0" + "@hapi/cryptiles" "^6.0.1" + "@hapi/hoek" "^11.0.2" + "@hapi/iron" "^7.0.1" + "@hapi/validate" "^2.0.1" + +"@hapi/subtext@^8.1.0": + version "8.1.0" + resolved "https://registry.yarnpkg.com/@hapi/subtext/-/subtext-8.1.0.tgz#58733020a6655bc4d978df9e2f75e31696ff3f91" + integrity sha512-PyaN4oSMtqPjjVxLny1k0iYg4+fwGusIhaom9B2StinBclHs7v46mIW706Y+Wo21lcgulGyXbQrmT/w4dus6ww== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/bourne" "^3.0.0" + "@hapi/content" "^6.0.0" + "@hapi/file" "^3.0.0" + "@hapi/hoek" "^11.0.2" + "@hapi/pez" "^6.1.0" + "@hapi/wreck" "^18.0.1" + +"@hapi/teamwork@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@hapi/teamwork/-/teamwork-6.0.0.tgz#b3a173cf811ba59fc6ee22318a1b51f4561f06e0" + integrity sha512-05HumSy3LWfXpmJ9cr6HzwhAavrHkJ1ZRCmNE2qJMihdM5YcWreWPfyN0yKT2ZjCM92au3ZkuodjBxOibxM67A== + +"@hapi/topo@^6.0.1": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-6.0.2.tgz#f219c1c60da8430228af4c1f2e40c32a0d84bbb4" + integrity sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg== + dependencies: + "@hapi/hoek" "^11.0.2" + +"@hapi/validate@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@hapi/validate/-/validate-2.0.1.tgz#45cf228c4c8cfc61ba2da7e0a5ba93ff3b9afff1" + integrity sha512-NZmXRnrSLK8MQ9y/CMqE9WSspgB9xA41/LlYR0k967aSZebWr4yNrpxIbov12ICwKy4APSlWXZga9jN5p6puPA== + dependencies: + "@hapi/hoek" "^11.0.2" + "@hapi/topo" "^6.0.1" + +"@hapi/vise@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@hapi/vise/-/vise-5.0.1.tgz#5c9f16bcf1c039ddd4b6cad5f32d71eeb6bb7dac" + integrity sha512-XZYWzzRtINQLedPYlIkSkUr7m5Ddwlu99V9elh8CSygXstfv3UnWIXT0QD+wmR0VAG34d2Vx3olqcEhRRoTu9A== + dependencies: + "@hapi/hoek" "^11.0.2" + +"@hapi/wreck@^18.0.1": + version "18.0.1" + resolved "https://registry.yarnpkg.com/@hapi/wreck/-/wreck-18.0.1.tgz#6df04532be25fd128c5244e72ccc21438cf8bb65" + integrity sha512-OLHER70+rZxvDl75xq3xXOfd3e8XIvz8fWY0dqg92UvhZ29zo24vQgfqgHSYhB5ZiuFpSLeriOisAlxAo/1jWg== + dependencies: + "@hapi/boom" "^10.0.1" + "@hapi/bourne" "^3.0.0" + "@hapi/hoek" "^11.0.2" + "@honeycombio/opentelemetry-node@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@honeycombio/opentelemetry-node/-/opentelemetry-node-0.4.0.tgz#974d3a8712bf98ddd50ef07de070d1aa7639da00" @@ -2899,6 +4092,19 @@ unbzip2-stream "1.4.3" yargs "17.7.1" +"@puppeteer/browsers@1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-1.6.0.tgz#d52413a7039e40a5ef72fb13fb6505fd87ce842e" + integrity sha512-R2ib8j329427jtKB/qlz0MJbwfJE/6I8ocJLiajsRqJ2PPI8DbjiNzC3lQZeISXEcjOBVhbG2RafN8SlHdcT+A== + dependencies: + debug "4.3.4" + extract-zip "2.0.1" + progress "2.0.3" + proxy-agent "6.3.0" + tar-fs "3.0.4" + unbzip2-stream "1.4.3" + yargs "17.7.1" + "@remix-run/router@1.7.2": version "1.7.2" resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.7.2.tgz#cba1cf0a04bc04cb66027c51fa600e9cbc388bc8" @@ -3025,6 +4231,45 @@ "@sentry/types" "7.60.0" tslib "^2.4.1 || ^1.9.3" +"@serverless/utils@^6.8.2": + version "6.13.1" + resolved "https://registry.yarnpkg.com/@serverless/utils/-/utils-6.13.1.tgz#bff40cbe82b4337185ab52b6f57bfe647b037700" + integrity sha512-yokWzlsIaAd3TWzNgIDz6l8HZmtYZs9caaLuheZ0IiZ/bDWSCLBWn84HKkdWZOmFnYxejyPNJEOwE59mtSR3Ow== + dependencies: + archive-type "^4.0.0" + chalk "^4.1.2" + ci-info "^3.8.0" + cli-progress-footer "^2.3.2" + content-disposition "^0.5.4" + d "^1.0.1" + decompress "^4.2.1" + event-emitter "^0.3.5" + ext "^1.7.0" + ext-name "^5.0.0" + file-type "^16.5.4" + filenamify "^4.3.0" + get-stream "^6.0.1" + got "^11.8.6" + inquirer "^8.2.5" + js-yaml "^4.1.0" + jwt-decode "^3.1.2" + lodash "^4.17.21" + log "^6.3.1" + log-node "^8.0.3" + make-dir "^4.0.0" + memoizee "^0.4.15" + ms "^2.1.3" + ncjsm "^4.3.2" + node-fetch "^2.6.11" + open "^8.4.2" + p-event "^4.2.0" + supports-color "^8.1.1" + timers-ext "^0.1.7" + type "^2.7.2" + uni-global "^1.0.0" + uuid "^8.3.2" + write-file-atomic "^4.0.2" + "@sinclair/typebox@^0.24.1": version "0.24.51" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" @@ -3035,6 +4280,11 @@ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== +"@sindresorhus/is@^4.0.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== + "@sindresorhus/is@^5.2.0": version "5.5.2" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.5.2.tgz#cbfd816d556b941f65d32cfc6d708359b826e7ea" @@ -3078,6 +4328,633 @@ dotenv "^16.0.2" winston "^3.8.2" +"@smithy/abort-controller@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-1.1.0.tgz#2da0d73c504b93ca8bb83bdc8d6b8208d73f418b" + integrity sha512-5imgGUlZL4dW4YWdMYAKLmal9ny/tlenM81QZY7xYyb76z9Z/QOg7oM5Ak9HQl8QfFTlGVWwcMXl+54jroRgEQ== + dependencies: + "@smithy/types" "^1.2.0" + tslib "^2.5.0" + +"@smithy/abort-controller@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-2.0.2.tgz#e2188247a1723b58d60b0803f3ba24b76a714413" + integrity sha512-ln5Cob0mksym62sLr7NiPOSqJ0jKao4qjfcNLDdgINM1lQI12hXrZBlKdPHbXJqpKhKiECDgonMoqCM8bigq4g== + dependencies: + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/chunked-blob-reader-native@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.0.0.tgz#f6d0eeeb5481026b68b054f45540d924c194d558" + integrity sha512-HM8V2Rp1y8+1343tkZUKZllFhEQPNmpNdgFAncbTsxkZ18/gqjk23XXv3qGyXWp412f3o43ZZ1UZHVcHrpRnCQ== + dependencies: + "@smithy/util-base64" "^2.0.0" + tslib "^2.5.0" + +"@smithy/chunked-blob-reader@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.0.0.tgz#c44fe2c780eaf77f9e5381d982ac99a880cce51b" + integrity sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg== + dependencies: + tslib "^2.5.0" + +"@smithy/config-resolver@^1.0.1": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-1.1.0.tgz#e604fe25a65a77bc21cc01b66e0bee5bc0c9e57b" + integrity sha512-7WD9eZHp46BxAjNGHJLmxhhyeiNWkBdVStd7SUJPUZqQGeIO/REtIrcIfKUfdiHTQ9jyu2SYoqvzqqaFc6987w== + dependencies: + "@smithy/types" "^1.2.0" + "@smithy/util-config-provider" "^1.1.0" + "@smithy/util-middleware" "^1.1.0" + tslib "^2.5.0" + +"@smithy/config-resolver@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-2.0.2.tgz#64496d2f2f9f1482d2e982d3dc057dccc4ba97db" + integrity sha512-0kdsqBL6BdmSbdU6YaDkodVBMua5MuQQluC3nocJ7OJ6PnOuM7i2FEQHE46LBadLqT+CimlDSM+6j91uHNL1ng== + dependencies: + "@smithy/types" "^2.1.0" + "@smithy/util-config-provider" "^2.0.0" + "@smithy/util-middleware" "^2.0.0" + tslib "^2.5.0" + +"@smithy/credential-provider-imds@^2.0.0", "@smithy/credential-provider-imds@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.2.tgz#9096ff1a2ceb235497a62d469ac70086b96022ad" + integrity sha512-mbWFYEZ00LBRDk3WvcXViwpdpkJQcfrM3seuKzFxZnF6wIBLMwrcWcsj+OUC/1L+86m8aQY9imXMAaQsAoGxow== + dependencies: + "@smithy/node-config-provider" "^2.0.2" + "@smithy/property-provider" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + tslib "^2.5.0" + +"@smithy/eventstream-codec@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-2.0.2.tgz#9d81c8d081ac28ba098d98b06cbb39955af1e09b" + integrity sha512-PQZiKx7fMnNwx4zxcUCm82VjnqK6wV4MEHSmMy3taj5dKfXV782IjRGyaDT+8TsmNqVdZIkve5zLRAzh+7kOhA== + dependencies: + "@aws-crypto/crc32" "3.0.0" + "@smithy/types" "^2.1.0" + "@smithy/util-hex-encoding" "^2.0.0" + tslib "^2.5.0" + +"@smithy/eventstream-serde-browser@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.2.tgz#96558c867291d90cbd30927c3c1b480991d48e5f" + integrity sha512-qaHlcFI+ILE+gZV2B/aZMVXc9LG4v1Owa20dHlP0dLOiJ9WByOjtD2qZmYA/HO4qkkDZHEL/0baWc63aqLCHKQ== + dependencies: + "@smithy/eventstream-serde-universal" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/eventstream-serde-config-resolver@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.2.tgz#7f23160a99276a8d3d29d84e2266bc20896cda44" + integrity sha512-iVC7/NFNWfSXllAxFNUuC4QlREdZjMmAOdISb6fwny/4mUDt1EtYLCrXq7gN1mIzhRPwMpL9YvQ8jpgvfA0Jdw== + dependencies: + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/eventstream-serde-node@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.2.tgz#0f48deca0bde6b1216c6457780294ce77416a36a" + integrity sha512-p7py8jDpIS1bRewskwgEgJx1OkFvockA2bJnXtOAPJib42DtyRpp8oV14s2ZpjMq57r9KMCQy2j02g554DNavg== + dependencies: + "@smithy/eventstream-serde-universal" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/eventstream-serde-universal@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.2.tgz#8dcc8bf3704afc09d999d13776362bb0b20d4394" + integrity sha512-zf/hm5VIDsvl+XpI1rop4xwXLKiBUe5pxgjRFdHi7AC1p6Zc8uJfyCExLiMUP/QspoIrVV1xGwFFxRCeddDH3g== + dependencies: + "@smithy/eventstream-codec" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/fetch-http-handler@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-1.1.0.tgz#933694dcc0e1ade205161237a151c1c818479676" + integrity sha512-N22C9R44u5WGlcY+Wuv8EXmCAq62wWwriRAuoczMEwAIjPbvHSthyPSLqI4S7kAST1j6niWg8kwpeJ3ReAv3xg== + dependencies: + "@smithy/protocol-http" "^1.2.0" + "@smithy/querystring-builder" "^1.1.0" + "@smithy/types" "^1.2.0" + "@smithy/util-base64" "^1.1.0" + tslib "^2.5.0" + +"@smithy/fetch-http-handler@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-2.0.2.tgz#dcc0e9d365efd8feef4a54dd96a264735a1446b7" + integrity sha512-Wo2m1RaiXNSLF4J3D62LpdSoj/YYb+6tn0H8is1tSrzr7eXAdiYVBc0wIa23N0wT4zmN0iG/yNY6gTCDQ6799A== + dependencies: + "@smithy/protocol-http" "^2.0.2" + "@smithy/querystring-builder" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/util-base64" "^2.0.0" + tslib "^2.5.0" + +"@smithy/hash-blob-browser@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-2.0.3.tgz#6198dd0382e6ddc9d3f27f7b4f85252c12af054d" + integrity sha512-YQywO2eGG4x3klQZ+R7G8X3oCgrzQaCNC3zYq7kcGibE2Z+q9Lzt3prYiODUwAihDJTCG09xHq1p9IW+z/fp+Q== + dependencies: + "@smithy/chunked-blob-reader" "^2.0.0" + "@smithy/chunked-blob-reader-native" "^2.0.0" + "@smithy/types" "^2.2.0" + tslib "^2.5.0" + +"@smithy/hash-node@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-2.0.2.tgz#e968a3e7ab7072bd12297063e3770ae6d9249dee" + integrity sha512-JKDzZ1YVR7JzOBaJoWy3ToJCE86OQE6D4kOBvvVsu93a3lcF9kv6KYTKBYEWAjwOn/CpK4NH7mKB01OQ8H+aiA== + dependencies: + "@smithy/types" "^2.1.0" + "@smithy/util-buffer-from" "^2.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@smithy/hash-stream-node@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-2.0.3.tgz#3b3a6756792f3e27e617fa372766ba2aa8ca49bf" + integrity sha512-rFUhbuynRMd1DlYewqXRog2bZIMaDL3sNTAK7fg+7DngPpus7hiIGuXn3tJNnCiqiNuxVrhi/ffWpwt21+8DtA== + dependencies: + "@smithy/types" "^2.2.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@smithy/invalid-dependency@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-2.0.2.tgz#1f7b6a860395e9f11fcdbdf3ac22fb95ce863c69" + integrity sha512-inQZQ5gCO3WRWuXpsc1YJ4KBjsvj2qsoU32yTIKznBWTCQe/D5Dp+sSaysqBqxe0VTZ+8nFEHdUMWUX2BxQThw== + dependencies: + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/is-array-buffer@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-1.1.0.tgz#29948072da2b57575aa9898cda863932e842ab11" + integrity sha512-twpQ/n+3OWZJ7Z+xu43MJErmhB/WO/mMTnqR6PwWQShvSJ/emx5d1N59LQZk6ZpTAeuRWrc+eHhkzTp9NFjNRQ== + dependencies: + tslib "^2.5.0" + +"@smithy/is-array-buffer@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz#8fa9b8040651e7ba0b2f6106e636a91354ff7d34" + integrity sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug== + dependencies: + tslib "^2.5.0" + +"@smithy/md5-js@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-2.0.3.tgz#fb9e7ace2ddbc385986e6b75352f1a68f4d9046b" + integrity sha512-pYnD2US3SioMynHytq4n2BsB5L6uJ7pWKxl9sQqvWwYJXcT3VSnJ0/9adbVcWE+GrMRlGO4CpRg9SIKpdQYR+Q== + dependencies: + "@smithy/types" "^2.2.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@smithy/middleware-content-length@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-2.0.2.tgz#6167e8ca52cb5f2b06d3c76fa445080c45baaf25" + integrity sha512-FmHlNfuvYgDZE3fIx0G3rD/wLXfAmBYE4mVc/w6d7RllA7TygPzq2pfHL1iCMzWkWTdoAVnt3h4aavAZnhaxEQ== + dependencies: + "@smithy/protocol-http" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/middleware-endpoint@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.2.tgz#29f4c8ae799ffb0891f96148eb754f8d0a41a97c" + integrity sha512-ropE7/c+g22QeluZ+By/B/WvVep0UFreX+IeRMGIO7EbOUPgqtJRXpbJFdG6JKB1uC+CdaJLn4MnZnVBpcyjuA== + dependencies: + "@smithy/middleware-serde" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/url-parser" "^2.0.2" + "@smithy/util-middleware" "^2.0.0" + tslib "^2.5.0" + +"@smithy/middleware-retry@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-2.0.2.tgz#0d6feb551a5d546c720106435d2a4e7878fd8ea2" + integrity sha512-wtBUXqtZVriiXppYaFkUrybAPhFVX7vebnW/yVPliLMWMcguOMS58qhOYPZe3t9Wki2+mASfyu+kO3An8lAg2A== + dependencies: + "@smithy/protocol-http" "^2.0.2" + "@smithy/service-error-classification" "^2.0.0" + "@smithy/types" "^2.1.0" + "@smithy/util-middleware" "^2.0.0" + "@smithy/util-retry" "^2.0.0" + tslib "^2.5.0" + uuid "^8.3.2" + +"@smithy/middleware-serde@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-2.0.2.tgz#a59f74e981be8b76ef18e272d525e24e3974dc82" + integrity sha512-Kw9xLdlueIaivUWslKB67WZ/cCUg3QnzYVIA3t5KfgsseEEuU4UxXw8NSTvIt71gqQloY+Um8ugS+idgxrWWnw== + dependencies: + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/middleware-stack@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-1.1.0.tgz#04edd33b5db48d880b9942c38459f193144fa533" + integrity sha512-XynYiIvXNea2BbLcppvpNK0zu8o2woJqgnmxqYTn4FWagH/Hr2QIk8LOsUz7BIJ4tooFhmx8urHKCdlPbbPDCA== + dependencies: + tslib "^2.5.0" + +"@smithy/middleware-stack@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz#cd9f442c2788b1ef0ea6b32236d80c76b3c342e9" + integrity sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ== + dependencies: + tslib "^2.5.0" + +"@smithy/node-config-provider@^1.0.1": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-1.1.0.tgz#86c64e4ef6a557863422a236ba10aa7ed51ad85d" + integrity sha512-2G4TlzUnmTrUY26VKTonQqydwb+gtM/mcl+TqDP8CnWtJKVL8ElPpKgLGScP04bPIRY9x2/10lDdoaRXDqPuCw== + dependencies: + "@smithy/property-provider" "^1.2.0" + "@smithy/shared-ini-file-loader" "^1.1.0" + "@smithy/types" "^1.2.0" + tslib "^2.5.0" + +"@smithy/node-config-provider@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-2.0.2.tgz#a15f125f7011ff82610297d899826b7ef7889867" + integrity sha512-9wVJccASfuCctNWrzR0zrDkf0ox3HCHGEhFlWL2LBoghUYuK28pVRBbG69wvnkhlHnB8dDZHagxH+Nq9dm7eWw== + dependencies: + "@smithy/property-provider" "^2.0.2" + "@smithy/shared-ini-file-loader" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/node-http-handler@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-1.1.0.tgz#887cee930b520e08043c9f41e463f8d8f5dae127" + integrity sha512-d3kRriEgaIiGXLziAM8bjnaLn1fthCJeTLZIwEIpzQqe6yPX0a+yQoLCTyjb2fvdLwkMoG4p7THIIB5cj5lkbg== + dependencies: + "@smithy/abort-controller" "^1.1.0" + "@smithy/protocol-http" "^1.2.0" + "@smithy/querystring-builder" "^1.1.0" + "@smithy/types" "^1.2.0" + tslib "^2.5.0" + +"@smithy/node-http-handler@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-2.0.2.tgz#3c4d43352f5412cdb23ca075327ac997f5b03df2" + integrity sha512-lpZjmtmyZqSAtMPsbrLhb7XoAQ2kAHeuLY/csW6I2k+QyFvOk7cZeQsqEngWmZ9SJaeYiDCBINxAIM61i5WGLw== + dependencies: + "@smithy/abort-controller" "^2.0.2" + "@smithy/protocol-http" "^2.0.2" + "@smithy/querystring-builder" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/property-provider@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-1.2.0.tgz#2e4ca34b0994ec6de734316c0093e671a1bfa5c7" + integrity sha512-qlJd9gT751i4T0t/hJAyNGfESfi08Fek8QiLcysoKPgR05qHhG0OYhlaCJHhpXy4ECW0lHyjvFM1smrCLIXVfw== + dependencies: + "@smithy/types" "^1.2.0" + tslib "^2.5.0" + +"@smithy/property-provider@^2.0.0", "@smithy/property-provider@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-2.0.2.tgz#abe091d1e7dc5b617e3418b63eaed11363c96f21" + integrity sha512-DfaZ8cO+d/mgnMzIllcXcU4OYP+omiOl2LYdn/fTGpw/EAQSVzscYV2muV3sDDnuPYQ/r014hUqIxnF+pzh+SQ== + dependencies: + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/protocol-http@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-1.2.0.tgz#a554e4dabb14508f0bc2cdef9c3710e2b294be04" + integrity sha512-GfGfruksi3nXdFok5RhgtOnWe5f6BndzYfmEXISD+5gAGdayFGpjWu5pIqIweTudMtse20bGbc+7MFZXT1Tb8Q== + dependencies: + "@smithy/types" "^1.2.0" + tslib "^2.5.0" + +"@smithy/protocol-http@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-2.0.2.tgz#ec3d45a650cb5554b6aba1c38768f51fc9cf79b5" + integrity sha512-qWu8g1FUy+m36KpO1sREJSF7BaLmjw9AqOuwxLVVSdYz+nUQjc9tFAZ9LB6jJXKdsZFSjfkjHJBbhD78QdE7Rw== + dependencies: + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/querystring-builder@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-1.1.0.tgz#de6306104640ade34e59be33949db6cc64aa9d7f" + integrity sha512-gDEi4LxIGLbdfjrjiY45QNbuDmpkwh9DX4xzrR2AzjjXpxwGyfSpbJaYhXARw9p17VH0h9UewnNQXNwaQyYMDA== + dependencies: + "@smithy/types" "^1.2.0" + "@smithy/util-uri-escape" "^1.1.0" + tslib "^2.5.0" + +"@smithy/querystring-builder@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-2.0.2.tgz#67a1bb503037c4666b5df56ad4b9e10bc525f568" + integrity sha512-H99LOMWEssfwqkOoTs4Y12UiZ7CTGQSX5Nrx5UkYgRbUEpC1GnnaprHiYrqclC58/xr4K76aNchdPyioxewMzA== + dependencies: + "@smithy/types" "^2.1.0" + "@smithy/util-uri-escape" "^2.0.0" + tslib "^2.5.0" + +"@smithy/querystring-parser@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-2.0.2.tgz#d6b2562e7ae29282b144939e5fd439b17bdf61dd" + integrity sha512-L4VtKQ8O4/aWPQJbiFymbhAmxdfLnEaROh/Vs0OstJ7jtOZeBl2QJmuWY2V7hjt64W7V+tEn2sv6vVvnxkm/xQ== + dependencies: + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/service-error-classification@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-1.1.0.tgz#264dd432ae513b3f2ad9fc6f461deda8c516173c" + integrity sha512-OCTEeJ1igatd5kFrS2VDlYbainNNpf7Lj1siFOxnRWqYOP9oNvC5HOJBd3t+Z8MbrmehBtuDJ2QqeBsfeiNkww== + +"@smithy/service-error-classification@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz#bbce07c9c529d9333d40db881fd4a1795dd84892" + integrity sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw== + +"@smithy/shared-ini-file-loader@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-1.1.0.tgz#144a03a303590ef7d465ebcb21ffc2a52efc3389" + integrity sha512-S/v33zvCWzFyGZGlsEF0XsZtNNR281UhR7byk3nRfsgw5lGpg51rK/zjMgulM+h6NSuXaFILaYrw1I1v4kMcuA== + dependencies: + "@smithy/types" "^1.2.0" + tslib "^2.5.0" + +"@smithy/shared-ini-file-loader@^2.0.0", "@smithy/shared-ini-file-loader@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.2.tgz#49b9bf384ece821352f50c8f6cb989edc77d2dbf" + integrity sha512-2VkNOM/82u4vatVdK5nfusgGIlvR48Fkq6me17Oc+V1iyxfR/1x0pG6LzW0br1qlGtzBYFZKmDyviBRcPVFTVw== + dependencies: + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/signature-v4@^2.0.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-2.0.2.tgz#c1ec6d9485a72039060e9a8fe2c02e0afb9d7764" + integrity sha512-YMooDEw/UmGxcXY4qWnSXkbPFsRloluSvyXVT678YPDN/K2AS1GzKfRsvSU7fbccOB4WF8MHZf2UqcRGEltE3Q== + dependencies: + "@smithy/eventstream-codec" "^2.0.2" + "@smithy/is-array-buffer" "^2.0.0" + "@smithy/types" "^2.1.0" + "@smithy/util-hex-encoding" "^2.0.0" + "@smithy/util-middleware" "^2.0.0" + "@smithy/util-uri-escape" "^2.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@smithy/smithy-client@^1.0.3": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-1.1.0.tgz#a546a41cc377c836756b6fa749fc9ae292472985" + integrity sha512-j32SGgVhv2G9nBTmel9u3OXux8KG20ssxuFakJrEeDug3kqbl1qrGzVLCe+Eib402UDtA0Sp1a4NZ2SEXDBxag== + dependencies: + "@smithy/middleware-stack" "^1.1.0" + "@smithy/types" "^1.2.0" + "@smithy/util-stream" "^1.1.0" + tslib "^2.5.0" + +"@smithy/smithy-client@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-2.0.2.tgz#3364bfb4afa73d57712b95cb9319f7c8324a104e" + integrity sha512-mDfokI8WwLU5C0gcQ4ww/zJI/WLGSh2+vdIA42JRnjfYUjJNH/rKfX9YOnn2eBOxl3loATERVUqkHmKe+P8s2Q== + dependencies: + "@smithy/middleware-stack" "^2.0.0" + "@smithy/types" "^2.1.0" + "@smithy/util-stream" "^2.0.2" + tslib "^2.5.0" + +"@smithy/types@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-1.2.0.tgz#9dc65767b0ee3d6681704fcc67665d6fc9b6a34e" + integrity sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA== + dependencies: + tslib "^2.5.0" + +"@smithy/types@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.1.0.tgz#67fd47c25bbb0fd818951891bf7bcf19a8ee2fe6" + integrity sha512-KLsCsqxX0j2l99iP8s0f7LBlcsp7a7ceXGn0LPYPyVOsqmIKvSaPQajq0YevlL4T9Bm+DtcyXfBTbtBcLX1I7A== + dependencies: + tslib "^2.5.0" + +"@smithy/types@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.2.0.tgz#52fa236967729f5a4e2c6c334f1a03930fa86f67" + integrity sha512-Ahpt9KvD0mWeWiyaGo5EBE7KOByLl3jl4CD9Ps/r8qySgzVzo/4qsa+vvstOU3ZEriALmrPqUKIhqHt0Rn+m6g== + dependencies: + tslib "^2.5.0" + +"@smithy/url-parser@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-2.0.2.tgz#af50bd62298b209b1a16c80912a03460b7cb8994" + integrity sha512-X1mHCzrSVDlhVy7d3S7Vq+dTfYzwh4n7xGHhyJumu77nJqIss0lazVug85Pwo0DKIoO314wAOvMnBxNYDa+7wA== + dependencies: + "@smithy/querystring-parser" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/util-base64@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-1.1.0.tgz#2b1854013bfd11aefdd0c035eae789d7c4e56a1e" + integrity sha512-FpYmDmVbOXAxqvoVCwqehUN0zXS+lN8V7VS9O7I8MKeVHdSTsZzlwiMEvGoyTNOXWn8luF4CTDYgNHnZViR30g== + dependencies: + "@smithy/util-buffer-from" "^1.1.0" + tslib "^2.5.0" + +"@smithy/util-base64@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-2.0.0.tgz#1beeabfb155471d1d41c8d0603be1351f883c444" + integrity sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA== + dependencies: + "@smithy/util-buffer-from" "^2.0.0" + tslib "^2.5.0" + +"@smithy/util-body-length-browser@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz#5447853003b4c73da3bc5f3c5e82c21d592d1650" + integrity sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg== + dependencies: + tslib "^2.5.0" + +"@smithy/util-body-length-node@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-2.0.0.tgz#4870b71cb9ded0123d984898ce952ce56896bc53" + integrity sha512-ZV7Z/WHTMxHJe/xL/56qZwSUcl63/5aaPAGjkfynJm4poILjdD4GmFI+V+YWabh2WJIjwTKZ5PNsuvPQKt93Mg== + dependencies: + tslib "^2.5.0" + +"@smithy/util-buffer-from@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-1.1.0.tgz#a000bd9f95c0e8d5b0edb0112f2a586daa5bed49" + integrity sha512-9m6NXE0ww+ra5HKHCHig20T+FAwxBAm7DIdwc/767uGWbRcY720ybgPacQNB96JMOI7xVr/CDa3oMzKmW4a+kw== + dependencies: + "@smithy/is-array-buffer" "^1.1.0" + tslib "^2.5.0" + +"@smithy/util-buffer-from@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz#7eb75d72288b6b3001bc5f75b48b711513091deb" + integrity sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw== + dependencies: + "@smithy/is-array-buffer" "^2.0.0" + tslib "^2.5.0" + +"@smithy/util-config-provider@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-1.1.0.tgz#eb7dcf9bfec9c359430c77dc9671decebeb0b2f9" + integrity sha512-rQ47YpNmF6Is4I9GiE3T3+0xQ+r7RKRKbmHYyGSbyep/0cSf9kteKcI0ssJTvveJ1K4QvwrxXj1tEFp/G2UqxQ== + dependencies: + tslib "^2.5.0" + +"@smithy/util-config-provider@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz#4dd6a793605559d94267312fd06d0f58784b4c38" + integrity sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg== + dependencies: + tslib "^2.5.0" + +"@smithy/util-defaults-mode-browser@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.2.tgz#fb3ad350573ddea0ff7222adc98e9ecc4155b0d3" + integrity sha512-c2tMMjb624XLuzmlRoZpnFOkejVxcgw3WQKdmgdGZYZapcLzXyC0H9JhnXMjQCt30GqLTlsILRNVBYwFRbw/4Q== + dependencies: + "@smithy/property-provider" "^2.0.2" + "@smithy/types" "^2.1.0" + bowser "^2.11.0" + tslib "^2.5.0" + +"@smithy/util-defaults-mode-node@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.2.tgz#2e16e3eb57427c76604c255c38d9e1eacd385d7e" + integrity sha512-gt7m5LLqUtEKldJLyc14DE4kb85vxwomvt9AfEMEvWM4VwfWS1kGJqiStZFb5KNqnQPXw8vvpgLTi8NrWAOXqg== + dependencies: + "@smithy/config-resolver" "^2.0.2" + "@smithy/credential-provider-imds" "^2.0.2" + "@smithy/node-config-provider" "^2.0.2" + "@smithy/property-provider" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + +"@smithy/util-hex-encoding@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-1.1.0.tgz#b5ba919aa076a3fd5e93e368e34ae2b732fa2090" + integrity sha512-7UtIE9eH0u41zpB60Jzr0oNCQ3hMJUabMcKRUVjmyHTXiWDE4vjSqN6qlih7rCNeKGbioS7f/y2Jgym4QZcKFg== + dependencies: + tslib "^2.5.0" + +"@smithy/util-hex-encoding@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz#0aa3515acd2b005c6d55675e377080a7c513b59e" + integrity sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA== + dependencies: + tslib "^2.5.0" + +"@smithy/util-middleware@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-1.1.0.tgz#9f186489437ca2ef753c5e1de2930f76fd1edc14" + integrity sha512-6hhckcBqVgjWAqLy2vqlPZ3rfxLDhFWEmM7oLh2POGvsi7j0tHkbN7w4DFhuBExVJAbJ/qqxqZdRY6Fu7/OezQ== + dependencies: + tslib "^2.5.0" + +"@smithy/util-middleware@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-2.0.0.tgz#706681d4a1686544a2275f68266304233f372c99" + integrity sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA== + dependencies: + tslib "^2.5.0" + +"@smithy/util-retry@^1.0.3": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-1.1.0.tgz#f6e62ec7d7d30f1dd9608991730ba7a86e445047" + integrity sha512-ygQW5HBqYXpR3ua09UciS0sL7UGJzGiktrKkOuEJwARoUuzz40yaEGU6xd9Gs7KBmAaFC8gMfnghHtwZ2nyBCQ== + dependencies: + "@smithy/service-error-classification" "^1.1.0" + tslib "^2.5.0" + +"@smithy/util-retry@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-2.0.0.tgz#7ac5d5f12383a9d9b2a43f9ff25f3866c8727c24" + integrity sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg== + dependencies: + "@smithy/service-error-classification" "^2.0.0" + tslib "^2.5.0" + +"@smithy/util-stream@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-1.1.0.tgz#3f174223bef33af85aa39261fccb908648e13af9" + integrity sha512-w3lsdGsntaLQIrwDWJkIFKrFscgZXwU/oxsse09aSTNv5TckPhDeYea3LhsDrU5MGAG3vprhVZAKr33S45coVA== + dependencies: + "@smithy/fetch-http-handler" "^1.1.0" + "@smithy/node-http-handler" "^1.1.0" + "@smithy/types" "^1.2.0" + "@smithy/util-base64" "^1.1.0" + "@smithy/util-buffer-from" "^1.1.0" + "@smithy/util-hex-encoding" "^1.1.0" + "@smithy/util-utf8" "^1.1.0" + tslib "^2.5.0" + +"@smithy/util-stream@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-2.0.2.tgz#cb4f3c4eca4253f77a780fd861630ed02d67b220" + integrity sha512-Mg9IJcKIu4YKlbzvpp1KLvh4JZLdcPgpxk+LICuDwzZCfxe47R9enVK8dNEiuyiIGK2ExbfvzCVT8IBru62vZw== + dependencies: + "@smithy/fetch-http-handler" "^2.0.2" + "@smithy/node-http-handler" "^2.0.2" + "@smithy/types" "^2.1.0" + "@smithy/util-base64" "^2.0.0" + "@smithy/util-buffer-from" "^2.0.0" + "@smithy/util-hex-encoding" "^2.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.5.0" + +"@smithy/util-uri-escape@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-1.1.0.tgz#a8c5edaf19c0efdb9b51661e840549cf600a1808" + integrity sha512-/jL/V1xdVRt5XppwiaEU8Etp5WHZj609n0xMTuehmCqdoOFbId1M+aEeDWZsQ+8JbEB/BJ6ynY2SlYmOaKtt8w== + dependencies: + tslib "^2.5.0" + +"@smithy/util-uri-escape@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz#19955b1a0f517a87ae77ac729e0e411963dfda95" + integrity sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw== + dependencies: + tslib "^2.5.0" + +"@smithy/util-utf8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-1.1.0.tgz#b791ab1e3f694374edfe22811e39dd8424a1be69" + integrity sha512-p/MYV+JmqmPyjdgyN2UxAeYDj9cBqCjp0C/NsTWnnjoZUVqoeZ6IrW915L9CAKWVECgv9lVQGc4u/yz26/bI1A== + dependencies: + "@smithy/util-buffer-from" "^1.1.0" + tslib "^2.5.0" + +"@smithy/util-utf8@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.0.0.tgz#b4da87566ea7757435e153799df9da717262ad42" + integrity sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ== + dependencies: + "@smithy/util-buffer-from" "^2.0.0" + tslib "^2.5.0" + +"@smithy/util-waiter@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-2.0.2.tgz#32fa0fbd3ec12827daa396f2ec52e5f47478d327" + integrity sha512-7XCEVXDLguf3Og0NIF/KYEAHtrzNXmCdtEwMfOXr4iBKOUWYzNj91YB9O7tLrct8VGvysGA0x2xYzbxMbvF0QQ== + dependencies: + "@smithy/abort-controller" "^2.0.2" + "@smithy/types" "^2.1.0" + tslib "^2.5.0" + "@surma/rollup-plugin-off-main-thread@^2.2.3": version "2.2.3" resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053" @@ -3191,6 +5068,13 @@ "@svgr/plugin-svgo" "^5.5.0" loader-utils "^2.0.0" +"@szmarczak/http-timer@^4.0.5": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" + integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== + dependencies: + defer-to-connect "^2.0.0" + "@szmarczak/http-timer@^5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" @@ -3334,6 +5218,16 @@ dependencies: "@types/node" "*" +"@types/cacheable-request@^6.0.1": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" + integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "^3.1.4" + "@types/node" "*" + "@types/responselike" "^1.0.0" + "@types/connect-history-api-fallback@^1.3.5": version "1.5.0" resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#9fd20b3974bdc2bcd4ac6567e2e0f6885cb2cf41" @@ -3457,7 +5351,7 @@ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== -"@types/http-cache-semantics@^4.0.1": +"@types/http-cache-semantics@*", "@types/http-cache-semantics@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== @@ -3511,6 +5405,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/keyv@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" + integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== + dependencies: + "@types/node" "*" + "@types/long@^4.0.1": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" @@ -3616,6 +5517,13 @@ dependencies: "@types/node" "*" +"@types/responselike@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + "@types/retry@0.12.0": version "0.12.0" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" @@ -4345,6 +6253,13 @@ anymatch@^3.0.3, anymatch@~3.1.2: resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== +archive-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" + integrity sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA== + dependencies: + file-type "^4.2.0" + archiver-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2" @@ -4361,7 +6276,7 @@ archiver-utils@^2.1.0: normalize-path "^3.0.0" readable-stream "^2.0.0" -archiver@^5.3.0: +archiver@^5.3.0, archiver@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.1.tgz#21e92811d6f09ecfce649fbefefe8c79e57cbbb6" integrity sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w== @@ -4472,6 +6387,11 @@ array-timsort@^1.0.3: resolved "https://registry.yarnpkg.com/array-timsort/-/array-timsort-1.0.3.tgz#3c9e4199e54fb2b9c3fe5976396a21614ef0d926" integrity sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ== +array-unflat-js@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/array-unflat-js/-/array-unflat-js-0.1.3.tgz#e1c516a50d9a4e86f127f5c76bae2c51e2981e1e" + integrity sha512-8pljkLj4vfz2i7Tf3yB31tRrszjP8/kwIyABGfcZ1GcHlvdUB0Sbx0WzQkOPMqUBxa/bu4+/NAyHEpDtZJzlJw== + array-union@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" @@ -4900,7 +6820,15 @@ bindings@^1.4.0, bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -bl@^4.0.3: +bl@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bl@^4.0.3, bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== @@ -4918,7 +6846,7 @@ bl@^5.0.0: inherits "^2.0.4" readable-stream "^3.4.0" -bluebird@^3.5.5: +bluebird@^3.5.5, bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== @@ -4961,7 +6889,12 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -boxen@7.1.1, boxen@^7.0.0: +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + +boxen@7.1.1, boxen@^7.0.0, boxen@^7.0.1: version "7.1.1" resolved "https://registry.yarnpkg.com/boxen/-/boxen-7.1.1.tgz#f9ba525413c2fec9cdb88987d835c4f7cad9c8f4" integrity sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog== @@ -5035,6 +6968,19 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" @@ -5045,6 +6991,11 @@ buffer-equal-constant-time@1.0.1: resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -5118,6 +7069,11 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cacheable-lookup@^5.0.3: + version "5.0.4" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" + integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== + cacheable-lookup@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz#3476a8215d046e5a3202a9209dd13fec1f933a27" @@ -5136,6 +7092,19 @@ cacheable-request@^10.2.8: normalize-url "^8.0.0" responselike "^3.0.0" +cacheable-request@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" + integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + cachedir@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8" @@ -5245,7 +7214,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -5347,6 +7316,13 @@ chromium-bidi@0.4.16: dependencies: mitt "3.0.0" +chromium-bidi@0.4.20: + version "0.4.20" + resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.4.20.tgz#1cd56426638452b40b29b7054e83c379e7e2b20a" + integrity sha512-ruHgVZFEv00mAQMz1tQjfjdG63jiPWrQPF6HLlX2ucqLqVTJoWngeBEKHaJ6n1swV/HSvgnBNbtTRIlcVyW3Fw== + dependencies: + mitt "3.0.1" + chromium-bidi@0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.4.5.tgz#a352e755536dde609bd2c77e4b1f0906bff8784e" @@ -5354,7 +7330,21 @@ chromium-bidi@0.4.5: dependencies: mitt "3.0.0" -ci-info@3.8.0, ci-info@^3.2.0: +chromium@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/chromium/-/chromium-3.0.3.tgz#0f776510d6b2749d3cf5632383c6e15a97390e9c" + integrity sha512-TfbzP/3t38Us5xrbb9x87M/y5I/j3jx0zeJhhQ72gjp6dwJuhVP6hBZnBH4wEg7512VVXk9zCfTuPFOdw7bQqg== + dependencies: + cachedir "^2.3.0" + debug "^4.1.0" + extract-zip "^1.7.0" + got "^11.5.1" + progress "^2.0.3" + rimraf "^2.7.1" + tmp "0.0.33" + tunnel "^0.0.6" + +ci-info@3.8.0, ci-info@^3.2.0, ci-info@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== @@ -5402,6 +7392,17 @@ cli-boxes@^3.0.0: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== +cli-color@^2.0.1, cli-color@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.3.tgz#73769ba969080629670f3f2ef69a4bf4e7cc1879" + integrity sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.61" + es6-iterator "^2.0.3" + memoizee "^0.4.15" + timers-ext "^0.1.7" + cli-cursor@^2.0.0, cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -5409,6 +7410,13 @@ cli-cursor@^2.0.0, cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + cli-cursor@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea" @@ -5416,6 +7424,19 @@ cli-cursor@^4.0.0: dependencies: restore-cursor "^4.0.0" +cli-progress-footer@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/cli-progress-footer/-/cli-progress-footer-2.3.2.tgz#1c13ba3c3dd894ef366f4a4f0620b3067284154d" + integrity sha512-uzHGgkKdeA9Kr57eyH1W5HGiNShP8fV1ETq04HDNM1Un6ShXbHhwi/H8LNV9L1fQXKjEw0q5FUkEVNuZ+yZdSw== + dependencies: + cli-color "^2.0.2" + d "^1.0.1" + es5-ext "^0.10.61" + mute-stream "0.0.8" + process-utils "^4.0.0" + timers-ext "^0.1.7" + type "^2.6.0" + cli-progress@^3.11.2: version "3.12.0" resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-3.12.0.tgz#807ee14b66bcc086258e444ad0f19e7d42577942" @@ -5423,11 +7444,21 @@ cli-progress@^3.11.2: dependencies: string-width "^4.2.3" -cli-spinners@^2.6.1: +cli-spinners@^2.5.0, cli-spinners@^2.6.1: version "2.9.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.0.tgz#5881d0ad96381e117bbe07ad91f2008fe6ffd8db" integrity sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g== +cli-sprintf-format@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/cli-sprintf-format/-/cli-sprintf-format-1.1.1.tgz#ec69955c89ef1c61243b52e68015b75c08fb9188" + integrity sha512-BbEjY9BEdA6wagVwTqPvmAwGB24U93rQPBFZUT8lNCDxXzre5LFHQUTJc70czjgUomVg8u8R5kW8oY9DYRFNeg== + dependencies: + cli-color "^2.0.1" + es5-ext "^0.10.53" + sprintf-kit "^2.0.1" + supports-color "^6.1.0" + cli-truncate@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" @@ -5441,6 +7472,11 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -5459,6 +7495,13 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" +clone-response@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== + dependencies: + mimic-response "^1.0.0" + clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" @@ -5690,6 +7733,16 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +concat-stream@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + concordance@5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/concordance/-/concordance-5.0.4.tgz#9896073261adced72f88d60e4d56f8efc4bbbbd2" @@ -5900,7 +7953,7 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cron-parser@4.8.1, cron-parser@^4.1.0: +cron-parser@4.8.1, cron-parser@^4.1.0, cron-parser@^4.2.0: version "4.8.1" resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.8.1.tgz#47062ea63d21d78c10ddedb08ea4c5b6fc2750fb" integrity sha512-jbokKWGcyU4gl6jAfX97E1gDpY12DJ1cLJZmoDzaAln/shZ+S3KBFBuA2Q6WeUN4gJf/8klnV1EfvhA2lK5IRQ== @@ -6243,6 +8296,14 @@ d3-zoom@^2.0.0: d3-selection "2" d3-transition "2" +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" @@ -6279,14 +8340,14 @@ date-time@^3.1.0: dependencies: time-zone "^1.0.0" -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -6324,6 +8385,59 @@ decompress-response@^6.0.0: dependencies: mimic-response "^3.1.0" +decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" + integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== + dependencies: + file-type "^5.2.0" + is-stream "^1.1.0" + tar-stream "^1.5.2" + +decompress-tarbz2@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" + integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== + dependencies: + decompress-tar "^4.1.0" + file-type "^6.1.0" + is-stream "^1.1.0" + seek-bzip "^1.0.5" + unbzip2-stream "^1.0.9" + +decompress-targz@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" + integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== + dependencies: + decompress-tar "^4.1.1" + file-type "^5.2.0" + is-stream "^1.1.0" + +decompress-unzip@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" + integrity sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw== + dependencies: + file-type "^3.8.0" + get-stream "^2.2.0" + pify "^2.3.0" + yauzl "^2.4.2" + +decompress@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" + integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== + dependencies: + decompress-tar "^4.0.0" + decompress-tarbz2 "^4.0.0" + decompress-targz "^4.0.0" + decompress-unzip "^4.0.1" + graceful-fs "^4.1.10" + make-dir "^1.0.0" + pify "^2.3.0" + strip-dirs "^2.0.0" + dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -6382,11 +8496,22 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" -defer-to-connect@^2.0.1: +defer-to-connect@^2.0.0, defer-to-connect@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== +deferred@^0.7.11: + version "0.7.11" + resolved "https://registry.yarnpkg.com/deferred/-/deferred-0.7.11.tgz#8c3f272fd5e6ce48a969cb428c0d233ba2146322" + integrity sha512-8eluCl/Blx4YOGwMapBvXRKxHXhA8ejDXYzEaK8+/gtcm8hRMhSLmXSqDmNUKNc/C8HNSmuyyp/hflhqDAvK2A== + dependencies: + d "^1.0.1" + es5-ext "^0.10.50" + event-emitter "^0.3.5" + next-tick "^1.0.0" + timers-ext "^0.1.7" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -6461,6 +8586,11 @@ dequal@^2.0.3: resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== +desm@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/desm/-/desm-1.3.0.tgz#109f8f134b33d429bff4124ca6ca02f96a07711f" + integrity sha512-RvlHN2gfYA0BpCfjpWzCdQeR6p5U+84f5DzcirLow86UA/OcpwuOqXRC4Oz0bG9rzcJPVtMT6ZgNtjp4qh+uqA== + destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -6764,6 +8894,14 @@ duplexer@^0.1.2: resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== +duration@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/duration/-/duration-0.2.2.tgz#ddf149bc3bc6901150fe9017111d016b3357f529" + integrity sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg== + dependencies: + d "1" + es5-ext "~0.10.46" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -6833,7 +8971,7 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -end-of-stream@^1.1.0, end-of-stream@^1.4.1: +end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== @@ -6992,11 +9130,59 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es5-ext@^0.10.12, es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.49, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@^0.10.62, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46: + version "0.10.62" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5" + integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + next-tick "^1.1.0" + +es6-iterator@^2.0.3, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + es6-promisify@^6.0.0: version "6.1.1" resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-6.1.1.tgz#46837651b7b06bf6fff893d03f29393668d01621" integrity sha512-HBL8I3mIki5C1Cc9QjKUenHtnG0A5/xA8Q/AllRcfiwl2CZFXGK7ddBiCoRwAix4i2KxcQfjtIVcrVbB3vbmwg== +es6-set@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.6.tgz#5669e3b2aa01d61a50ba79964f733673574983b8" + integrity sha512-TE3LgGLDIBX332jq3ypv6bcOpkLO0AslAQo7p2VqX/1N46YNsvIWgvjojjSEnWEGWMhr1qUbYeTSir5J6mFHOw== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + es6-iterator "~2.0.3" + es6-symbol "^3.1.3" + event-emitter "^0.3.5" + type "^2.7.2" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +es6-weak-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -7250,6 +9436,14 @@ eslint@^8.3.0: strip-ansi "^6.0.1" text-table "^0.2.0" +esniff@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/esniff/-/esniff-1.1.0.tgz#c66849229f91464dede2e0d40201ed6abf65f2ac" + integrity sha512-vmHXOeOt7FJLsqofvFk4WB3ejvcHizCd8toXXwADmYfd02p2QwHRgkUbhYDX54y08nqk818CUTWipgZGlyN07g== + dependencies: + d "1" + es5-ext "^0.10.12" + espree@^9.6.0: version "9.6.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" @@ -7308,6 +9502,14 @@ etag@1.8.1, etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + event-target-shim@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" @@ -7338,7 +9540,7 @@ execa@5.1.1, execa@^5.0.0, execa@^5.1.1: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^6.0.0: +execa@^6.0.0, execa@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/execa/-/execa-6.1.0.tgz#cea16dee211ff011246556388effa0818394fb20" integrity sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA== @@ -7452,6 +9654,13 @@ ext-name@^5.0.0: ext-list "^2.0.0" sort-keys-length "^1.0.0" +ext@^1.1.2, ext@^1.4.0, ext@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -7501,6 +9710,16 @@ extract-zip@2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" +extract-zip@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.7.0.tgz#556cc3ae9df7f452c493a0cfb51cc30277940927" + integrity sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA== + dependencies: + concat-stream "^1.6.2" + debug "^2.6.9" + mkdirp "^0.5.4" + yauzl "^2.10.0" + fast-content-type-parse@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-content-type-parse/-/fast-content-type-parse-1.0.0.tgz#cddce00df7d7efb3727d375a598e4904bfcb751c" @@ -7586,6 +9805,13 @@ fast-uri@^2.0.0, fast-uri@^2.1.0: resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-2.2.0.tgz#519a0f849bef714aad10e9753d69d8f758f7445a" integrity sha512-cIusKBIt/R/oI6z/1nyfe2FvGKVTohVRfvkOhvx0nCEW+xf5NoCXjAHcWp93uOUBchzYcsvPlrapAdX1uW+YGg== +fast-xml-parser@4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" + integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== + dependencies: + strnum "^1.0.5" + fastest-levenshtein@1.0.16: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" @@ -7690,7 +9916,7 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^3.2.0: +figures@^3.0.0, figures@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== @@ -7728,6 +9954,15 @@ file-loader@^6.2.0: loader-utils "^2.0.0" schema-utils "^3.0.0" +file-type@^16.5.4: + version "16.5.4" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.5.4.tgz#474fb4f704bee427681f98dd390058a172a6c2fd" + integrity sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw== + dependencies: + readable-web-to-node-stream "^3.0.0" + strtok3 "^6.2.4" + token-types "^4.1.1" + file-type@^18.5.0: version "18.5.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-18.5.0.tgz#604a001ba0d32577d4c3fa420ee104d656b914d2" @@ -7737,6 +9972,26 @@ file-type@^18.5.0: strtok3 "^7.0.0" token-types "^5.0.1" +file-type@^3.8.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + integrity sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA== + +file-type@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" + integrity sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ== + +file-type@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + integrity sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ== + +file-type@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== + file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -7749,11 +10004,25 @@ filelist@^1.0.4: dependencies: minimatch "^5.0.1" +filename-reserved-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" + integrity sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ== + filename-reserved-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-3.0.0.tgz#3d5dd6d4e2d73a3fed2ebc4cd0b3448869a081f7" integrity sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw== +filenamify@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-4.3.0.tgz#62391cb58f02b09971c9d4f9d63b3cf9aba03106" + integrity sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg== + dependencies: + filename-reserved-regex "^2.0.0" + strip-outer "^1.0.1" + trim-repeated "^1.0.0" + filenamify@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-5.1.1.tgz#a1ccc5ae678a5e34f578afcb9b72898264d166d2" @@ -7826,6 +10095,14 @@ find-my-way@^7.6.0: fast-querystring "^1.0.0" safe-regex2 "^2.0.0" +find-requires@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/find-requires/-/find-requires-1.0.0.tgz#a4a750ed37133dee8a9cc8efd2cc56aca01dd96d" + integrity sha512-UME7hNwBfzeISSFQcBEDemEEskpOjI/shPrpJM5PI4DSdn6hX0dmz+2dL70blZER2z8tSnTRL+2rfzlYgtbBoQ== + dependencies: + es5-ext "^0.10.49" + esniff "^1.1.0" + find-up@6.3.0, find-up@^6.0.0, find-up@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" @@ -7857,6 +10134,13 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -8007,6 +10291,15 @@ fs-extra@^10.0.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@^11.1.0, fs-extra@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d" + integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -8048,6 +10341,19 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fs2@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/fs2/-/fs2-0.3.9.tgz#3869e5b2ec7e0622eaa5f4373df540d3d427a9fb" + integrity sha512-WsOqncODWRlkjwll+73bAxVW3JPChDgaPX3DT4iTTm73UmG4VgALa7LaFblP232/DN60itkOrPZ8kaP1feksGQ== + dependencies: + d "^1.0.1" + deferred "^0.7.11" + es5-ext "^0.10.53" + event-emitter "^0.3.5" + ignore "^5.1.8" + memoizee "^0.4.14" + type "^2.1.0" + fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -8141,6 +10447,14 @@ get-port@^6.1.2: resolved "https://registry.yarnpkg.com/get-port/-/get-port-6.1.2.tgz#c1228abb67ba0e17fb346da33b15187833b9c08a" integrity sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw== +get-stream@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + integrity sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA== + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" @@ -8240,7 +10554,7 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.1, glob@^8.0.3: +glob@^8.0.1, glob@^8.0.3, glob@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== @@ -8348,6 +10662,23 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" +got@^11.5.1, got@^11.8.6: + version "11.8.6" + resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" + integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== + dependencies: + "@sindresorhus/is" "^4.0.0" + "@szmarczak/http-timer" "^4.0.5" + "@types/cacheable-request" "^6.0.1" + "@types/responselike" "^1.0.0" + cacheable-lookup "^5.0.3" + cacheable-request "^7.0.2" + decompress-response "^6.0.0" + http2-wrapper "^1.0.0-beta.5.2" + lowercase-keys "^2.0.0" + p-cancelable "^2.0.0" + responselike "^2.0.0" + got@^12.0.0, got@^12.1.0, got@^12.3.1, got@^12.6.1: version "12.6.1" resolved "https://registry.yarnpkg.com/got/-/got-12.6.1.tgz#8869560d1383353204b5a9435f782df9c091f549" @@ -8387,7 +10718,7 @@ graceful-fs@4.2.10: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -8640,7 +10971,7 @@ htmlparser2@^8.0.1: domutils "^3.0.1" entities "^4.4.0" -http-cache-semantics@^4.1.1: +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -8724,6 +11055,14 @@ http-proxy@1.18.1, http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" +http2-wrapper@^1.0.0-beta.5.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" + integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.0.0" + http2-wrapper@^2.1.10: version "2.2.0" resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.0.tgz#b80ad199d216b7d3680195077bd7b9060fa9d7f3" @@ -8794,11 +11133,16 @@ ieee754@^1.1.13, ieee754@^1.2.1: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^5.2.0, ignore@^5.2.4: +ignore@^5.1.8, ignore@^5.2.0, ignore@^5.2.4: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + immer@^9.0.7: version "9.0.21" resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176" @@ -8903,6 +11247,27 @@ inquirer@6.5.2, inquirer@^6.0.0: strip-ansi "^5.1.0" through "^2.3.6" +inquirer@^8.2.5: + version "8.2.6" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.6.tgz#733b74888195d8d400a67ac332011b5fae5ea562" + integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.5.5" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + wrap-ansi "^6.0.1" + inspect-with-kind@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/inspect-with-kind/-/inspect-with-kind-1.0.5.tgz#fce151d4ce89722c82ca8e9860bb96f9167c316c" @@ -9012,7 +11377,7 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-builtin-module@^3.1.0: +is-builtin-module@^3.1.0, is-builtin-module@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== @@ -9146,6 +11511,11 @@ is-installed-globally@^0.4.0: global-dirs "^3.0.0" is-path-inside "^3.0.2" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + is-interactive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-2.0.0.tgz#40c57614593826da1100ade6059778d597f16e90" @@ -9161,6 +11531,11 @@ is-module@^1.0.0: resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== +is-natural-number@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" + integrity sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ== + is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -9254,7 +11629,7 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-promise@^2.1.0: +is-promise@^2.1.0, is-promise@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== @@ -9335,6 +11710,11 @@ is-typedarray@^1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-unicode-supported@^1.1.0, is-unicode-supported@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714" @@ -9482,6 +11862,11 @@ jake@^10.8.5: filelist "^1.0.4" minimatch "^3.1.2" +java-invoke-local@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/java-invoke-local/-/java-invoke-local-0.0.6.tgz#0e04b20b5e306a1e8384846a9ac286790ee6d868" + integrity sha512-gZmQKe1QrfkkMjCn8Qv9cpyJFyogTYqkP5WCobX5RNaHsJzIV/6NvAnlnouOcwKr29QrxLGDGcqYuJ+ae98s1A== + jest-changed-files@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5" @@ -10028,6 +12413,11 @@ jiti@^1.18.2: resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.19.1.tgz#fa99e4b76a23053e0e7cde098efe1704a14c16f1" integrity sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg== +jose@^4.11.2: + version "4.14.4" + resolved "https://registry.yarnpkg.com/jose/-/jose-4.14.4.tgz#59e09204e2670c3164ee24cbfe7115c6f8bff9ca" + integrity sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g== + js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -10159,11 +12549,21 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +jsonpath-plus@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-7.2.0.tgz#7ad94e147b3ed42f7939c315d2b9ce490c5a3899" + integrity sha512-zBfiUPM5nD0YZSBT/o/fbCUlCcepMIdP0CJZxM1+KgA4f2T206f6VAg9e7mX35+KlMaIc5qXW34f3BnwJ3w+RA== + jsonpointer@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== +jsonschema@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.1.tgz#cc4c3f0077fb4542982973d8a083b6b34f482dab" + integrity sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ== + jsonwebtoken@9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz#81d8c901c112c24e497a55daf6b2be1225b40145" @@ -10184,6 +12584,16 @@ jsonwebtoken@9.0.1: object.assign "^4.1.4" object.values "^1.1.6" +jszip@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + junk@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/junk/-/junk-4.0.1.tgz#7ee31f876388c05177fe36529ee714b07b50fbed" @@ -10206,7 +12616,7 @@ jws@^3.2.2: jwa "^1.4.1" safe-buffer "^5.0.1" -jwt-decode@3.1.2: +jwt-decode@3.1.2, jwt-decode@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59" integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A== @@ -10218,7 +12628,7 @@ keep-func-props@^4.0.0: dependencies: mimic-fn "^4.0.0" -keyv@^4.5.2: +keyv@^4.0.0, keyv@^4.5.2: version "4.5.3" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.3.tgz#00873d2b046df737963157bd04f294ca818c9c25" integrity sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug== @@ -10318,6 +12728,13 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + light-my-request@^5.6.1: version "5.10.0" resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-5.10.0.tgz#0a2bbc1d1bb573ed3b78143960920ecdc05bf157" @@ -10504,6 +12921,20 @@ lodash@4.17.21, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17. resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +log-node@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/log-node/-/log-node-8.0.3.tgz#441bf1a72f9f1c28b62f5bf42e9eb3765af74d73" + integrity sha512-1UBwzgYiCIDFs8A0rM2QdBFo8Wd8UQ0HrSTu/MNI+/2zN3NoHRj2fhplurAyuxTYUXu3Oohugq1jAn5s05u1MQ== + dependencies: + ansi-regex "^5.0.1" + cli-color "^2.0.1" + cli-sprintf-format "^1.1.1" + d "^1.0.1" + es5-ext "^0.10.53" + sprintf-kit "^2.0.1" + supports-color "^8.1.1" + type "^2.5.0" + log-process-errors@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/log-process-errors/-/log-process-errors-8.0.0.tgz#f88a9556e4914037ad97ceee24b148dc1b566dfd" @@ -10532,6 +12963,14 @@ log-symbols@^1.0.2: dependencies: chalk "^1.0.0" +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + log-update@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/log-update/-/log-update-5.0.1.tgz#9e928bf70cb183c1f0c9e91d9e6b7115d597ce09" @@ -10552,6 +12991,19 @@ log-update@^2.3.0: cli-cursor "^2.0.0" wrap-ansi "^3.0.1" +log@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/log/-/log-6.3.1.tgz#fcf9bd71fe2274a51ad608dc95c549dd7512146b" + integrity sha512-McG47rJEWOkXTDioZzQNydAVvZNeEkSyLJ1VWkFwfW+o1knW+QSi8D1KjPn/TnctV+q99lkvJNe1f0E1IjfY2A== + dependencies: + d "^1.0.1" + duration "^0.2.2" + es5-ext "^0.10.53" + event-emitter "^0.3.5" + sprintf-kit "^2.0.1" + type "^2.5.0" + uni-global "^1.0.0" + logform@^2.3.2, logform@^2.4.0: version "2.5.1" resolved "https://registry.yarnpkg.com/logform/-/logform-2.5.1.tgz#44c77c34becd71b3a42a3970c77929e52c6ed48b" @@ -10564,6 +13016,11 @@ logform@^2.3.2, logform@^2.4.0: safe-stable-stringify "^2.3.1" triple-beam "^1.3.0" +long-timeout@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" + integrity sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w== + long@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/long/-/long-2.4.0.tgz#9fa180bb1d9500cdc29c4156766a1995e1f4524f" @@ -10593,6 +13050,11 @@ lower-case@^2.0.2: dependencies: tslib "^2.0.3" +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + lowercase-keys@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" @@ -10622,6 +13084,18 @@ lru-cache@^7.14.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.0.tgz#b9e2a6a72a129d81ab317202d93c7691df727e61" integrity sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw== +lru-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ== + dependencies: + es5-ext "~0.10.2" + +luxon@^3.2.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.4.0.tgz#17cb754efecbf76994f05b2a3f1f91fad7ddfde7" + integrity sha512-7eDo4Pt7aGhoCheGFIuq4Xa2fJm4ZpmldpGhjTYBNUYNCN6TIEP6v7chwwwt3KRp7YR+rghbfvjyo3V5y9hgBw== + luxon@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.3.0.tgz#d73ab5b5d2b49a461c47cedbc7e73309b4805b48" @@ -10644,6 +13118,13 @@ magic-string@^0.25.0, magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -10744,6 +13225,20 @@ memoize-one@^6.0.0: resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== +memoizee@^0.4.14, memoizee@^0.4.15: + version "0.4.15" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.15.tgz#e6f3d2da863f318d02225391829a6c5956555b72" + integrity sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ== + dependencies: + d "^1.0.1" + es5-ext "^0.10.53" + es6-weak-map "^2.0.3" + event-emitter "^0.3.5" + is-promise "^2.2.2" + lru-queue "^0.1.0" + next-tick "^1.1.0" + timers-ext "^0.1.7" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -10808,7 +13303,7 @@ micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.2" picomatch "^2.3.1" -mime-db@1.52.0, "mime-db@>= 1.43.0 < 2", mime-db@^1.28.0: +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2", mime-db@^1.28.0, mime-db@^1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== @@ -10845,6 +13340,11 @@ mimic-fn@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + mimic-response@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" @@ -10940,6 +13440,11 @@ mitt@3.0.0: resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.0.tgz#69ef9bd5c80ff6f57473e8d89326d01c414be0bd" integrity sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ== +mitt@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" + integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== + mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -10953,7 +13458,7 @@ mkdirp-classic@^0.5.2: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@^0.5.1, mkdirp@~0.5.1: +mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -11003,7 +13508,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@2.1.3, ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -11030,6 +13535,11 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ== +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -11076,6 +13586,20 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +ncjsm@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ncjsm/-/ncjsm-4.3.2.tgz#87fc4be253481969f691060a919ca194ba5ca879" + integrity sha512-6d1VWA7FY31CpI4Ki97Fpm36jfURkVbpktizp8aoVViTZRQgr/0ddmlKerALSSlzfwQRBeSq1qwwVcBJK4Sk7Q== + dependencies: + builtin-modules "^3.3.0" + deferred "^0.7.11" + es5-ext "^0.10.62" + es6-set "^0.1.6" + ext "^1.7.0" + find-requires "^1.0.0" + fs2 "^0.3.9" + type "^2.7.2" + negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -11251,6 +13775,11 @@ netmask@^2.0.2: resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7" integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg== +next-tick@1, next-tick@^1.0.0, next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + no-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" @@ -11264,7 +13793,7 @@ node-domexception@^1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.12, node-fetch@^2.6.12, node-fetch@^2.6.7: +node-fetch@2.6.12, node-fetch@^2.6.11, node-fetch@^2.6.12, node-fetch@^2.6.7: version "2.6.12" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== @@ -11287,6 +13816,15 @@ node-fetch@^3.0.0, node-fetch@^3.1.1, node-fetch@^3.3.1: fetch-blob "^3.1.4" formdata-polyfill "^4.0.10" +node-fetch@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-forge@^1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -11307,6 +13845,15 @@ node-releases@^2.0.12: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== +node-schedule@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-2.1.1.tgz#6958b2c5af8834954f69bb0a7a97c62b97185de3" + integrity sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ== + dependencies: + cron-parser "^4.2.0" + long-timeout "0.1.1" + sorted-array-functions "^1.3.0" + node-source-walk@^6.0.0, node-source-walk@^6.0.1, node-source-walk@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/node-source-walk/-/node-source-walk-6.0.2.tgz#ba81bc4bc0f6f05559b084bea10be84c3f87f211" @@ -11606,7 +14153,7 @@ onetime@^6.0.0: dependencies: mimic-fn "^4.0.0" -open@^8.0.4, open@^8.0.9, open@^8.4.0: +open@^8.0.4, open@^8.0.9, open@^8.4.0, open@^8.4.2: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== @@ -11647,6 +14194,21 @@ ora@6.3.1: strip-ansi "^7.0.1" wcwidth "^1.0.1" +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + os-name@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/os-name/-/os-name-5.1.0.tgz#4f5ab5edfa6938b590112714f1570fe79f1d957a" @@ -11660,12 +14222,17 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== +p-cancelable@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== + p-cancelable@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== -p-event@^4.1.0: +p-event@^4.1.0, p-event@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== @@ -11759,6 +14326,14 @@ p-map@^2.0.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== +p-memoize@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/p-memoize/-/p-memoize-7.1.1.tgz#53b1d0e6007288f7261cfa11a7603b84c9261bfa" + integrity sha512-DZ/bONJILHkQ721hSr/E9wMz5Am/OTJ9P6LhLFo2Tu+jL8044tgc9LwHO8g4PiaYePnlVVRAJcKmgy8J9MVFrA== + dependencies: + mimic-fn "^4.0.0" + type-fest "^3.0.0" + p-reduce@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-3.0.0.tgz#f11773794792974bd1f7a14c72934248abff4160" @@ -11772,7 +14347,7 @@ p-retry@^4.5.0: "@types/retry" "0.12.0" retry "^0.13.1" -p-retry@^5.1.1: +p-retry@^5.1.1, p-retry@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-5.1.2.tgz#c16eaee4f2016f9161d12da40d3b8b0f2e3c1b76" integrity sha512-couX95waDu98NfNZV+i/iLt+fdVxmI7CbrrdC2uDWfPdUAApyxT4wmDlyOtR5KtTDmkDO0zDScDjDou9YHhd9g== @@ -11849,6 +14424,11 @@ package-json@^8.1.0: registry-url "^6.0.0" semver "^7.3.7" +pako@~1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + parallel-transform@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" @@ -11994,6 +14574,11 @@ path-type@^5.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-5.0.0.tgz#14b01ed7aea7ddf9c7c3f46181d4d04f9c785bb8" integrity sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg== +peek-readable@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72" + integrity sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg== + peek-readable@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.0.0.tgz#7ead2aff25dc40458c60347ea76cfdfd63efdfec" @@ -12034,11 +14619,28 @@ pify@^2.3.0: resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg== + pify@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== + pino-abstract-transport@v1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3" @@ -12750,6 +15352,16 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/process-utils/-/process-utils-4.0.0.tgz#3e5b204e1d38e62fe39ef3144664a1fe94097b9e" + integrity sha512-fMyMQbKCxX51YxR7YGCzPjLsU3yDzXFkP4oi1/Mt5Ixnk7GO/7uUTj8mrCHUwuvozWzI+V7QSJR9cZYnwNOZPg== + dependencies: + ext "^1.4.0" + fs2 "^0.3.9" + memoizee "^0.4.14" + type "^2.1.0" + process-warning@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.2.0.tgz#008ec76b579820a8e5c35d81960525ca64feb626" @@ -12765,7 +15377,7 @@ process@^0.11.10: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== -progress@2.0.3: +progress@2.0.3, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== @@ -12899,7 +15511,7 @@ puppeteer-core@19.7.5: unbzip2-stream "1.4.3" ws "8.12.1" -puppeteer-core@20.9.0, puppeteer-core@^20.9.0: +puppeteer-core@20.9.0: version "20.9.0" resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-20.9.0.tgz#6f4b420001b64419deab38d398a4d9cd071040e6" integrity sha512-H9fYZQzMTRrkboEfPmf7m3CLDN6JvbxXA3qTtS+dFt27tR+CsFHzPsT6pzp6lYL6bJbAPaR0HaPO6uSi+F94Pg== @@ -12911,6 +15523,18 @@ puppeteer-core@20.9.0, puppeteer-core@^20.9.0: devtools-protocol "0.0.1147663" ws "8.13.0" +puppeteer-core@^21.0.3: + version "21.0.3" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-21.0.3.tgz#201bfbf18a9467dbedb10c3c2c9c43462bb9bb84" + integrity sha512-AGvopfkA0jLbW5Ba0m6kBuvRIpLo76PXUK3zJYkXOr9NI1LknJESyai6TtXc6GUSewMkinmyEDx1pFgq900hqg== + dependencies: + "@puppeteer/browsers" "1.6.0" + chromium-bidi "0.4.20" + cross-fetch "4.0.0" + debug "4.3.4" + devtools-protocol "0.0.1147663" + ws "8.13.0" + puppeteer@^20.9.0: version "20.9.0" resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-20.9.0.tgz#7bfb9e37deab9728e13b02ea3fb499b5560c79a7" @@ -13234,7 +15858,7 @@ read-pkg@^7.1.0: parse-json "^5.2.0" type-fest "^2.0.0" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.0, readable-stream@^2.3.5, readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -13267,7 +15891,7 @@ readable-stream@^4.0.0: process "^0.11.10" string_decoder "^1.3.0" -readable-web-to-node-stream@^3.0.2: +readable-web-to-node-stream@^3.0.0, readable-web-to-node-stream@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb" integrity sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw== @@ -13461,7 +16085,7 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== -resolve-alpn@^1.2.0: +resolve-alpn@^1.0.0, resolve-alpn@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== @@ -13522,6 +16146,13 @@ resolve@^2.0.0-next.1, resolve@^2.0.0-next.4: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +responselike@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" + integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== + dependencies: + lowercase-keys "^2.0.0" + responselike@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/responselike/-/responselike-3.0.0.tgz#20decb6c298aff0dbee1c355ca95461d42823626" @@ -13537,6 +16168,14 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + restore-cursor@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9" @@ -13577,6 +16216,13 @@ rimraf@4.4.0: dependencies: glob "^9.2.0" +rimraf@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -13620,6 +16266,13 @@ rxjs@^6.3.3, rxjs@^6.4.0, rxjs@^6.6.2: dependencies: tslib "^1.9.0" +rxjs@^7.5.5: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + safe-array-concat@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060" @@ -13635,7 +16288,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -13752,7 +16405,7 @@ secure-json-parse@^2.5.0: resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== -seek-bzip@^1.0.6: +seek-bzip@^1.0.5, seek-bzip@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.6.tgz#35c4171f55a680916b52a07859ecf3b5857f21c4" integrity sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ== @@ -13851,6 +16504,71 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" +serverless-domain-manager@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/serverless-domain-manager/-/serverless-domain-manager-7.1.1.tgz#ebd377aa112fda747bdba137abda5671338214dd" + integrity sha512-OFY99eOpyQU69HjNwWaFICjzT2K5u98th6rl2+HZx95baKqaYhgIlfh9mKtKLhNKVmUV5iIzKVr5R9uiJECY3A== + dependencies: + "@aws-sdk/client-acm" "^3.370.0" + "@aws-sdk/client-api-gateway" "^3.370.0" + "@aws-sdk/client-apigatewayv2" "^3.370.0" + "@aws-sdk/client-cloudformation" "^3.370.0" + "@aws-sdk/client-route-53" "^3.370.0" + "@aws-sdk/client-s3" "^3.370.0" + "@aws-sdk/config-resolver" "^3.370.0" + "@aws-sdk/credential-providers" "^3.370.0" + "@aws-sdk/node-config-provider" "^3.370.0" + "@aws-sdk/smithy-client" "^3.370.0" + "@aws-sdk/util-retry" "^3.370.0" + +serverless-offline@^12.0.4: + version "12.0.4" + resolved "https://registry.yarnpkg.com/serverless-offline/-/serverless-offline-12.0.4.tgz#93f60be0423867a5ebcf1cbc8d278e7bfa24e210" + integrity sha512-G256wDHI12vE0CJ0uTJMBlfnaN7o7td4GgClvQtuedt/n7vKoUfN0och+LybD6YVGsR5h1xpYjPPPLy2QFqWaA== + dependencies: + "@aws-sdk/client-lambda" "^3.241.0" + "@hapi/boom" "^10.0.0" + "@hapi/h2o2" "^10.0.0" + "@hapi/hapi" "^21.1.0" + "@serverless/utils" "^6.8.2" + array-unflat-js "^0.1.3" + boxen "^7.0.1" + chalk "^5.2.0" + desm "^1.3.0" + execa "^6.1.0" + fs-extra "^11.1.0" + is-wsl "^2.2.0" + java-invoke-local "0.0.6" + jose "^4.11.2" + js-string-escape "^1.0.1" + jsonpath-plus "^7.2.0" + jsonschema "^1.4.1" + jszip "^3.10.1" + luxon "^3.2.0" + node-fetch "^3.3.0" + node-schedule "^2.1.0" + object.hasown "^1.1.2" + p-memoize "^7.1.1" + p-retry "^5.1.2" + velocityjs "^2.0.6" + ws "^8.11.0" + +serverless-webpack@^5.13.0: + version "5.13.0" + resolved "https://registry.yarnpkg.com/serverless-webpack/-/serverless-webpack-5.13.0.tgz#0159dfeae10da502748db0bc761dfa2548cde22e" + integrity sha512-isMEbXbAK1F8YZJfeKgYA5uNuXPFzdHwZyRA9SuMGXVY2L8t1JIzPvRDLZiT4F3uQm16woyal+uaoDyxQo13vg== + dependencies: + archiver "^5.3.1" + bluebird "^3.7.2" + find-yarn-workspace-root "^2.0.0" + fs-extra "^11.1.1" + glob "^8.1.0" + is-builtin-module "^3.2.1" + lodash "^4.17.21" + semver "^7.3.8" + optionalDependencies: + ts-node ">= 8.3.0" + set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -13871,6 +16589,11 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -14049,6 +16772,11 @@ sort-keys@^1.0.0: dependencies: is-plain-obj "^1.0.0" +sorted-array-functions@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz#8605695563294dffb2c9796d602bd8459f7a0dd5" + integrity sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA== + source-list-map@^2.0.0, source-list-map@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" @@ -14192,6 +16920,13 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +sprintf-kit@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/sprintf-kit/-/sprintf-kit-2.0.1.tgz#bb837e8fa4b28f094531d8e33669120027236bb8" + integrity sha512-2PNlcs3j5JflQKcg4wpdqpZ+AjhQJ2OZEo34NXDtlB0tIPG84xaaXhpA8XFacFiwjKA4m49UOYG83y3hbMn/gQ== + dependencies: + es5-ext "^0.10.53" + stable@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" @@ -14441,6 +17176,13 @@ strip-comments@^2.0.1: resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b" integrity sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw== +strip-dirs@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" + integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== + dependencies: + is-natural-number "^4.0.1" + strip-dirs@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-3.0.0.tgz#7c9a5d7822ce079a9db40387a4b20d5654746f42" @@ -14476,11 +17218,31 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== +strip-outer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" + integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== + dependencies: + escape-string-regexp "^1.0.2" + strip-outer@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-2.0.0.tgz#c45c724ed9b1ff6be5f660503791404f4714084b" integrity sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + +strtok3@^6.2.4: + version "6.3.0" + resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-6.3.0.tgz#358b80ffe6d5d5620e19a073aa78ce947a90f9a0" + integrity sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw== + dependencies: + "@tokenizer/token" "^0.3.0" + peek-readable "^4.1.0" + strtok3@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-7.0.0.tgz#868c428b4ade64a8fd8fee7364256001c1a4cbe5" @@ -14557,6 +17319,13 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -14564,7 +17333,7 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.0.0: +supports-color@^8.0.0, supports-color@^8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== @@ -14705,6 +17474,19 @@ tar-fs@3.0.4: pump "^3.0.0" tar-stream "^3.1.5" +tar-stream@^1.5.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + tar-stream@^2.1.4, tar-stream@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" @@ -14892,6 +17674,14 @@ time-zone@^1.0.0: resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" integrity sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA== +timers-ext@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" + integrity sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ== + dependencies: + es5-ext "~0.10.46" + next-tick "1" + tiny-lru@^11.0.1: version "11.0.1" resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-11.0.1.tgz#629d6ddd88bd03c0929722680167f1feadf576f2" @@ -14904,7 +17694,7 @@ tmp-promise@^3.0.2, tmp-promise@^3.0.3: dependencies: tmp "^0.2.0" -tmp@^0.0.33: +tmp@0.0.33, tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== @@ -14923,6 +17713,11 @@ tmpl@1.0.5: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -14970,6 +17765,14 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +token-types@^4.1.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/token-types/-/token-types-4.2.1.tgz#0f897f03665846982806e138977dbe72d44df753" + integrity sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ== + dependencies: + "@tokenizer/token" "^0.3.0" + ieee754 "^1.2.1" + token-types@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/token-types/-/token-types-5.0.1.tgz#aa9d9e6b23c420a675e55413b180635b86a093b4" @@ -15029,6 +17832,13 @@ traceroute@^1.0.0: resolved "https://registry.yarnpkg.com/traceroute/-/traceroute-1.0.0.tgz#4b08996e2a84ee5c5cd6e0eab15f97cd7a56a3db" integrity sha512-g+Ydtg6nkHVGAX3z51IM7utkbAJHtpb53IYXLTwSvD1nyhx2M7bT3QDFc1rj2OSKhemAxYVyYQHKWLFqjcbHPQ== +trim-repeated@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21" + integrity sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg== + dependencies: + escape-string-regexp "^1.0.2" + trim-repeated@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-2.0.0.tgz#5d60556d6d40d9461b7c7e06c3ac20b6b1d50090" @@ -15051,7 +17861,7 @@ ts-interface-checker@^0.1.9: resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699" integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA== -ts-node@^10.9.1: +"ts-node@>= 8.3.0", ts-node@^10.9.1: version "10.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== @@ -15080,7 +17890,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -15090,6 +17900,11 @@ tslib@^2.0.1, tslib@^2.0.3, tslib@^2.3.1, "tslib@^2.4.1 || ^1.9.3", tslib@^2.5.0 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== +tslib@^2.1.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.1.tgz#fd8c9a0ff42590b25703c0acb3de3d3f4ede0410" + integrity sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -15097,6 +17912,11 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -15152,6 +17972,16 @@ type-is@^1.6.16, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.1.0, type@^2.5.0, type@^2.6.0, type@^2.7.2: + version "2.7.2" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0" + integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw== + typed-array-buffer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" @@ -15198,6 +18028,11 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + typescript@^5.0.0, typescript@^5.0.4, typescript@^5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274" @@ -15225,7 +18060,7 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" -unbzip2-stream@1.4.3, unbzip2-stream@^1.4.3: +unbzip2-stream@1.4.3, unbzip2-stream@^1.0.9, unbzip2-stream@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" integrity sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg== @@ -15233,6 +18068,13 @@ unbzip2-stream@1.4.3, unbzip2-stream@^1.4.3: buffer "^5.2.1" through "^2.3.8" +uni-global@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/uni-global/-/uni-global-1.0.0.tgz#3583c449e87a2d9dc270ea221410a649bcdad040" + integrity sha512-WWM3HP+siTxzIWPNUg7hZ4XO8clKi6NoCAJJWnuRL+BAqyFXF8gC03WNyTefGoUXYc47uYgXxpKLIEvo65PEHw== + dependencies: + type "^2.5.0" + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" @@ -15465,6 +18307,13 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +velocityjs@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/velocityjs/-/velocityjs-2.0.6.tgz#fbd5ec5bc6e75a889f73c1d67baddd4e0af7b35a" + integrity sha512-QMYLeYLBX6eqekCin3OPmDAHapaUx3foNFE264ml1/yxRZ8TUUlI1+u6rtN4E8tKNqwzpRPeNgJtjLbgRNK4fw== + dependencies: + debug "^4.3.3" + w3c-hr-time@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" @@ -15495,10 +18344,10 @@ walker@^1.0.7: dependencies: makeerror "1.0.12" -wappalyzer@^6.10.63: - version "6.10.63" - resolved "https://registry.yarnpkg.com/wappalyzer/-/wappalyzer-6.10.63.tgz#90d7d46d8a714a4be3772958c6a679c138e8b6b6" - integrity sha512-y1NV/0thtKTu8pAcCUp3+DE/Tn1255S+lbCL3tFCN4hrzExdL881SEne8sIJTEwugbJw43AJXMPtsuzQ83MdBg== +wappalyzer@^6.10.65: + version "6.10.65" + resolved "https://registry.yarnpkg.com/wappalyzer/-/wappalyzer-6.10.65.tgz#52527ab2575b8a10282f2285bdfc91f110f09f99" + integrity sha512-xBEdR7IhOMgLVfrolV9M5ZAMqL+MHU5YASKLDJkRIFplvr9dCYZhN8JfUksZ+snGO+WiBCPaArhJmwS+jiv9JQ== dependencies: puppeteer "~19.7.0" @@ -15609,6 +18458,11 @@ webpack-manifest-plugin@^4.0.2: tapable "^2.0.0" webpack-sources "^2.2.0" +webpack-node-externals@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz#1a3407c158d547a9feb4229a9e3385b7b60c9917" + integrity sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ== + webpack-sources@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" @@ -15630,7 +18484,7 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.64.4: +webpack@^5.64.4, webpack@^5.88.2: version "5.88.2" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.2.tgz#f62b4b842f1c6ff580f3fcb2ed4f0b579f4c210e" integrity sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ== @@ -16009,6 +18863,15 @@ wrap-ansi@^3.0.1: string-width "^2.1.1" strip-ansi "^4.0.0" +wrap-ansi@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -16050,7 +18913,7 @@ write-file-atomic@^3.0.0, write-file-atomic@^3.0.3: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write-file-atomic@^4.0.1: +write-file-atomic@^4.0.1, write-file-atomic@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== @@ -16063,7 +18926,7 @@ ws@8.12.1: resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.1.tgz#c51e583d79140b5e42e39be48c934131942d4a8f" integrity sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew== -ws@8.13.0, ws@^8.13.0: +ws@8.13.0, ws@^8.11.0, ws@^8.13.0: version "8.13.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== @@ -16083,10 +18946,10 @@ xml-name-validator@^3.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== -xml2js@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.0.tgz#07afc447a97d2bd6507a1f76eeadddb09f7a8282" - integrity sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w== +xml2js@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" + integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== dependencies: sax ">=0.6.0" xmlbuilder "~11.0.0" @@ -16185,7 +19048,7 @@ yargs@^17.0.0, yargs@^17.6.0, yargs@^17.7.2: y18n "^5.0.5" yargs-parser "^21.1.1" -yauzl@^2.10.0: +yauzl@^2.10.0, yauzl@^2.4.2: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g== From e47b39041bc1d5d2cba441d872711ecc8adf17ea Mon Sep 17 00:00:00 2001 From: Gustav Soelberg <69247026+gso-trifork-security@users.noreply.github.com> Date: Sat, 12 Aug 2023 11:27:22 +0200 Subject: [PATCH 36/94] Update exposed ports Ports in use was wrong --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index b4e02b7..4266560 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,5 +4,5 @@ services: container_name: Web-Check image: lissy93/web-check ports: - - 8888:8888 + - 3000:3000 restart: unless-stopped From 15e5ba3cfcfe6089719b6fe09cc557acf5ba0be6 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 12 Aug 2023 16:07:27 +0100 Subject: [PATCH 37/94] Updates start script --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9ce96a8..88ae1e3 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,8 @@ }, "scripts": { "dev": "netlify dev", - "serve": "netlify serve --offline", - "start": "node server", + "serve": "node serve", + "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" From efba42d59dd78129b62af85d7394014f3e4360f1 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 12 Aug 2023 16:07:47 +0100 Subject: [PATCH 38/94] Adds firewall WAF checks --- api/firewall.js | 105 ++++++++++++++++++++++++++++ src/components/Results/Firewall.tsx | 24 +++++++ 2 files changed, 129 insertions(+) create mode 100644 api/firewall.js create mode 100644 src/components/Results/Firewall.tsx diff --git a/api/firewall.js b/api/firewall.js new file mode 100644 index 0000000..f90e108 --- /dev/null +++ b/api/firewall.js @@ -0,0 +1,105 @@ +const axios = require('axios'); +const middleware = require('./_common/middleware'); + +const hasWaf = (waf) => { + return { + hasWaf: true, waf, + } +}; + +const handler = async (url) => { + const fullUrl = url.startsWith('http') ? url : `http://${url}`; + + try { + const response = await axios.get(fullUrl); + + const headers = response.headers; + + if (headers['server'] && headers['server'].includes('cloudflare')) { + return hasWaf('Cloudflare'); + } + + if (headers['x-powered-by'] && headers['x-powered-by'].includes('AWS Lambda')) { + return hasWaf('AWS WAF'); + } + + if (headers['server'] && headers['server'].includes('AkamaiGHost')) { + return hasWaf('Akamai'); + } + + if (headers['server'] && headers['server'].includes('Sucuri')) { + return hasWaf('Sucuri'); + } + + if (headers['server'] && headers['server'].includes('BarracudaWAF')) { + return hasWaf('Barracuda WAF'); + } + + if (headers['server'] && (headers['server'].includes('F5 BIG-IP') || headers['server'].includes('BIG-IP'))) { + return hasWaf('F5 BIG-IP'); + } + + if (headers['x-sucuri-id'] || headers['x-sucuri-cache']) { + return hasWaf('Sucuri CloudProxy WAF'); + } + + if (headers['server'] && headers['server'].includes('FortiWeb')) { + return hasWaf('Fortinet FortiWeb WAF'); + } + + if (headers['server'] && headers['server'].includes('Imperva')) { + return hasWaf('Imperva SecureSphere WAF'); + } + + if (headers['x-protected-by'] && headers['x-protected-by'].includes('Sqreen')) { + return hasWaf('Sqreen'); + } + + if (headers['x-waf-event-info']) { + return hasWaf('Reblaze WAF'); + } + + if (headers['set-cookie'] && headers['set-cookie'].includes('_citrix_ns_id')) { + return hasWaf('Citrix NetScaler'); + } + + if (headers['x-denied-reason'] || headers['x-wzws-requested-method']) { + return hasWaf('WangZhanBao WAF'); + } + + if (headers['x-webcoment']) { + return hasWaf('Webcoment Firewall'); + } + + if (headers['server'] && headers['server'].includes('Yundun')) { + return hasWaf('Yundun WAF'); + } + + if (headers['x-yd-waf-info'] || headers['x-yd-info']) { + return hasWaf('Yundun WAF'); + } + + if (headers['server'] && headers['server'].includes('Safe3WAF')) { + return hasWaf('Safe3 Web Application Firewall'); + } + + if (headers['server'] && headers['server'].includes('NAXSI')) { + return hasWaf('NAXSI WAF'); + } + + if (headers['x-datapower-transactionid']) { + return hasWaf('IBM WebSphere DataPower'); + } + + return { + hasWaf: false, + } + } catch (error) { + return { + statusCode: 500, + body: JSON.stringify({ error: error.message }), + }; + } +}; + +exports.handler = middleware(handler); diff --git a/src/components/Results/Firewall.tsx b/src/components/Results/Firewall.tsx new file mode 100644 index 0000000..080b87d --- /dev/null +++ b/src/components/Results/Firewall.tsx @@ -0,0 +1,24 @@ +import styled from 'styled-components'; +import { Card } from 'components/Form/Card'; +import Row from 'components/Form/Row'; + +const Note = styled.small` +opacity: 0.5; +display: block; +margin-top: 0.5rem; +`; + +const FirewallCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => { + const data = props.data; + return ( + + + { data.waf && } + { !data.hasWaf && ( + *The domain may be protected with a proprietary or custom WAF which we were unable to identify automatically + ) } + + ); +} + +export default FirewallCard; From 1e8d6e868c435ad3e008f05a9ef72ceebf31eabc Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 12 Aug 2023 16:08:06 +0100 Subject: [PATCH 39/94] Adds HTTP security header checks --- api/http-security.js | 25 +++++++++++++++++++++++++ src/components/Results/HttpSecurity.tsx | 17 +++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 api/http-security.js create mode 100644 src/components/Results/HttpSecurity.tsx diff --git a/api/http-security.js b/api/http-security.js new file mode 100644 index 0000000..0cd644d --- /dev/null +++ b/api/http-security.js @@ -0,0 +1,25 @@ +const axios = require('axios'); +const middleware = require('./_common/middleware'); + +const handler = async (url) => { + const fullUrl = url.startsWith('http') ? url : `http://${url}`; + + try { + const response = await axios.get(fullUrl); + const headers = response.headers; + return { + strictTransportPolicy: headers['strict-transport-policy'] ? true : false, + xFrameOptions: headers['x-frame-options'] ? true : false, + xContentTypeOptions: headers['x-content-type-options'] ? true : false, + xXSSProtection: headers['x-xss-protection'] ? true : false, + contentSecurityPolicy: headers['content-security-policy'] ? true : false, + } + } catch (error) { + return { + statusCode: 500, + body: JSON.stringify({ error: error.message }), + }; + } +}; + +exports.handler = middleware(handler); diff --git a/src/components/Results/HttpSecurity.tsx b/src/components/Results/HttpSecurity.tsx new file mode 100644 index 0000000..20c0f49 --- /dev/null +++ b/src/components/Results/HttpSecurity.tsx @@ -0,0 +1,17 @@ +import { Card } from 'components/Form/Card'; +import Row from 'components/Form/Row'; + +const HttpSecurityCard = (props: { data: any, title: string, actionButtons: any }): JSX.Element => { + const data = props.data; + return ( + + + + + + + + ); +} + +export default HttpSecurityCard; From b0008823da01cdae7218e8b816c0839101da7325 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sat, 12 Aug 2023 16:08:22 +0100 Subject: [PATCH 40/94] Adds docs for WAF and HTTP sec headers --- src/utils/docs.ts | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/utils/docs.ts b/src/utils/docs.ts index 0913217..6852410 100644 --- a/src/utils/docs.ts +++ b/src/utils/docs.ts @@ -310,6 +310,7 @@ const docs: Doc[] = [ description: 'This check determines the DNS server(s) that the requested URL / IP resolves to. Also fires off a rudimentary check to see if the DNS server supports DoH, and weather it\'s vulnerable to DNS cache poisoning.', use: '', resources: [], + screenshot: 'https://i.ibb.co/tKpL8F9/Screenshot-from-2023-08-12-15-43-12.png', }, { id: 'tech-stack', @@ -323,6 +324,7 @@ const docs: Doc[] = [ { title: 'Wappalyzer fingerprints', link: 'https://github.com/wappalyzer/wappalyzer/tree/master/src/technologies'}, { title: 'BuiltWith - Check what tech a site is using', link: 'https://builtwith.com/'}, ], + screenshot: 'https://i.ibb.co/bBQSQNz/Screenshot-from-2023-08-12-15-43-46.png', }, { id: 'sitemap', @@ -402,6 +404,43 @@ const docs: Doc[] = [ ], screenshot: 'https://i.ibb.co/yqhwx5G/Screenshot-from-2023-07-29-18-22-20.png', }, + { + id: 'firewall', + title: 'Firewall Detection', + description: 'A WAF or web application firewall helps protect web applications by filtering and monitoring HTTP traffic between a web application and the Internet. It typically protects web applications from attacks such as cross-site forgery, cross-site-scripting (XSS), file inclusion, and SQL injection, among others.', + use: 'It\'s useful to understand if a site is using a WAF, and which firewall software / service it is using, as this provides an insight into the sites protection against several attack vectors, but also may reveal vulnerabilities in the firewall itself.', + resources: [ + { title: 'What is a WAF (via Cloudflare Learning)', link: 'https://www.cloudflare.com/learning/ddos/glossary/web-application-firewall-waf/' }, + { title: 'OWASP - Web Application Firewalls', link: 'https://owasp.org/www-community/Web_Application_Firewall' }, + { title: 'Web Application Firewall Best Practices', link: 'https://owasp.org/www-pdf-archive/Best_Practices_Guide_WAF_v104.en.pdf' }, + { title: 'WAF - Wiki', link: 'https://en.wikipedia.org/wiki/Web_application_firewall' }, + ], + screenshot: 'https://i.ibb.co/MfcxQt2/Screenshot-from-2023-08-12-15-40-52.png', + }, + { + id: 'http-security', + title: 'HTTP Security Features', + description: 'Correctly configured security HTTP headers adds a layer of protection against common attacks to your site. The main headers to be aware of are: ' + + 'HTTP Strict Transport Security (HSTS): Enforces the use of HTTPS, mitigating man-in-the-middle attacks and protocol downgrade attempts. ' + + 'Content Security Policy (CSP): Constrains web page resources to prevent cross-site scripting and data injection attacks. ' + + 'X-Content-Type-Options: Prevents browsers from MIME-sniffing a response away from the declared content type, curbing MIME-type confusion attacks. ' + + 'X-Frame-Options: Protects users from clickjacking attacks by controlling whether a browser should render the page in a ,