diff --git a/package.json b/package.json index 5ab7cb8bb..4950f7869 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@babel/preset-env": "^7.11.5", "@babel/register": "^7.11.5", "@oclif/dev-cli": "^1.22.2", + "babel-plugin-module-resolver": "^4.0.0", "babel-plugin-istanbul": "^6.0.0", "cross-env": "^7.0.2", "eslint": "^7.9.0", diff --git a/packages/cli-snapshot/package.json b/packages/cli-snapshot/package.json index d4396a937..1436bc87f 100644 --- a/packages/cli-snapshot/package.json +++ b/packages/cli-snapshot/package.json @@ -36,9 +36,8 @@ "@percy/core": "^1.0.0-beta.13", "@percy/dom": "^1.0.0-beta.13", "@percy/logger": "^1.0.0-beta.13", - "cors": "^2.8.5", - "express": "^4.17.1", "globby": "^11.0.1", + "serve-handler": "^6.1.3", "yaml": "^1.10.0" } } diff --git a/packages/cli-snapshot/src/commands/snapshot.js b/packages/cli-snapshot/src/commands/snapshot.js index c7a733132..d7bb8d143 100644 --- a/packages/cli-snapshot/src/commands/snapshot.js +++ b/packages/cli-snapshot/src/commands/snapshot.js @@ -106,14 +106,13 @@ export class Snapshot extends Command { // Serves a static directory at a base-url and resolves when listening. async serve(staticDir, baseUrl) { - let express = require('express'); - let app = express(); - - app.use(require('cors')()); - app.use(baseUrl, express.static(staticDir)); + let http = require('http'); + let serve = require('serve-handler'); return new Promise(resolve => { - this.server = app.listen(() => { + this.server = http.createServer((req, res) => { + serve(req, res, { public: staticDir }); + }).listen(() => { let { port } = this.server.address(); resolve(`http://localhost:${port}`); }); diff --git a/packages/cli-snapshot/test/snapshot.test.js b/packages/cli-snapshot/test/snapshot.test.js index 8d4f076c5..02c8039af 100644 --- a/packages/cli-snapshot/test/snapshot.test.js +++ b/packages/cli-snapshot/test/snapshot.test.js @@ -159,9 +159,8 @@ describe('percy snapshot', () => { let server; beforeEach(async () => { - server = await createTestServer(); - server.app.get('/', (req, res) => { - res.set('Content-Type', 'text/html').send('
Test
'); + server = await createTestServer({ + default: () => [200, 'text/html', 'Test
'] }); }); diff --git a/packages/core/README.md b/packages/core/README.md index ff30585cc..b28b0b2a9 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -45,8 +45,7 @@ await percy.start() #### API Server Starting a `Percy` instance will start a local API server unless `server` is `false`. The server can -be found at `http://localhost:5338/` or at the provided `port` number. All POST requests accept a -JSON body with the `application/json` content-type. +be found at `http://localhost:5338/` or at the provided `port` number. - GET `/percy/healthcheck` – Responds with information about the running instance - GET `/percy/dom.js` – Responds with the [`@percy/dom`](./packages/dom) library diff --git a/packages/core/package.json b/packages/core/package.json index 6d5280a5c..b6e34f6a2 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -6,7 +6,8 @@ "types": "types/index.d.ts", "files": [ "dist", - "types/index.d.ts" + "types/index.d.ts", + "test/helpers/server.js" ], "scripts": { "build": "babel --root-mode upward src --out-dir dist", @@ -27,9 +28,6 @@ "@percy/client": "^1.0.0-beta.13", "@percy/dom": "^1.0.0-beta.13", "@percy/logger": "^1.0.0-beta.13", - "body-parser": "^1.19.0", - "cors": "^2.8.5", - "express": "^4.17.1", "node-fetch": "^2.6.1", "progress": "^2.0.3", "puppeteer-core": "^5.3.1" diff --git a/packages/core/src/percy.js b/packages/core/src/percy.js index 25d1b6a06..3fe759de4 100644 --- a/packages/core/src/percy.js +++ b/packages/core/src/percy.js @@ -4,7 +4,7 @@ import log from '@percy/logger'; import { schema } from './config'; import Discoverer from './discoverer'; import injectPercyCSS from './percy-css'; -import { createServerApp, startServer } from './server'; +import createPercyServer from './server'; import Queue from './queue'; import assert from './utils/assert'; import { createRootResource, createLogResource } from './utils/resources'; @@ -54,7 +54,7 @@ export default class Percy { if (server) { this.port = port; - this.app = createServerApp(this); + this.server = createPercyServer(this); } this.#snapshots = new Queue(); @@ -90,10 +90,8 @@ export default class Percy { this.client.getToken(); try { - // if there is an exress app, a server should be started - if (this.app) { - this.server = await startServer(this.app, this.port); - } + // if there is a server, start listening + await this.server?.listen(this.port); // launch the discoverer browser and create a percy build await this.discoverer.launch(); diff --git a/packages/core/src/server.js b/packages/core/src/server.js index 7b7d2a4b9..5204b2ddb 100644 --- a/packages/core/src/server.js +++ b/packages/core/src/server.js @@ -1,64 +1,104 @@ -// Handles async routes with a middleware pattern to catch and forward errors -function asyncRoute(handler) { - return (req, res, next) => handler(req, res, next).catch(next); +import http from 'http'; +import fs from 'fs'; + +async function getReply(routes, request) { + let route = routes[request.url] || routes.default; + let reply; + + // cors preflight + if (request.method === 'OPTIONS') { + reply = [204, { 'Access-Control-Allow-Methods': 'GET,POST' }]; + } else { + reply = await Promise.resolve() + .then(() => routes.middleware?.(request)) + .then(() => route?.(request)) + .catch(routes.catch); + } + + // default 404 when reply is not an array + let [status, headers, body] = Array.isArray(reply) ? reply : [404, {}]; + // support content-type header shortcut + if (typeof headers === 'string') headers = { 'Content-Type': headers }; + // auto stringify json + if (headers['Content-Type']?.includes('json')) body = JSON.stringify(body); + // add content length and cors headers + headers['Content-Length'] = body?.length ?? 0; + headers['Access-Control-Allow-Origin'] = '*'; + + return [status, headers, body]; } -// Lazily creates and returns an express app for communicating with the Percy -// instance using a local API -export function createServerApp(percy) { - // lazily required to speed up imports when the server is not needed - let express = require('express'); - let cors = require('cors'); - let bodyParser = require('body-parser'); - - return express() - .use(cors()) - .use(bodyParser.urlencoded({ extended: true })) - .use(bodyParser.json({ limit: '50mb' })) - // healthcheck returns meta info as well - .get('/percy/healthcheck', (_, res) => { - res.json({ - success: true, - config: percy.config, - loglevel: percy.loglevel(), - build: percy.client.build - }); - }) - // responds when idle - .get('/percy/idle', asyncRoute(async (_, res) => { - await percy.idle(); - res.json({ success: true }); - })) - // serves @percy/dom as a convenience - .get('/percy/dom.js', (_, res) => { - res.sendFile(require.resolve('@percy/dom')); - }) - // forward snapshot requests - .post('/percy/snapshot', asyncRoute(async (req, res) => { - await percy.snapshot(req.body); - res.json({ success: true }); - })) - // stops the instance - .post('/percy/stop', asyncRoute(async (_, res) => { - await percy.stop(); - res.json({ success: true }); - })) - // other routes 404 - .use('*', (_, res) => { - res.status(404).json({ success: false, error: 'Not found' }); - }) - // generic error handler - .use(({ message }, req, res, next) => { - res.status(500).json({ success: false, error: message }); +export function createServer(routes) { + let context = { + get listening() { + return context.server.listening; + } + }; + + context.server = http.createServer((request, response) => { + request.on('data', chunk => { + request.body = (request.body || '') + chunk; }); + + request.on('end', async () => { + try { request.body = JSON.parse(request.body); } catch {} + let [status, headers, body] = await getReply(routes, request); + response.writeHead(status, headers).end(body); + }); + }); + + context.close = () => context.server.close(); + context.listen = port => new Promise((resolve, reject) => { + context.server.on('listening', () => resolve(context)); + context.server.on('error', reject); + context.server.listen(port); + }); + + context.reply = (url, handler) => { + routes[url] = handler; + return context; + }; + + return context; } -// Promised based helper for starting an app at the specified port. Resolves -// when the server is listening, rejects if there are any errors when starting. -export function startServer(app, port) { - return new Promise((resolve, reject) => { - let server = app.listen(port); - server.once('listening', () => resolve(server)); - server.once('error', reject); +export default function createPercyServer(percy) { + return createServer({ + // healthcheck returns meta info on success + '/percy/healthcheck': () => [200, 'application/json', { + success: true, + config: percy.config, + loglevel: percy.loglevel(), + build: percy.client.build + }], + + // responds when idle + '/percy/idle': () => percy.idle() + .then(() => [200, 'application/json', { success: true }]), + + // serves @percy/dom as a convenience + '/percy/dom.js': () => fs.promises + .readFile(require.resolve('@percy/dom'), 'utf-8') + .then(content => [200, 'applicaton/javascript', content]), + + // forward snapshot requests + '/percy/snapshot': ({ body }) => percy.snapshot(body) + .then(() => [200, 'application/json', { success: true }]), + + // stops the instance + '/percy/stop': () => percy.stop() + .then(() => [200, 'application/json', { success: true }]), + + // other routes 404 + default: () => [404, 'application/json', { + error: 'Not found', + success: false + }], + + // generic error handler + catch: ({ message }) => [500, 'application/json', { + error: message, + success: false + }] }); } diff --git a/packages/core/test/asset-discovery.test.js b/packages/core/test/asset-discovery.test.js index 744e52549..5f8078bd8 100644 --- a/packages/core/test/asset-discovery.test.js +++ b/packages/core/test/asset-discovery.test.js @@ -41,18 +41,11 @@ describe('Asset Discovery', () => { return [201, { data: { id: '4567' } }]; }); - server = await createTestServer(); - - server.app - .get('/', (req, res) => { - res.set('Content-Type', 'text/html').send(testDOM); - }) - .get('/style.css', (req, res) => { - res.set('Content-Type', 'text/css').send(testCSS); - }) - .get('/img.gif', (req, res) => setTimeout(() => { - res.set('Content-Type', 'image/gif').send(pixel); - }, 10)); + server = await createTestServer({ + '/': () => [200, 'text/html', testDOM], + '/style.css': () => [200, 'text/css', testCSS], + '/img.gif': () => [200, 'image/gif', pixel] + }); percy = await Percy.start({ token: 'PERCY_TOKEN', @@ -75,7 +68,7 @@ describe('Asset Discovery', () => { }); await percy.idle(); - let paths = server.requests.map(r => r.path); + let paths = server.requests.map(r => r[0]); // does not request the root url (serves domSnapshot instead) expect(paths).not.toContain('/'); expect(paths).toContain('/style.css'); @@ -118,7 +111,7 @@ describe('Asset Discovery', () => { }); await percy.idle(); - let paths = server.requests.map(r => r.path); + let paths = server.requests.map(r => r[0]); expect(paths).toContain('/style.css'); expect(captured[0]).toEqual([ @@ -163,9 +156,7 @@ describe('Asset Discovery', () => { }); it('follows redirects', async () => { - server.app.get('/stylesheet.css', (req, res) => { - res.redirect('/style.css'); - }); + server.reply('/stylesheet.css', () => [301, { Location: '/style.css' }]); await percy.snapshot({ name: 'test snapshot', @@ -174,7 +165,7 @@ describe('Asset Discovery', () => { }); await percy.idle(); - let paths = server.requests.map(r => r.path); + let paths = server.requests.map(r => r[0]); expect(paths).toContain('/stylesheet.css'); expect(paths).toContain('/style.css'); @@ -190,9 +181,7 @@ describe('Asset Discovery', () => { }); it('skips capturing large files', async () => { - server.app.get('/large.css', (req, res) => { - res.set('Content-Type', 'text/stylesheet').send('A'.repeat(16000000)); - }); + server.reply('/large.css', () => [200, 'text/css', 'A'.repeat(16_000_000)]); percy.loglevel('debug'); await stdio.capture(() => ( @@ -314,7 +303,7 @@ describe('Asset Discovery', () => { await snapshot(2); // only one request for each resource should be made - let paths = server.requests.map(r => r.path); + let paths = server.requests.map(r => r[0]); expect(paths.sort()).toEqual(['/img.gif', '/style.css']); // both snapshots' captured resources should match @@ -332,7 +321,7 @@ describe('Asset Discovery', () => { await snapshot(2); // two requests for each resource should be made (opposite of prev test) - let paths = server.requests.map(r => r.path); + let paths = server.requests.map(r => r[0]); expect(paths.sort()).toEqual(['/img.gif', '/img.gif', '/style.css', '/style.css']); // bot snapshots' captured resources should match @@ -343,7 +332,6 @@ describe('Asset Discovery', () => { }); }); - // these caches helpers are no longer used describe('with unhandled errors', async () => { it('logs unhandled request errors gracefully', async () => { // sabotage this property to trigger unexpected error handling @@ -397,10 +385,9 @@ describe('Asset Discovery', () => { let server2; beforeEach(async () => { - server2 = await createTestServer(8001); - server2.app.get('/img.gif', (req, res) => { - res.set('Content-Type', 'image/gif').send(pixel); - }); + server2 = await createTestServer({ + '/img.gif': () => [200, 'image/gif', pixel] + }, 8001); }); afterEach(() => { @@ -415,10 +402,10 @@ describe('Asset Discovery', () => { }); await percy.idle(); - let paths = server.requests.map(r => r.path); + let paths = server.requests.map(r => r[0]); expect(paths).toContain('/style.css'); expect(paths).not.toContain('/img.gif'); - let paths2 = server2.requests.map(r => r.path); + let paths2 = server2.requests.map(r => r[0]); expect(paths2).not.toContain('/img.gif'); expect(captured[0]).toEqual([ diff --git a/packages/core/test/helpers/.babelrc b/packages/core/test/helpers/.babelrc new file mode 100644 index 000000000..00c5172d3 --- /dev/null +++ b/packages/core/test/helpers/.babelrc @@ -0,0 +1,10 @@ +{ + "plugins": [ + ["module-resolver", { + "alias": { + // for coverage during tests without needing to compile helper + "@percy/core/dist/server": "./src/server" + } + }] + ] +} diff --git a/packages/core/test/helpers/index.js b/packages/core/test/helpers/index.js index 76c71f729..f2b869877 100644 --- a/packages/core/test/helpers/index.js +++ b/packages/core/test/helpers/index.js @@ -17,5 +17,5 @@ afterEach(() => { export { mockAPI }; export { default as stdio } from '@percy/logger/test/helper'; -export { default as createTestServer } from './test-server'; +export { default as createTestServer } from './server'; export { default as dedent } from './dedent'; diff --git a/packages/core/test/helpers/server.js b/packages/core/test/helpers/server.js new file mode 100644 index 000000000..9cc7399b9 --- /dev/null +++ b/packages/core/test/helpers/server.js @@ -0,0 +1,11 @@ +// aliased to src for coverage during tests without needing to compile this file +const { createServer } = require('@percy/core/dist/server'); + +module.exports = function createTestServer(routes, port = 8000) { + let onError = ({ message }) => [500, 'text/plain', message]; + let middleware = ({ url, body }) => server.requests.push(body ? [url, body] : [url]); + let server = createServer({ ...routes, middleware, catch: onError }); + server.requests = []; + + return server.listen(port); +}; diff --git a/packages/core/test/helpers/test-server.js b/packages/core/test/helpers/test-server.js deleted file mode 100644 index 3e0e42092..000000000 --- a/packages/core/test/helpers/test-server.js +++ /dev/null @@ -1,15 +0,0 @@ -import express from 'express'; -import { startServer } from '../../src/server'; - -export default async function createTestServer(port = 8000) { - let app = express(); - let requests = []; - - app.use('*', (req, res, next) => { - requests.push(req); - next(); - }); - - let server = await startServer(app, port); - return { app, requests, close: () => server.close() }; -} diff --git a/packages/core/test/percy-css.test.js b/packages/core/test/percy-css.test.js index 300ac964f..8aedd57df 100644 --- a/packages/core/test/percy-css.test.js +++ b/packages/core/test/percy-css.test.js @@ -14,10 +14,8 @@ describe('Percy CSS', () => { `; beforeEach(async () => { - server = await createTestServer(); - - server.app.get('/', (req, res) => { - res.set('Content-Type', 'text/html').send(testDOM); + server = await createTestServer({ + default: () => [200, 'text/html', testDOM] }); percy = await Percy.start({ diff --git a/packages/core/test/percy.test.js b/packages/core/test/percy.test.js index ce03f0976..c890c1ec1 100644 --- a/packages/core/test/percy.test.js +++ b/packages/core/test/percy.test.js @@ -234,9 +234,8 @@ describe('Percy', () => { }); it('logs when stopping with pending captures', async () => { - server = await createTestServer(); - server.app.get('/', (req, res) => { - res.set('Content-Type', 'text/html').send('Test
'); + server = await createTestServer({ + default: () => [200, 'text/html', 'Test
'] }); // not awaited on so it becomes pending @@ -273,9 +272,8 @@ describe('Percy', () => { }); it('resolves after captures idle', async () => { - server = await createTestServer(); - server.app.get('/', (req, res) => { - res.set('Content-Type', 'text/html').send('Test
'); + server = await createTestServer({ + default: () => [200, 'text/html', 'Test
'] }); // not awaited on so it becomes pending @@ -322,18 +320,11 @@ describe('Percy', () => { let pixel = Buffer.from('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==', 'base64'); beforeEach(async () => { - server = await createTestServer(); - - server.app - .get('/', (req, res) => { - res.set('Content-Type', 'text/html').send(testDOM); - }) - .get('/style.css', (req, res) => { - res.set('Content-Type', 'text/css').send(testCSS); - }) - .get('/img.gif', (req, res) => { - res.set('Content-Type', 'image/gif').send(pixel); - }); + server = await createTestServer({ + '/': () => [200, 'text/html', testDOM], + '/style.css': () => [200, 'text/css', testCSS], + '/img.gif': () => [200, 'image/gif', pixel] + }); await percy.start(); }); @@ -532,9 +523,9 @@ describe('Percy', () => { beforeEach(async () => { testDOM = 'Test
'; - server = await createTestServer(); - server.app.get('/', (req, res) => { - res.set('Content-Type', 'text/html').send(testDOM); + + server = await createTestServer({ + default: () => [200, 'text/html', testDOM] }); await percy.start(); diff --git a/packages/core/test/server.test.js b/packages/core/test/server.test.js index 450759997..2de9717b8 100644 --- a/packages/core/test/server.test.js +++ b/packages/core/test/server.test.js @@ -49,7 +49,9 @@ describe('Snapshot Server', () => { it('has an /idle endpoint that calls #idle()', async () => { await percy.start(); - percy.idle = () => (percy.idle.calls = percy.idle.calls || []).push(undefined); + percy.idle = async () => ( + percy.idle.calls = percy.idle.calls || [] + ).push(undefined); let response = await fetch('http://localhost:1337/percy/idle'); await expect(response.json()).resolves.toEqual({ success: true }); @@ -57,7 +59,8 @@ describe('Snapshot Server', () => { }); it('serves the @percy/dom bundle', async () => { - let bundle = require('fs').readFileSync(require.resolve('@percy/dom'), { encoding: 'utf-8' }); + let bundle = require('fs') + .readFileSync(require.resolve('@percy/dom'), { encoding: 'utf-8' }); await percy.start(); let response = await fetch('http://localhost:1337/percy/dom.js'); @@ -66,7 +69,9 @@ describe('Snapshot Server', () => { it('has a /stop endpoint that calls #stop()', async () => { await percy.start(); - percy.stop = () => (percy.stop.calls = percy.stop.calls || []).push(undefined); + percy.stop = async () => ( + percy.stop.calls = percy.stop.calls || [] + ).push(undefined); let response = await fetch('http://localhost:1337/percy/stop', { method: 'post' }); await expect(response.json()).resolves.toEqual({ success: true }); @@ -75,11 +80,12 @@ describe('Snapshot Server', () => { it('has a /snapshot endpoint that calls #snapshot()', async () => { await percy.start(); - percy.snapshot = data => (percy.snapshot.calls = percy.snapshot.calls || []).push(data); + percy.snapshot = async data => ( + percy.snapshot.calls = percy.snapshot.calls || [] + ).push(data); let response = await fetch('http://localhost:1337/percy/snapshot', { method: 'post', - headers: { 'Content-Type': 'application/json' }, body: '{ "test": true }' }); @@ -90,11 +96,10 @@ describe('Snapshot Server', () => { it('returns a 500 error when an endpoint throws', async () => { await percy.start(); - percy.snapshot = () => { throw new Error('test error'); }; + percy.snapshot = () => Promise.reject(new Error('test error')); let response = await fetch('http://localhost:1337/percy/snapshot', { method: 'post', - headers: { 'Content-Type': 'application/json' }, body: '{ "test": true }' }); @@ -116,6 +121,22 @@ describe('Snapshot Server', () => { }); }); + it('accepts preflight cors checks', async () => { + let called = false; + + await percy.start(); + percy.snapshot = async () => (called = true); + + let response = await fetch('http://localhost:1337/percy/snapshot', { + method: 'OPTIONS' + }); + + expect(response.status).toBe(204); + expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*'); + expect(response.headers.get('Access-Control-Allow-Methods')).toBe('GET,POST'); + expect(called).toBe(false); + }); + describe('when the server is disabled', () => { beforeEach(async () => { percy = await Percy.start({ diff --git a/scripts/babel-register.js b/scripts/babel-register.js index 70fa93909..3bfd2023e 100644 --- a/scripts/babel-register.js +++ b/scripts/babel-register.js @@ -3,6 +3,7 @@ const path = require('path'); require('@babel/register')({ // allow monorepos to share a single babel config rootMode: 'upward', + babelrcRoots: ['.'], // specified without the cwd so tests can share helpers only: [ diff --git a/yarn.lock b/yarn.lock index 3d918a280..fc5641547 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2229,7 +2229,7 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@~1.3.4, accepts@~1.3.7: +accepts@~1.3.4: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== @@ -2463,11 +2463,6 @@ array-find-index@^1.0.1: resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - array-ify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" @@ -2651,6 +2646,17 @@ babel-plugin-istanbul@^6.0.0: istanbul-lib-instrument "^4.0.0" test-exclude "^6.0.0" +babel-plugin-module-resolver@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-module-resolver/-/babel-plugin-module-resolver-4.0.0.tgz#8f3a3d9d48287dc1d3b0d5595113adabd36a847f" + integrity sha512-3pdEq3PXALilSJ6dnC4wMWr0AZixHRM4utpdpBR9g5QG7B7JwWyukQv7a9hVxkbGFl+nQbrHDqqQOIBtTXTP/Q== + dependencies: + find-babel-config "^1.2.0" + glob "^7.1.6" + pkg-up "^3.1.0" + reselect "^4.0.0" + resolve "^1.13.1" + backo2@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" @@ -2759,7 +2765,7 @@ bn.js@^5.1.1: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== -body-parser@1.19.0, body-parser@^1.19.0: +body-parser@^1.19.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== @@ -2963,6 +2969,11 @@ byte-size@^5.0.1: resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-5.0.1.tgz#4b651039a5ecd96767e71a3d7ed380e48bed4191" integrity sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw== +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + bytes@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" @@ -3538,12 +3549,10 @@ contains-path@^0.1.0: resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= content-type@^1.0.4, content-type@~1.0.4: version "1.0.4" @@ -3640,21 +3649,11 @@ convert-source-map@^1.1.0, convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -3685,14 +3684,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cors@^2.8.5: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - cosmiconfig@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" @@ -4016,11 +4007,6 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" @@ -4711,11 +4697,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - eventemitter3@^3.1.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" @@ -4797,42 +4778,6 @@ expect@^26.4.2: jest-message-util "^26.3.0" jest-regex-util "^26.0.0" -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -4946,6 +4891,13 @@ fast-safe-stringify@^2.0.4: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== +fast-url-parser@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= + dependencies: + punycode "^1.3.2" + fastq@^1.6.0: version "1.8.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" @@ -5006,7 +4958,7 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.1.2, finalhandler@~1.1.2: +finalhandler@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== @@ -5019,6 +4971,14 @@ finalhandler@1.1.2, finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" +find-babel-config@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.2.0.tgz#a9b7b317eb5b9860cda9d54740a8c8337a2283a2" + integrity sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA== + dependencies: + json5 "^0.5.1" + path-exists "^3.0.0" + find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -5151,11 +5111,6 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" @@ -5163,11 +5118,6 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" @@ -5780,17 +5730,6 @@ http-errors@1.7.2: statuses ">= 1.5.0 < 2" toidentifier "1.0.0" -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-proxy-agent@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" @@ -5967,7 +5906,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -6042,11 +5981,6 @@ ip@1.1.5: resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - irregular-plurals@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-3.2.0.tgz#b19c490a0723798db51b235d7e39add44dab0822" @@ -6602,6 +6536,11 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -7195,21 +7134,11 @@ meow@^7.0.0, meow@^7.0.1: type-fest "^0.13.1" yargs-parser "^18.1.3" -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - merge2@^1.2.3, merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -7250,6 +7179,18 @@ mime-db@1.44.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== + +mime-types@2.1.18: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== + dependencies: + mime-db "~1.33.0" + mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" @@ -7257,11 +7198,6 @@ mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: dependencies: mime-db "1.44.0" -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - mime@^2.4.4, mime@^2.4.5: version "2.4.6" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" @@ -7445,11 +7381,6 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@2.1.2, ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -7786,7 +7717,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -8236,6 +8167,11 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-is-inside@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -8251,10 +8187,10 @@ path-parse@^1.0.6: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-to-regexp@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" + integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== path-type@^1.0.0: version "1.1.0" @@ -8365,6 +8301,13 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" + integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== + dependencies: + find-up "^3.0.0" + plur@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/plur/-/plur-4.0.0.tgz#729aedb08f452645fe8c58ef115bf16b0a73ef84" @@ -8472,14 +8415,6 @@ protoduck@^5.0.1: dependencies: genfun "^5.0.0" -proxy-addr@~2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" - integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.1" - proxy-from-env@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -8537,7 +8472,7 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= -punycode@^1.2.4: +punycode@^1.2.4, punycode@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -8652,7 +8587,12 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -range-parser@^1.2.1, range-parser@~1.2.1: +range-parser@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= + +range-parser@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== @@ -9009,6 +8949,11 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= +reselect@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" + integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== + resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -9139,16 +9084,16 @@ rxjs@^6.4.0: dependencies: tslib "^1.9.0" -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, 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== +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -9206,25 +9151,6 @@ semver@^7.2.1, semver@^7.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - serialize-javascript@4.0.0, serialize-javascript@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" @@ -9232,15 +9158,19 @@ serialize-javascript@4.0.0, serialize-javascript@^4.0.0: dependencies: randombytes "^2.1.0" -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== +serve-handler@^6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" + integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" + bytes "3.0.0" + content-disposition "0.5.2" + fast-url-parser "1.1.3" + mime-types "2.1.18" + minimatch "3.0.4" + path-is-inside "1.0.2" + path-to-regexp "2.2.1" + range-parser "1.2.0" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -10212,7 +10142,7 @@ type-fest@^0.8.0, type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -type-is@~1.6.17, type-is@~1.6.18: +type-is@~1.6.17: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== @@ -10461,11 +10391,6 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" -vary@^1, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"