diff --git a/.github/workflows/coder.yaml b/.github/workflows/coder.yaml index 75cc84d59d..d0afed5280 100644 --- a/.github/workflows/coder.yaml +++ b/.github/workflows/coder.yaml @@ -352,6 +352,8 @@ jobs: working-directory: site - run: yarn playwright:test + env: + DEBUG: pw:api working-directory: site - name: Upload DataDog Trace diff --git a/Makefile b/Makefile index c157c2aed2..5f7d5fb9b2 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,6 @@ provisionersdk/proto: provisionersdk/proto/provisioner.proto site/out: ./scripts/yarn_install.sh cd site && yarn build - cd site && yarn export # Restores GITKEEP files! git checkout HEAD site/out .PHONY: site/out diff --git a/coderd/coderd.go b/coderd/coderd.go index 6a21929411..1ce7c0453d 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -168,7 +168,7 @@ func New(options *Options) (http.Handler, func()) { r.Get("/resources", api.workspaceBuildResources) }) }) - r.NotFound(site.Handler(options.Logger).ServeHTTP) + r.NotFound(site.DefaultHandler().ServeHTTP) return r, api.websocketWaitGroup.Wait } diff --git a/site/Main.tsx b/site/Main.tsx new file mode 100644 index 0000000000..157f3c56f7 --- /dev/null +++ b/site/Main.tsx @@ -0,0 +1,14 @@ +import React from "react" +import ReactDOM from "react-dom" + +import { App } from "./app" + +// This is the entry point for the app - where everything start. +// In the future, we'll likely bring in more bootstrapping logic - +// like: https://github.com/coder/m/blob/50898bd4803df7639bd181e484c74ac5d84da474/product/coder/site/pages/_app.tsx#L32 +const main = () => { + const element = document.getElementById("root") + ReactDOM.render(, element) +} + +main() diff --git a/site/_jest/setupTests.ts b/site/_jest/setupTests.ts deleted file mode 100644 index 5f2c86f457..0000000000 --- a/site/_jest/setupTests.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Global setup for our Jest tests - */ - -// Set up 'next-router-mock' to with our front-end tests: -// https://github.com/scottrippey/next-router-mock#quick-start -jest.mock("next/router", () => require("next-router-mock")) - -// Suppress isolated modules warning -export {} diff --git a/site/app.tsx b/site/app.tsx new file mode 100644 index 0000000000..51e0872b09 --- /dev/null +++ b/site/app.tsx @@ -0,0 +1,73 @@ +import React from "react" +import CssBaseline from "@material-ui/core/CssBaseline" +import ThemeProvider from "@material-ui/styles/ThemeProvider" +import { SWRConfig } from "swr" +import { UserProvider } from "./contexts/UserContext" +import { light } from "./theme" +import { BrowserRouter as Router, Route, Routes } from "react-router-dom" + +import { CliAuthenticationPage } from "./pages/cli-auth" +import { NotFoundPage } from "./pages/404" +import { IndexPage } from "./pages/index" +import { SignInPage } from "./pages/login" +import { ProjectsPage } from "./pages/projects" +import { ProjectPage } from "./pages/projects/[organization]/[project]" +import { CreateWorkspacePage } from "./pages/projects/[organization]/[project]/create" +import { WorkspacePage } from "./pages/workspaces/[workspace]" + +export const App: React.FC = () => { + return ( + + { + const res = await fetch(url) + + // By default, `fetch` won't treat 4xx or 5xx response as errors. + // However, we want SWR to treat these as errors - so if `res.ok` is false, + // we want to throw an error to bubble that up to SWR. + if (!res.ok) { + const err = new Error((await res.json()).error?.message || res.statusText) + throw err + } + return res.json() + }, + }} + > + + + + + + + } /> + + } /> + } /> + + + } /> + + } /> + } /> + + + + + } /> + + + {/* Using path="*"" means "match anything", so this route + acts like a catch-all for URLs that we don't have explicit + routes for. */} + } /> + + + + + + + ) +} diff --git a/site/components/Navbar/index.tsx b/site/components/Navbar/index.tsx index 01100e40eb..cc02405a9b 100644 --- a/site/components/Navbar/index.tsx +++ b/site/components/Navbar/index.tsx @@ -1,7 +1,7 @@ import React from "react" import Button from "@material-ui/core/Button" import { makeStyles } from "@material-ui/core/styles" -import Link from "next/link" +import { Link } from "react-router-dom" import { User } from "../../contexts/UserContext" import { Logo } from "../Icons" @@ -17,7 +17,7 @@ export const Navbar: React.FC = ({ user, onSignOut }) => { return (
- + diff --git a/site/components/Redirect.test.tsx b/site/components/Redirect.test.tsx deleted file mode 100644 index 4b53889f39..0000000000 --- a/site/components/Redirect.test.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { render, waitFor } from "@testing-library/react" -import singletonRouter from "next/router" -import mockRouter from "next-router-mock" -import React from "react" -import { Redirect } from "./Redirect" - -describe("Redirect", () => { - // Reset the router to '/' before every test - beforeEach(() => { - mockRouter.setCurrentUrl("/") - }) - - it("performs client-side redirect on render", async () => { - // When - render() - - // Then - await waitFor(() => { - expect(singletonRouter).toMatchObject({ asPath: "/workspaces/v2" }) - }) - }) -}) diff --git a/site/components/Redirect.tsx b/site/components/Redirect.tsx deleted file mode 100644 index 1429421d2a..0000000000 --- a/site/components/Redirect.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React, { useEffect } from "react" -import { useRouter } from "next/router" - -export interface RedirectProps { - /** - * The path to redirect to - * @example '/projects' - */ - to: string -} - -/** - * Helper component to perform a client-side redirect - */ -export const Redirect: React.FC = ({ to }) => { - const { replace } = useRouter() - - useEffect(() => { - void replace(to) - }, [replace, to]) - - return null -} diff --git a/site/components/SignIn/SignInForm.test.tsx b/site/components/SignIn/SignInForm.test.tsx index 1306fd43fa..83694b50fc 100644 --- a/site/components/SignIn/SignInForm.test.tsx +++ b/site/components/SignIn/SignInForm.test.tsx @@ -1,13 +1,12 @@ import React from "react" -import singletonRouter from "next/router" -import mockRouter from "next-router-mock" -import { act, fireEvent, render, screen, waitFor } from "@testing-library/react" +import { act, fireEvent, screen, waitFor } from "@testing-library/react" +import { history, render } from "../../test_helpers" import { SignInForm } from "./SignInForm" describe("SignInForm", () => { beforeEach(() => { - mockRouter.setCurrentUrl("/login") + history.replace("/") }) it("renders content", async () => { @@ -56,14 +55,14 @@ describe("SignInForm", () => { // Then // Should redirect because login was successful - await waitFor(() => expect(singletonRouter).toMatchObject({ asPath: "/" })) + await waitFor(() => expect(history.location.pathname).toEqual("/")) }) it("respects ?redirect query parameter when complete", async () => { // Given const loginHandler = (_email: string, _password: string) => Promise.resolve() // Set a path to redirect to after login is successful - mockRouter.setCurrentUrl("/login?redirect=%2Fsome%2Fother%2Fpath") + history.replace("/login?redirect=%2Fsome%2Fother%2Fpath") // When // Render the component @@ -78,6 +77,6 @@ describe("SignInForm", () => { // Then // Should redirect to /some/other/path because ?redirect was specified and login was successful - await waitFor(() => expect(singletonRouter).toMatchObject({ asPath: "/some/other/path" })) + await waitFor(() => expect(history.location.pathname).toEqual("/some/other/path")) }) }) diff --git a/site/components/SignIn/SignInForm.tsx b/site/components/SignIn/SignInForm.tsx index 3216e53ba4..6f48f61058 100644 --- a/site/components/SignIn/SignInForm.tsx +++ b/site/components/SignIn/SignInForm.tsx @@ -1,6 +1,7 @@ import { makeStyles } from "@material-ui/core/styles" import { FormikContextType, useFormik } from "formik" -import { NextRouter, useRouter } from "next/router" +import { Location } from "history" +import { useNavigate, useLocation } from "react-router-dom" import React from "react" import { useSWRConfig } from "swr" import * as Yup from "yup" @@ -9,7 +10,6 @@ import { Welcome } from "./Welcome" import { FormTextField } from "../Form" import * as API from "./../../api" import { LoadingButton } from "./../Button" -import { firstOrItem } from "../../util/array" /** * BuiltInAuthFormValues describes a form using built-in (email/password) @@ -47,7 +47,8 @@ export interface SignInProps { export const SignInForm: React.FC = ({ loginHandler = (email: string, password: string) => API.login(email, password), }) => { - const router = useRouter() + const navigate = useNavigate() + const location = useLocation() const styles = useStyles() const { mutate } = useSWRConfig() @@ -63,8 +64,8 @@ export const SignInForm: React.FC = ({ // Tell SWR to invalidate the cache for the user endpoint await mutate("/api/v2/users/me") - const redirect = getRedirectFromRouter(router) - await router.push(redirect) + const redirect = getRedirectFromLocation(location) + await navigate(redirect) } catch (err) { helpers.setFieldError("password", "The username or password is incorrect.") } @@ -121,11 +122,10 @@ export const SignInForm: React.FC = ({ ) } -const getRedirectFromRouter = (router: NextRouter) => { +const getRedirectFromLocation = (location: Location) => { const defaultRedirect = "/" - if (router.query.redirect) { - return firstOrItem(router.query.redirect, defaultRedirect) - } else { - return defaultRedirect - } + + const searchParams = new URLSearchParams(location.search) + const redirect = searchParams.get("redirect") + return redirect ? redirect : defaultRedirect } diff --git a/site/components/Workspace/Workspace.test.tsx b/site/components/Workspace/Workspace.test.tsx index d0a2279c58..e085171070 100644 --- a/site/components/Workspace/Workspace.test.tsx +++ b/site/components/Workspace/Workspace.test.tsx @@ -1,7 +1,7 @@ -import { render, screen } from "@testing-library/react" +import { screen } from "@testing-library/react" import React from "react" import { Workspace } from "./Workspace" -import { MockOrganization, MockProject, MockWorkspace } from "../../test_helpers" +import { MockOrganization, MockProject, MockWorkspace, render } from "../../test_helpers" describe("Workspace", () => { it("renders", async () => { diff --git a/site/components/Workspace/Workspace.tsx b/site/components/Workspace/Workspace.tsx index 68c64a467a..8eb1887881 100644 --- a/site/components/Workspace/Workspace.tsx +++ b/site/components/Workspace/Workspace.tsx @@ -3,7 +3,7 @@ import Paper from "@material-ui/core/Paper" import Typography from "@material-ui/core/Typography" import { makeStyles } from "@material-ui/core/styles" import CloudCircleIcon from "@material-ui/icons/CloudCircle" -import Link from "next/link" +import { Link } from "react-router-dom" import React from "react" import * as Constants from "./constants" import * as API from "../../api" @@ -68,7 +68,7 @@ export const WorkspaceHeader: React.FC = ({ organization, projec
{workspace.name} - {project.name} + {project.name}
diff --git a/site/components/index.tsx b/site/components/index.tsx index ebb1a90188..5fd2a75122 100644 --- a/site/components/index.tsx +++ b/site/components/index.tsx @@ -1,4 +1,3 @@ export * from "./Button" export * from "./EmptyState" export * from "./Page" -export * from "./Redirect" diff --git a/site/contexts/UserContext.test.tsx b/site/contexts/UserContext.test.tsx index 22685b6399..58af022aa0 100644 --- a/site/contexts/UserContext.test.tsx +++ b/site/contexts/UserContext.test.tsx @@ -1,11 +1,8 @@ -import singletonRouter from "next/router" -import mockRouter from "next-router-mock" import React from "react" import { SWRConfig } from "swr" -import { render, screen, waitFor } from "@testing-library/react" - +import { screen, waitFor } from "@testing-library/react" import { User, UserProvider, useUser } from "./UserContext" -import { MockUser } from "../test_helpers" +import { history, MockUser, render } from "../test_helpers" namespace Helpers { // Helper component that renders out the state of the `useUser` hook. @@ -54,7 +51,7 @@ describe("UserContext", () => { // Reset the router to '/' before every test beforeEach(() => { - mockRouter.setCurrentUrl("/") + history.replace("/") }) it("shouldn't redirect if user fails to load and redirectOnFailure is false", async () => { @@ -67,7 +64,8 @@ describe("UserContext", () => { expect(screen.queryByText("Error:", { exact: false })).toBeDefined() }) // ...and the route should be unchanged - expect(singletonRouter).toMatchObject({ asPath: "/" }) + expect(history.location.pathname).toEqual("/") + expect(history.location.search).toEqual("") }) it("should redirect if user fails to load and redirectOnFailure is true", async () => { @@ -76,7 +74,8 @@ describe("UserContext", () => { // Then // Verify we route to the login page - await waitFor(() => expect(singletonRouter).toMatchObject({ asPath: "/login?redirect=%2F" })) + await waitFor(() => expect(history.location.pathname).toEqual("/login")) + await waitFor(() => expect(history.location.search).toEqual("?redirect=%2F")) }) it("should not redirect if user loads and redirectOnFailure is true", async () => { @@ -89,6 +88,7 @@ describe("UserContext", () => { expect(screen.queryByText("Me:", { exact: false })).toBeDefined() }) // ...and the route should be unchanged - expect(singletonRouter).toMatchObject({ asPath: "/" }) + expect(history.location.pathname).toEqual("/") + expect(history.location.search).toEqual("") }) }) diff --git a/site/contexts/UserContext.tsx b/site/contexts/UserContext.tsx index 7db4169140..459af26595 100644 --- a/site/contexts/UserContext.tsx +++ b/site/contexts/UserContext.tsx @@ -1,4 +1,4 @@ -import { useRouter } from "next/router" +import { useLocation, useNavigate } from "react-router-dom" import React, { useContext, useEffect } from "react" import useSWR from "swr" @@ -25,18 +25,15 @@ const UserContext = React.createContext({ export const useUser = (redirectOnError = false): UserContext => { const ctx = useContext(UserContext) - const { push, asPath } = useRouter() + const navigate = useNavigate() + const { pathname } = useLocation() const requestError = ctx.error useEffect(() => { if (redirectOnError && requestError) { - // 'void' means we are ignoring handling the promise returned - // from router.push (and lets the linter know we're OK with that!) - void push({ + navigate({ pathname: "/login", - query: { - redirect: asPath, - }, + search: "?redirect=" + encodeURIComponent(pathname), }) } // Disabling exhaustive deps here because it can cause an @@ -48,18 +45,17 @@ export const useUser = (redirectOnError = false): UserContext => { } export const UserProvider: React.FC = (props) => { - const router = useRouter() + const navigate = useNavigate() + const location = useLocation() const { data, error, mutate } = useSWR("/api/v2/users/me") const signOut = async () => { await API.logout() // Tell SWR to invalidate the cache for the user endpoint await mutate("/api/v2/users/me") - await router.push({ + navigate({ pathname: "/login", - query: { - redirect: router.asPath, - }, + search: "?redirect=" + encodeURIComponent(location.pathname), }) } diff --git a/site/dev.ts b/site/dev.ts deleted file mode 100644 index 19a39f58d5..0000000000 --- a/site/dev.ts +++ /dev/null @@ -1,42 +0,0 @@ -import express from "express" -import { createProxyMiddleware } from "http-proxy-middleware" -import next from "next" - -const port = process.env.PORT || 8080 -const dev = process.env.NODE_ENV !== "production" - -let coderV2Host = "http://127.0.0.1:3000" - -if (process.env.CODERV2_HOST) { - if (!/^http(s)?:\/\//.test(process.env.CODERV2_HOST)) { - throw new Error("CODERV2_HOST must be http(s)") - } else { - coderV2Host = process.env.CODERV2_HOST - } -} - -console.log(`Using CODERV2_HOST: ${coderV2Host}`) - -const app = next({ dev, dir: "." }) -const handle = app.getRequestHandler() - -app - .prepare() - .then(() => { - const server = express() - server.use( - "/api", - createProxyMiddleware("/api", { - target: coderV2Host, - ws: true, - secure: false, - changeOrigin: true, - }), - ) - server.all("*", (req, res) => handle(req, res)) - server.listen(port) - }) - .catch((err) => { - console.error(err) - process.exit(1) - }) diff --git a/site/e2e/tests/login.spec.ts b/site/e2e/tests/login.spec.ts index 02a51cd699..b751aecd9d 100644 --- a/site/e2e/tests/login.spec.ts +++ b/site/e2e/tests/login.spec.ts @@ -1,6 +1,7 @@ import { test } from "@playwright/test" import { ProjectsPage, SignInPage } from "../pom" import { email, password } from "../constants" +import { waitForClientSideNavigation } from "./../util" test("Login takes user to /projects", async ({ baseURL, page }) => { await page.goto(baseURL + "/", { waitUntil: "networkidle" }) @@ -10,7 +11,7 @@ test("Login takes user to /projects", async ({ baseURL, page }) => { await signInPage.submitBuiltInAuthentication(email, password) const projectsPage = new ProjectsPage(baseURL, page) - await page.waitForNavigation({ url: projectsPage.url, waitUntil: "networkidle" }) + await waitForClientSideNavigation(page, { to: projectsPage.url }) await page.waitForSelector("text=Projects") }) diff --git a/site/e2e/util.ts b/site/e2e/util.ts new file mode 100644 index 0000000000..c51455db84 --- /dev/null +++ b/site/e2e/util.ts @@ -0,0 +1,82 @@ +import { Page } from "@playwright/test" + +/** + * `timeout(x)` is a helper function to create a promise that resolves after `x` milliseconds. + * + * @param timeoutInMilliseconds Time to wait for promise to resolve + * @returns `Promise` + */ +export const timeout = (timeoutInMilliseconds: number): Promise => { + return new Promise((resolve) => { + setTimeout(resolve, timeoutInMilliseconds) + }) +} + +/** + * `waitFor(f, timeout?)` waits for a predicate to return `true`, running it periodically until it returns `true`. + * + * If `f` never returns `true`, the function will simply return. In other words, the burden is on the consumer + * to check that the predicate is passing (`waitFor` does no validation). + * + * @param f A predicate that returns a `Promise` + * @param timeToWaitInMilliseconds The total time to wait for the condition to be `true`. + * @returns + */ +export const waitFor = async (f: () => Promise, timeToWaitInMilliseconds = 30000): Promise => { + let elapsedTime = 0 + const timeToWaitPerIteration = 1000 + + while (elapsedTime < timeToWaitInMilliseconds) { + const condition = await f() + + if (condition) { + return + } + + await timeout(timeToWaitPerIteration) + elapsedTime += timeToWaitPerIteration + } +} + +interface WaitForClientSideNavigationOpts { + /** + * from is the page before navigation (the 'current' page) + */ + from?: string + /** + * to is the page after navigation (the 'next' page) + */ + to?: string +} + +/** + * waitForClientSideNavigation waits for the url to change from opts.from to + * opts.to (if specified), as well as a network idle load state. This enhances + * a native playwright check for navigation or loadstate. + * + * @remark This is necessary in a client-side SPA world since playwright + * waitForNavigation waits for load events on the DOM (ex: after a page load + * from the server). + * + * @todo Better logging for this. + */ +export const waitForClientSideNavigation = async (page: Page, opts: WaitForClientSideNavigationOpts): Promise => { + await Promise.all([ + waitFor(() => { + const conditions: boolean[] = [] + + if (opts.from) { + conditions.push(page.url() !== opts.from) + } + + if (opts.to) { + conditions.push(page.url() === opts.to) + } + + const unmetConditions = conditions.filter((condition) => !condition) + + return Promise.resolve(unmetConditions.length === 0) + }), + page.waitForLoadState("networkidle"), + ]) +} diff --git a/site/embed.go b/site/embed.go index 6d750b8855..98982234b3 100644 --- a/site/embed.go +++ b/site/embed.go @@ -4,57 +4,89 @@ package site import ( + "bytes" "embed" "fmt" + "io" "io/fs" "net/http" + "path" + "path/filepath" "strings" + "text/template" // html/template escapes some nonces + "time" "github.com/justinas/nosurf" "github.com/unrolled/secure" - - "cdr.dev/slog" - - "github.com/coder/coder/site/nextrouter" + "golang.org/x/xerrors" ) // The `embed` package ignores recursively including directories // that prefix with `_`. Wildcarding nested is janky, but seems to // work quite well for edge-cases. -//go:embed out/_next/*/*/*/* -//go:embed out/_next/*/*/* -//go:embed out/bin/* //go:embed out +//go:embed out/bin/* var site embed.FS -// Handler returns an HTTP handler for serving the static site. -func Handler(logger slog.Logger) http.Handler { - filesystem, err := fs.Sub(site, "out") +func DefaultHandler() http.Handler { + // the out directory is where webpack builds are created. It is in the same + // directory as this file (package site). + siteFS, err := fs.Sub(site, "out") + if err != nil { // This can't happen... Go would throw a compilation error. panic(err) } - // Render CSP and CSRF in the served pages - templateFunc := func(r *http.Request) interface{} { - return htmlState{ - // Nonce is the CSP nonce for the given request (if there is one present) - CSP: cspState{Nonce: secure.CSPNonce(r.Context())}, - // Token is the CSRF token for the given request - CSRF: csrfState{Token: nosurf.Token(r)}, - } + return Handler(siteFS) +} + +// Handler returns an HTTP handler for serving the static site. +func Handler(fileSystem fs.FS) http.Handler { + // html files are handled by a text/template. Non-html files + // are served by the default file server. + // + // REMARK: text/template is needed to inject values on each request like + // CSRF. + files, err := htmlFiles(fileSystem) + + if err != nil { + panic(xerrors.Errorf("Failed to return handler for static files. Html files failed to load: %w", err)) } - nextRouterHandler, err := nextrouter.Handler(filesystem, &nextrouter.Options{ - Logger: logger, - TemplateDataFunc: templateFunc, + return secureHeaders(&handler{ + fs: fileSystem, + htmlFiles: files, + h: http.FileServer(http.FS(fileSystem)), // All other non-html static files }) - if err != nil { - // There was an error setting up our file system handler. - // This likely means a problem with our embedded file system. - panic(err) +} + +type handler struct { + fs fs.FS + // htmlFiles is the text/template for all *.html files. + // This is needed to support Content Security Policy headers. + // Due to material UI, we are forced to use a nonce to allow inline + // scripts, and that nonce is passed through a template. + // We only do this for html files to reduce the amount of in memory caching + // of duplicate files as `fs`. + htmlFiles *htmlTemplates + h http.Handler +} + +// filePath returns the filepath of the requested file. +func filePath(p string) string { + if !strings.HasPrefix(p, "/") { + p = "/" + p } - return secureHeaders(nextRouterHandler) + return strings.TrimPrefix(path.Clean(p), "/") +} + +func (h *handler) exists(filePath string) bool { + f, err := h.fs.Open(filePath) + if err == nil { + _ = f.Close() + } + return err == nil } type htmlState struct { @@ -70,30 +102,141 @@ type csrfState struct { Token string } -// cspDirectives is a map of all csp fetch directives to their values. +func ShouldCacheFile(reqFile string) bool { + // Images, favicons and uniquely content hashed bundle assets should be + // cached. By default, we cache everything in the site/out directory except + // for deny-listed items enumerated here. The reason for this approach is + // that cache invalidation techniques should be used by default for all + // webpack-processed assets. The scenarios where we don't use cache + // invalidation techniques are one-offs or things that should have + // invalidation in the future. + denyListedSuffixes := []string{ + // ALL *.html files + ".html", + + // ALL *worker.js files (including service-worker.js) + // + // REMARK(Grey): I'm unsure if there's a desired setting in Workbox for + // content hashing these, or if doing so is a risk for + // users that have a PWA installed. + "worker.js", + } + + for _, suffix := range denyListedSuffixes { + if strings.HasSuffix(reqFile, suffix) { + return false + } + } + + return true +} + +func (h *handler) ServeHTTP(resp http.ResponseWriter, req *http.Request) { + // reqFile is the static file requested + reqFile := filePath(req.URL.Path) + state := htmlState{ + // Token is the CSRF token for the given request + CSRF: csrfState{Token: nosurf.Token(req)}, + } + + // First check if it's a file we have in our templates + if h.serveHTML(resp, req, reqFile, state) { + return + } + + // If the original file path exists we serve it. + if h.exists(reqFile) { + if ShouldCacheFile(reqFile) { + resp.Header().Add("Cache-Control", "public, max-age=31536000, immutable") + } + h.h.ServeHTTP(resp, req) + return + } + + // Serve the file assuming it's an html file + // This matches paths like `/app/terminal.html` + req.URL.Path = strings.TrimSuffix(req.URL.Path, "/") + req.URL.Path += ".html" + + reqFile = filePath(req.URL.Path) + // All html files should be served by the htmlFile templates + if h.serveHTML(resp, req, reqFile, state) { + return + } + + // If we don't have the file... we should redirect to `/` + // for our single-page-app. + req.URL.Path = "/" + if h.serveHTML(resp, req, "", state) { + return + } + + // This will send a correct 404 + h.h.ServeHTTP(resp, req) +} + +func (h *handler) serveHTML(resp http.ResponseWriter, request *http.Request, reqPath string, state htmlState) bool { + if data, err := h.htmlFiles.renderWithState(reqPath, state); err == nil { + if reqPath == "" { + // Pass "index.html" to the ServeContent so the ServeContent sets the right content headers. + reqPath = "index.html" + } + http.ServeContent(resp, request, reqPath, time.Time{}, bytes.NewReader(data)) + return true + } + return false +} + +type htmlTemplates struct { + tpls *template.Template +} + +// renderWithState will render the file using the given nonce if the file exists +// as a template. If it does not, it will return an error. +func (t *htmlTemplates) renderWithState(filePath string, state htmlState) ([]byte, error) { + var buf bytes.Buffer + if filePath == "" { + filePath = "index.html" + } + err := t.tpls.ExecuteTemplate(&buf, filePath, state) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +// CSPDirectives is a map of all csp fetch directives to their values. // Each directive is a set of values that is joined by a space (' '). // All directives are semi-colon separated as a single string for the csp header. -type cspDirectives map[cspFetchDirective][]string +type CSPDirectives map[CSPFetchDirective][]string -// cspFetchDirective is the list of all constant fetch directives that +func (s CSPDirectives) Append(d CSPFetchDirective, values ...string) { + if _, ok := s[d]; !ok { + s[d] = make([]string, 0) + } + s[d] = append(s[d], values...) +} + +// CSPFetchDirective is the list of all constant fetch directives that // can be used/appended to. -type cspFetchDirective string +type CSPFetchDirective string const ( - cspDirectiveDefaultSrc = "default-src" - cspDirectiveConnectSrc = "connect-src" - cspDirectiveChildSrc = "child-src" - cspDirectiveScriptSrc = "script-src" - cspDirectiveFontSrc = "font-src" - cspDirectiveStyleSrc = "style-src" - cspDirectiveObjectSrc = "object-src" - cspDirectiveManifestSrc = "manifest-src" - cspDirectiveFrameSrc = "frame-src" - cspDirectiveImgSrc = "img-src" - cspDirectiveReportURI = "report-uri" - cspDirectiveFormAction = "form-action" - cspDirectiveMediaSrc = "media-src" - cspFrameAncestors = "frame-ancestors" + CSPDirectiveDefaultSrc = "default-src" + CSPDirectiveConnectSrc = "connect-src" + CSPDirectiveChildSrc = "child-src" + CSPDirectiveScriptSrc = "script-src" + CSPDirectiveFontSrc = "font-src" + CSPDirectiveStyleSrc = "style-src" + CSPDirectiveObjectSrc = "object-src" + CSPDirectiveManifestSrc = "manifest-src" + CSPDirectiveFrameSrc = "frame-src" + CSPDirectiveImgSrc = "img-src" + CSPDirectiveReportURI = "report-uri" + CSPDirectiveFormAction = "form-action" + CSPDirectiveMediaSrc = "media-src" + CSPFrameAncestors = "frame-ancestors" ) // secureHeaders is only needed for statically served files. We do not need this for api endpoints. @@ -104,26 +247,26 @@ func secureHeaders(next http.Handler) http.Handler { // If we ever want to render something like a PDF, we need to adjust "object-src" // // The list of CSP options: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/default-src - cspSrcs := cspDirectives{ + cspSrcs := CSPDirectives{ // All omitted fetch csp srcs default to this. - cspDirectiveDefaultSrc: {"'self'"}, - cspDirectiveConnectSrc: {"'self' ws: wss:"}, - cspDirectiveChildSrc: {"'self'"}, - cspDirectiveScriptSrc: {"'self'"}, - cspDirectiveFontSrc: {"'self'"}, - cspDirectiveStyleSrc: {"'self' 'unsafe-inline'"}, + CSPDirectiveDefaultSrc: {"'self'"}, + CSPDirectiveConnectSrc: {"'self' ws: wss:"}, + CSPDirectiveChildSrc: {"'self'"}, + CSPDirectiveScriptSrc: {"'self'"}, + CSPDirectiveFontSrc: {"'self'"}, + CSPDirectiveStyleSrc: {"'self' 'unsafe-inline'"}, // object-src is needed to support code-server - cspDirectiveObjectSrc: {"'self'"}, + CSPDirectiveObjectSrc: {"'self'"}, // blob: for loading the pwa manifest for code-server - cspDirectiveManifestSrc: {"'self' blob:"}, - cspDirectiveFrameSrc: {"'self'"}, + CSPDirectiveManifestSrc: {"'self' blob:"}, + CSPDirectiveFrameSrc: {"'self'"}, // data: for loading base64 encoded icons for generic applications. - cspDirectiveImgSrc: {"'self' https://cdn.coder.com data:"}, - cspDirectiveFormAction: {"'self'"}, - cspDirectiveMediaSrc: {"'self'"}, + CSPDirectiveImgSrc: {"'self' https://cdn.coder.com data:"}, + CSPDirectiveFormAction: {"'self'"}, + CSPDirectiveMediaSrc: {"'self'"}, // Report all violations back to the server to log - cspDirectiveReportURI: {"/api/private/csp/reports"}, - cspFrameAncestors: {"'none'"}, + CSPDirectiveReportURI: {"/api/private/csp/reports"}, + CSPFrameAncestors: {"'none'"}, // Only scripts can manipulate the dom. This prevents someone from // naming themselves something like ''. @@ -171,3 +314,52 @@ func secureHeaders(next http.Handler) http.Handler { ReferrerPolicy: "no-referrer", }).Handler(next) } + +// htmlFiles recursively walks the file system passed finding all *.html files. +// The template returned has all html files parsed. +func htmlFiles(files fs.FS) (*htmlTemplates, error) { + // root is the collection of html templates. All templates are named by their pathing. + // So './404.html' is named '404.html'. './subdir/index.html' is 'subdir/index.html' + root := template.New("") + + rootPath := "." + err := fs.WalkDir(files, rootPath, func(filePath string, directory fs.DirEntry, err error) error { + if err != nil { + return err + } + + if directory.IsDir() { + return nil + } + + if filepath.Ext(directory.Name()) != ".html" { + return nil + } + + file, err := files.Open(filePath) + if err != nil { + return err + } + + data, err := io.ReadAll(file) + if err != nil { + return err + } + + tPath := strings.TrimPrefix(filePath, rootPath+string(filepath.Separator)) + _, err = root.New(tPath).Parse(string(data)) + if err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &htmlTemplates{ + tpls: root, + }, nil +} diff --git a/site/embed_slim.go b/site/embed_slim.go index 7a91f163c2..7960769e94 100644 --- a/site/embed_slim.go +++ b/site/embed_slim.go @@ -5,10 +5,8 @@ package site import ( "net/http" - - "cdr.dev/slog" ) -func Handler(logger slog.Logger) http.Handler { +func DefaultHandler() http.Handler { return http.NotFoundHandler() } diff --git a/site/embed_test.go b/site/embed_test.go index 8dee1ca925..2907da01e9 100644 --- a/site/embed_test.go +++ b/site/embed_test.go @@ -5,28 +5,170 @@ package site_test import ( "context" + "fmt" "io" "net/http" "net/http/httptest" "testing" + "testing/fstest" + "time" "github.com/stretchr/testify/require" - "cdr.dev/slog" - "github.com/coder/coder/site" ) -func TestIndexPageRenders(t *testing.T) { +func TestCaching(t *testing.T) { t.Parallel() - srv := httptest.NewServer(site.Handler(slog.Logger{})) + // Create a test server + rootFS := fstest.MapFS{ + "bundle.js": &fstest.MapFile{}, + "image.png": &fstest.MapFile{}, + "static/image.png": &fstest.MapFile{}, + "favicon.ico": &fstest.MapFile{ + Data: []byte("folderFile"), + }, - req, err := http.NewRequestWithContext(context.Background(), "GET", srv.URL, nil) - require.NoError(t, err) - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err, "get index") - defer resp.Body.Close() - data, _ := io.ReadAll(resp.Body) - require.NotEmpty(t, data, "index should have contents") + "service-worker.js": &fstest.MapFile{}, + "index.html": &fstest.MapFile{ + Data: []byte("folderFile"), + }, + "terminal.html": &fstest.MapFile{ + Data: []byte("folderFile"), + }, + } + + srv := httptest.NewServer(site.Handler(rootFS)) + defer srv.Close() + + // Create a context + ctx, cancelFunc := context.WithTimeout(context.Background(), 1*time.Second) + defer cancelFunc() + + testCases := []struct { + path string + isExpectingCache bool + }{ + {"/bundle.js", true}, + {"/image.png", true}, + {"/static/image.png", true}, + {"/favicon.ico", true}, + + {"/", false}, + {"/service-worker.js", false}, + {"/index.html", false}, + {"/double/nested/terminal.html", false}, + } + + for _, testCase := range testCases { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, srv.URL+testCase.path, nil) + require.NoError(t, err, "create request") + + res, err := srv.Client().Do(req) + require.NoError(t, err, "get index") + + cache := res.Header.Get("Cache-Control") + if testCase.isExpectingCache { + require.Equalf(t, "public, max-age=31536000, immutable", cache, "expected %w file to have immutable cache", testCase.path) + } else { + require.Equalf(t, "", cache, "expected %w file to not have immutable cache header", testCase.path) + } + + require.NoError(t, res.Body.Close(), "closing response") + } +} + +func TestServingFiles(t *testing.T) { + t.Parallel() + + // Create a test server + rootFS := fstest.MapFS{ + "index.html": &fstest.MapFile{ + Data: []byte("index-bytes"), + }, + "favicon.ico": &fstest.MapFile{ + Data: []byte("favicon-bytes"), + }, + "dashboard.js": &fstest.MapFile{ + Data: []byte("dashboard-js-bytes"), + }, + "dashboard.css": &fstest.MapFile{ + Data: []byte("dashboard-css-bytes"), + }, + } + + srv := httptest.NewServer(site.Handler(rootFS)) + defer srv.Close() + + // Create a context + ctx, cancelFunc := context.WithTimeout(context.Background(), 1*time.Second) + defer cancelFunc() + + var testCases = []struct { + path string + expected string + }{ + // Index cases + {"/", "index-bytes"}, + {"/index.html", "index-bytes"}, + {"/nested", "index-bytes"}, + {"/nested/", "index-bytes"}, + {"/nested/index.html", "index-bytes"}, + + // These are nested paths that should lead back to index. We don't + // allow nested JS or CSS files. + {"/double/nested", "index-bytes"}, + {"/double/nested/", "index-bytes"}, + {"/double/nested/index.html", "index-bytes"}, + {"/nested/dashboard.js", "index-bytes"}, + {"/nested/dashboard.css", "index-bytes"}, + {"/double/nested/dashboard.js", "index-bytes"}, + {"/double/nested/dashboard.css", "index-bytes"}, + + // Favicon cases + // The favicon is always root-referenced in index.html: + {"/favicon.ico", "favicon-bytes"}, + + // JS, CSS cases + {"/dashboard.js", "dashboard-js-bytes"}, + {"/dashboard.css", "dashboard-css-bytes"}, + } + + for _, testCase := range testCases { + path := srv.URL + testCase.path + + req, err := http.NewRequestWithContext(ctx, "GET", path, nil) + require.NoError(t, err) + resp, err := http.DefaultClient.Do(req) + require.NoError(t, err, "get file") + data, _ := io.ReadAll(resp.Body) + require.Equal(t, string(data), testCase.expected, "Verify file: "+testCase.path) + err = resp.Body.Close() + require.NoError(t, err) + } +} + +func TestShouldCacheFile(t *testing.T) { + t.Parallel() + + var testCases = []struct { + reqFile string + expected bool + }{ + {"123456789.js", true}, + {"apps/app/code/terminal.css", true}, + {"image.png", true}, + {"static/image.png", true}, + {"static/images/section-a/image.jpeg", true}, + + {"service-worker.js", false}, + {"dashboard.html", false}, + {"apps/app/code/terminal.html", false}, + } + + for _, testCase := range testCases { + got := site.ShouldCacheFile(testCase.reqFile) + require.Equal(t, testCase.expected, got, fmt.Sprintf("Expected ShouldCacheFile(%s) to be %t", testCase.reqFile, testCase.expected)) + } } diff --git a/site/html_templates/index.html b/site/html_templates/index.html new file mode 100644 index 0000000000..ad38a815c0 --- /dev/null +++ b/site/html_templates/index.html @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + Coder + + + +
+ +
+ diff --git a/site/jest.config.js b/site/jest.config.js index f22ea399ee..17e6e73fd1 100644 --- a/site/jest.config.js +++ b/site/jest.config.js @@ -11,7 +11,6 @@ module.exports = { preset: "ts-jest", roots: [""], - setupFilesAfterEnv: ["/_jest/setupTests.ts"], transform: { "^.+\\.tsx?$": "ts-jest", }, @@ -24,15 +23,7 @@ module.exports = { displayName: "lint", runner: "jest-runner-eslint", testMatch: ["/**/*.js", "/**/*.ts", "/**/*.tsx"], - testPathIgnorePatterns: [ - "/.next/", - "/out/", - "/_jest/", - "dev.ts", - "jest.config.js", - "jest-runner.*.js", - "next.config.js", - ], + testPathIgnorePatterns: ["/out/", "/_jest/", "jest.config.js", "jest-runner.*.js"], }, ], collectCoverageFrom: [ @@ -41,15 +32,12 @@ module.exports = { "/**/*.tsx", "!/**/*.stories.tsx", "!/_jest/**/*.*", - "!/.next/**/*.*", "!/api.ts", "!/coverage/**/*.*", - "!/dev.ts", "!/e2e/**/*.*", "!/jest-runner.eslint.config.js", "!/jest.config.js", - "!/next-env.d.ts", - "!/next.config.js", + "!/webpack.*.ts", "!/out/**/*.*", "!/storybook-static/**/*.*", ], diff --git a/site/next-env.d.ts b/site/next-env.d.ts deleted file mode 100644 index 4f11a03dc6..0000000000 --- a/site/next-env.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/// -/// - -// NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/site/next.config.js b/site/next.config.js deleted file mode 100644 index 4c9546001c..0000000000 --- a/site/next.config.js +++ /dev/null @@ -1,25 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -/* eslint-disable @typescript-eslint/no-unsafe-return */ -/* eslint-disable @typescript-eslint/no-unsafe-call */ -/* eslint-disable @typescript-eslint/no-unsafe-member-access */ -/* eslint-disable @typescript-eslint/no-var-requires */ - -module.exports = { - env: {}, - experimental: { - // Allows us to import TS files from outside product/coder/site. - externalDir: true, - }, - webpack: (config, { isServer, webpack }) => { - // Inject CODERD_HOST environment variable for clients - if (!isServer) { - config.plugins.push( - new webpack.DefinePlugin({ - "process.env.CODERD_HOST": JSON.stringify(process.env.CODERD_HOST), - }), - ) - } - - return config - }, -} diff --git a/site/nextrouter/nextrouter.go b/site/nextrouter/nextrouter.go deleted file mode 100644 index caa84c4065..0000000000 --- a/site/nextrouter/nextrouter.go +++ /dev/null @@ -1,260 +0,0 @@ -package nextrouter - -import ( - "bytes" - "context" - "html/template" - "io/fs" - "net/http" - "path/filepath" - "strings" - "time" - - "github.com/go-chi/chi/v5" - - "cdr.dev/slog" -) - -// Options for configuring a nextrouter -type Options struct { - Logger slog.Logger - TemplateDataFunc HTMLTemplateHandler -} - -// HTMLTemplateHandler is a function that lets the consumer of `nextrouter` -// inject arbitrary template parameters, based on the request. This is useful -// if the Request object is carrying CSRF tokens, session tokens, etc - -// they can be emitted in the page. -type HTMLTemplateHandler func(*http.Request) interface{} - -// Handler returns an HTTP handler for serving a next-based static site -// This handler respects NextJS-based routing rules: -// https://nextjs.org/docs/routing/dynamic-routes -// -// 1) If a file is of the form `[org]`, it's a dynamic route for a single-parameter -// 2) If a file is of the form `[[...any]]`, it's a dynamic route for any parameters -func Handler(fileSystem fs.FS, options *Options) (http.Handler, error) { - if options == nil { - options = &Options{ - Logger: slog.Logger{}, - TemplateDataFunc: nil, - } - } - router := chi.NewRouter() - - // Build up a router that matches NextJS routing rules, for HTML files - err := registerRoutes(router, fileSystem, *options) - if err != nil { - return nil, err - } - - // Fallback to static file server for non-HTML files - router.NotFound(FileHandler(fileSystem)) - - // Finally, if there is a 404.html available, serve that - err = register404(fileSystem, router, *options) - if err != nil { - // An error may be expected if a 404.html is not present - options.Logger.Warn(context.Background(), "Unable to find 404.html", slog.Error(err)) - } - - return router, nil -} - -// FileHandler serves static content, additionally adding immutable -// cache-control headers for Next.js content -func FileHandler(fileSystem fs.FS) func(writer http.ResponseWriter, request *http.Request) { - // Non-HTML files don't have special routing rules, so we can just leverage - // the built-in http.FileServer for it. - fileHandler := http.FileServer(http.FS(fileSystem)) - - return func(writer http.ResponseWriter, request *http.Request) { - // From the Next.js documentation: - // - // "Caching improves response times and reduces the number - // of requests to external services. Next.js automatically - // adds caching headers to immutable assets served from - // /_next/static including JavaScript, CSS, static images, - // and other media." - // - // See: https://nextjs.org/docs/going-to-production - if strings.HasPrefix(request.URL.Path, "/_next/static/") { - writer.Header().Add("Cache-Control", "public, max-age=31536000, immutable") - } - - fileHandler.ServeHTTP(writer, request) - } -} - -// registerRoutes recursively traverses the file-system, building routes -// as appropriate for respecting NextJS dynamic rules. -func registerRoutes(rtr chi.Router, fileSystem fs.FS, options Options) error { - files, err := fs.ReadDir(fileSystem, ".") - if err != nil { - return err - } - - // Loop through everything in the current directory... - for _, file := range files { - name := file.Name() - - // If we're working with a file - just serve it up - if !file.IsDir() { - serveFile(rtr, fileSystem, name, options) - continue - } - - // ...otherwise, if it's a directory, create a sub-route by - // recursively calling `buildRouter` - sub, err := fs.Sub(fileSystem, name) - if err != nil { - return err - } - - // In the special case where the folder is dynamic, - // like `[org]`, we can convert to a chi-style dynamic route - // (which uses `{` instead of `[`) - routeName := name - if isDynamicRoute(name) { - routeName = "{dynamic}" - } - - options.Logger.Debug(context.Background(), "Registering route", slog.F("name", name), slog.F("routeName", routeName)) - rtr.Route("/"+routeName, func(r chi.Router) { - err := registerRoutes(r, sub, options) - if err != nil { - options.Logger.Error(context.Background(), "Error registering route", slog.F("name", routeName), slog.Error(err)) - } - }) - } - - return nil -} - -// serveFile is responsible for serving up HTML files in our next router -// It handles various special cases, like trailing-slashes or handling routes w/o the .html suffix. -func serveFile(router chi.Router, fileSystem fs.FS, fileName string, options Options) { - // We only handle .html files for now - ext := filepath.Ext(fileName) - if ext != ".html" { - return - } - - options.Logger.Debug(context.Background(), "Reading file", slog.F("fileName", fileName)) - - data, err := fs.ReadFile(fileSystem, fileName) - if err != nil { - options.Logger.Error(context.Background(), "Unable to read file", slog.F("fileName", fileName)) - return - } - - // Create a template from the data - we can inject custom parameters like CSRF here - tpls, err := template.New(fileName).Parse(string(data)) - if err != nil { - options.Logger.Error(context.Background(), "Unable to create template for file", slog.F("fileName", fileName)) - return - } - - handler := func(writer http.ResponseWriter, request *http.Request) { - var buf bytes.Buffer - - // See if there are any template parameters we need to inject! - // Things like CSRF tokens, etc... - //templateData := struct{}{} - var templateData interface{} - templateData = nil - if options.TemplateDataFunc != nil { - templateData = options.TemplateDataFunc(request) - } - - options.Logger.Debug(context.Background(), "Applying template parameters", slog.F("fileName", fileName), slog.F("templateData", templateData)) - err := tpls.ExecuteTemplate(&buf, fileName, templateData) - - if err != nil { - options.Logger.Error(request.Context(), "Error executing template", slog.F("template_parameters", templateData)) - http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) - return - } - - http.ServeContent(writer, request, fileName, time.Time{}, bytes.NewReader(buf.Bytes())) - } - - fileNameWithoutExtension := removeFileExtension(fileName) - - // Handle the `[[...any]]` catch-all case - if isCatchAllRoute(fileNameWithoutExtension) { - options.Logger.Info(context.Background(), "Registering catch-all route", slog.F("fileName", fileName)) - router.NotFound(handler) - return - } - - // Handle the `[org]` dynamic route case - if isDynamicRoute(fileNameWithoutExtension) { - options.Logger.Debug(context.Background(), "Registering dynamic route", slog.F("fileName", fileName)) - router.Get("/{dynamic}", handler) - return - } - - // Handle the basic file cases - // Directly accessing a file, ie `/providers.html` - router.Get("/"+fileName, handler) - // Accessing a file without an extension, ie `/providers` - router.Get("/"+fileNameWithoutExtension, handler) - - // Special case: '/' should serve index.html - if fileName == "index.html" { - router.Get("/", handler) - return - } - - // Otherwise, handling the trailing slash case - - // for examples, `providers.html` should serve `/providers/` - router.Get("/"+fileNameWithoutExtension+"/", handler) -} - -func register404(fileSystem fs.FS, router chi.Router, options Options) error { - // Get the file contents - fileBytes, err := fs.ReadFile(fileSystem, "404.html") - if err != nil { - // An error is expected if the file doesn't exist - return err - } - - router.NotFound(func(writer http.ResponseWriter, request *http.Request) { - writer.WriteHeader(http.StatusNotFound) - _, err = writer.Write(fileBytes) - if err != nil { - options.Logger.Error(request.Context(), "Unable to write bytes for 404") - return - } - }) - - return nil -} - -// isDynamicRoute returns true if the file is a NextJS dynamic route, like `[orgs]` -// Returns false if the file is not a dynamic route, or if it is a catch-all route (`[[...any]]`) -// NOTE: The extension should be removed from the file name -func isDynamicRoute(fileWithoutExtension string) bool { - // Assuming ASCII encoding - `len` in go works on bytes - byteLen := len(fileWithoutExtension) - if byteLen < 2 { - return false - } - - return fileWithoutExtension[0] == '[' && fileWithoutExtension[1] != '[' && fileWithoutExtension[byteLen-1] == ']' -} - -// isCatchAllRoute returns true if the file is a catch-all route, like `[[...any]]` -// Return false otherwise -// NOTE: The extension should be removed from the file name -func isCatchAllRoute(fileWithoutExtension string) bool { - ret := strings.HasPrefix(fileWithoutExtension, "[[.") - return ret -} - -// removeFileExtension removes the extension from a file -// For example, removeFileExtension("index.html") would return "index" -func removeFileExtension(fileName string) string { - return strings.TrimSuffix(fileName, filepath.Ext(fileName)) -} diff --git a/site/nextrouter/nextrouter_test.go b/site/nextrouter/nextrouter_test.go deleted file mode 100644 index 2f7c9c14d9..0000000000 --- a/site/nextrouter/nextrouter_test.go +++ /dev/null @@ -1,476 +0,0 @@ -package nextrouter_test - -import ( - "context" - "io" - "net/http" - "net/http/httptest" - "testing" - "testing/fstest" - "time" - - "github.com/stretchr/testify/require" - - "cdr.dev/slog" - - "github.com/coder/coder/site/nextrouter" -) - -func TestNextRouter(t *testing.T) { - t.Parallel() - - t.Run("Serves file at root", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "test.html": &fstest.MapFile{ - Data: []byte("test123"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/test.html") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - require.EqualValues(t, "test123", body) - require.Equal(t, http.StatusOK, res.StatusCode) - }) - - // This is a test case for the issue we hit in V1 w/ NextJS migration - t.Run("Prefer file over folder w/ trailing slash", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "folder/test.html": &fstest.MapFile{}, - "folder.html": &fstest.MapFile{ - Data: []byte("folderFile"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/folder/") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - require.EqualValues(t, "folderFile", body) - require.Equal(t, http.StatusOK, res.StatusCode) - }) - - t.Run("Serves non-html files at root", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "test.png": &fstest.MapFile{ - Data: []byte("png-bytes"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/test.png") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - require.Equal(t, "image/png", res.Header.Get("Content-Type")) - require.EqualValues(t, "png-bytes", body) - require.Equal(t, http.StatusOK, res.StatusCode) - }) - - t.Run("Serves html file without extension", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "test.html": &fstest.MapFile{ - Data: []byte("test-no-extension"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/test") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - require.EqualValues(t, "test-no-extension", body) - require.Equal(t, http.StatusOK, res.StatusCode) - }) - - t.Run("Defaults to index.html at root", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "index.html": &fstest.MapFile{ - Data: []byte("test-root-index"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - require.Equal(t, "text/html; charset=utf-8", res.Header.Get("Content-Type")) - require.EqualValues(t, "test-root-index", body) - require.Equal(t, http.StatusOK, res.StatusCode) - }) - - t.Run("Serves nested file", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "test/a/b/c.html": &fstest.MapFile{ - Data: []byte("test123"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/test/a/b/c.html") - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - - res, err = request(server, "/test/a/b/c.html") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - require.EqualValues(t, "test123", body) - require.Equal(t, http.StatusOK, res.StatusCode) - }) - - t.Run("Uses index.html in nested path", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "test/a/b/c/index.html": &fstest.MapFile{ - Data: []byte("test-abc-index"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/test/a/b/c") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - require.EqualValues(t, "test-abc-index", body) - require.Equal(t, http.StatusOK, res.StatusCode) - }) - - t.Run("404 if file at root is not found", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "test.html": &fstest.MapFile{ - Data: []byte("test123"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/test-non-existent.html") - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - require.Equal(t, http.StatusNotFound, res.StatusCode) - }) - - t.Run("404 if file at root is not found", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "test.html": &fstest.MapFile{ - Data: []byte("test123"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/test-non-existent.html") - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - require.Equal(t, http.StatusNotFound, res.StatusCode) - }) - - t.Run("Serve custom 404.html if available", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "404.html": &fstest.MapFile{ - Data: []byte("404 custom content"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/test-non-existent.html") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - - require.Equal(t, http.StatusNotFound, res.StatusCode) - require.EqualValues(t, "404 custom content", body) - }) - - t.Run("Serves dynamic-routed file", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "folder/[orgs].html": &fstest.MapFile{ - Data: []byte("test-dynamic-path"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/folder/org-1") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - - require.Equal(t, http.StatusOK, res.StatusCode) - require.EqualValues(t, "test-dynamic-path", body) - }) - - t.Run("Handles dynamic-routed folders", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "folder/[org]/[project]/create.html": &fstest.MapFile{ - Data: []byte("test-create"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/folder/org-1/project-1/create") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - - require.Equal(t, http.StatusOK, res.StatusCode) - require.EqualValues(t, "test-create", body) - }) - - t.Run("Handles catch-all routes", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "folder/[[...any]].html": &fstest.MapFile{ - Data: []byte("test-catch-all"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/folder/org-1/project-1/random") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - - require.Equal(t, http.StatusOK, res.StatusCode) - require.EqualValues(t, "test-catch-all", body) - }) - - t.Run("Static routes should be preferred to dynamic routes", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "folder/[orgs].html": &fstest.MapFile{ - Data: []byte("test-dynamic-path"), - }, - "folder/create.html": &fstest.MapFile{ - Data: []byte("test-create"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/folder/create") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - - require.Equal(t, http.StatusOK, res.StatusCode) - require.EqualValues(t, "test-create", body) - }) - - t.Run("Caching headers for _next resources", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "index.html": &fstest.MapFile{ - Data: []byte("test-root"), - }, - "_next/static/test.js": &fstest.MapFile{ - Data: []byte("test.js cached forever"), - }, - "_next/static/chunks/app/test.css": &fstest.MapFile{ - Data: []byte("test.css cached forever"), - }, - } - - router, err := nextrouter.Handler(rootFS, nil) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/index.html") - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - - require.Equal(t, http.StatusOK, res.StatusCode) - require.Empty(t, res.Header.Get("Cache-Control")) - - res, err = request(server, "/_next/static/test.js") - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - - require.Equal(t, http.StatusOK, res.StatusCode) - require.Equal(t, "public, max-age=31536000, immutable", res.Header.Get("Cache-Control")) - }) - - t.Run("Injects template parameters", func(t *testing.T) { - t.Parallel() - - rootFS := fstest.MapFS{ - "test.html": &fstest.MapFile{ - Data: []byte("{{ .CSRF.Token }}"), - }, - } - - type csrfState struct { - Token string - } - - type template struct { - CSRF csrfState - } - - // Add custom template function - templateFunc := func(request *http.Request) interface{} { - return template{ - CSRF: csrfState{ - Token: "hello-csrf", - }, - } - } - - router, err := nextrouter.Handler(rootFS, &nextrouter.Options{ - Logger: slog.Logger{}, - TemplateDataFunc: templateFunc, - }) - require.NoError(t, err) - - server := httptest.NewServer(router) - t.Cleanup(server.Close) - - res, err := request(server, "/test.html") - require.NoError(t, err) - - body, err := io.ReadAll(res.Body) - require.NoError(t, err) - require.NoError(t, res.Body.Close()) - - require.Equal(t, http.StatusOK, res.StatusCode) - require.EqualValues(t, "hello-csrf", body) - }) -} - -func request(server *httptest.Server, path string) (*http.Response, error) { - ctx, cancelFunc := context.WithTimeout(context.Background(), 1*time.Second) - defer cancelFunc() - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, server.URL+path, nil) - if err != nil { - return nil, err - } - - res, err := server.Client().Do(req) - if err != nil { - return nil, err - } - return res, err -} diff --git a/site/out/_next/chunks/pages/app/GITKEEP b/site/out/_next/chunks/pages/app/GITKEEP deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/site/package.json b/site/package.json index a9fb9e1899..22492fb50e 100644 --- a/site/package.json +++ b/site/package.json @@ -4,10 +4,9 @@ "repository": "https://github.com/coder/coder", "private": true, "scripts": { - "build": "NODE_ENV=production next build", - "build:dev": "next build", - "dev": "ts-node dev.ts", - "export": "next export", + "build": "NODE_ENV=production webpack build --config=webpack.prod.ts", + "build:analyze": "NODE_ENV=production webpack --profile --progress --json --config=webpack.prod.ts > out/stats.json && webpack-bundle-analyzer out/stats.json out", + "dev": "webpack-dev-server --config=webpack.dev.ts", "format:check": "prettier --check '**/*.{css,html,js,json,jsx,md,ts,tsx,yaml,yml}'", "format:write": "prettier --write '**/*.{css,html,js,json,jsx,md,ts,tsx,yaml,yml}' && sql-formatter -l postgresql ./database/query.sql -o ./database/query.sql", "lint": "jest --selectProjects lint", @@ -25,6 +24,7 @@ "@material-ui/icons": "4.5.1", "@material-ui/lab": "4.0.0-alpha.42", "@playwright/test": "1.19.2", + "@pmmmwh/react-refresh-webpack-plugin": "0.5.4", "@react-theming/storybook-addon": "1.1.5", "@storybook/addon-actions": "6.4.19", "@storybook/addon-essentials": "6.4.19", @@ -39,6 +39,7 @@ "@types/superagent": "4.1.15", "@typescript-eslint/eslint-plugin": "4.33.0", "@typescript-eslint/parser": "4.33.0", + "copy-webpack-plugin": "10.2.4", "eslint": "7.32.0", "eslint-config-prettier": "8.5.0", "eslint-import-resolver-alias": "1.1.2", @@ -52,24 +53,29 @@ "eslint-plugin-react-hooks": "4.3.0", "express": "4.17.3", "formik": "2.2.9", + "history": "5.3.0", + "html-webpack-plugin": "5.5.0", "http-proxy-middleware": "2.0.3", "jest": "27.5.1", "jest-junit": "13.0.0", "jest-runner-eslint": "1.0.0", - "next": "12.1.0", - "next-router-mock": "^0.6.5", "prettier": "2.5.1", "react": "17.0.2", "react-dom": "17.0.2", - "sql-formatter": "^4.0.2", + "react-hot-loader": "4.13.0", + "react-router-dom": "6.2.1", + "sql-formatter": "4.0.2", "swr": "1.2.2", "ts-jest": "27.1.3", "ts-loader": "9.2.8", "ts-node": "10.7.0", "typescript": "4.6.2", + "webpack": "5.65.0", + "webpack-bundle-analyzer": "4.5.0", + "webpack-cli": "4.9.1", + "webpack-dev-server": "4.7.4", "yup": "0.32.11" }, - "dependencies": {}, "browserslist": [ "chrome 66", "firefox 63", diff --git a/site/pages/404.tsx b/site/pages/404.tsx new file mode 100644 index 0000000000..facd13c1b2 --- /dev/null +++ b/site/pages/404.tsx @@ -0,0 +1,33 @@ +import { makeStyles } from "@material-ui/core/styles" +import React from "react" + +import Typography from "@material-ui/core/Typography" + +export const NotFoundPage: React.FC = () => { + const styles = useStyles() + + return ( +
+
+ 404 +
+ This page could not be found. +
+ ) +} + +const useStyles = makeStyles((theme) => ({ + root: { + width: "100vw", + height: "100vh", + display: "flex", + flexDirection: "row", + justifyContent: "center", + alignItems: "center", + }, + headingContainer: { + margin: theme.spacing(1), + padding: theme.spacing(1), + borderRight: theme.palette.divider, + }, +})) diff --git a/site/pages/_app.tsx b/site/pages/_app.tsx deleted file mode 100644 index 6c69513919..0000000000 --- a/site/pages/_app.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from "react" -import CssBaseline from "@material-ui/core/CssBaseline" -import ThemeProvider from "@material-ui/styles/ThemeProvider" -import { SWRConfig } from "swr" -import { AppProps } from "next/app" -import { UserProvider } from "../contexts/UserContext" -import { light } from "../theme" - -/** - * ClientRender is a component that only allows its children to be rendered - * client-side. This check is performed by querying the existence of the window - * global. - */ -const ClientRender: React.FC = ({ children }) => ( -
{typeof window === "undefined" ? null : children}
-) - -/** - * is the root rendering logic of the application - setting up our router - * and any contexts / global state management. - */ -const MyApp: React.FC = ({ Component, pageProps }) => { - return ( - - { - const res = await fetch(url) - if (!res.ok) { - const err = new Error((await res.json()).error?.message || res.statusText) - throw err - } - return res.json() - }, - }} - > - - - - - - - - - ) -} - -export default MyApp diff --git a/site/pages/_document.tsx b/site/pages/_document.tsx deleted file mode 100644 index 12a08ff3f8..0000000000 --- a/site/pages/_document.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import Document, { DocumentContext, Head, Html, Main, NextScript } from "next/document" -import React from "react" - -class MyDocument extends Document { - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - static async getInitialProps(ctx: DocumentContext) { - const initialProps = await Document.getInitialProps(ctx) - return { ...initialProps } - } - - render(): JSX.Element { - return ( - - - - - - - - - - - - -
- - - - ) - } -} - -export default MyDocument diff --git a/site/pages/cli-auth.tsx b/site/pages/cli-auth.tsx index a31c682d93..d4a080affd 100644 --- a/site/pages/cli-auth.tsx +++ b/site/pages/cli-auth.tsx @@ -6,7 +6,7 @@ import { CliAuthToken } from "../components/SignIn" import { FullScreenLoader } from "../components/Loader/FullScreenLoader" import { useUser } from "../contexts/UserContext" -const CliAuthenticationPage: React.FC = () => { +export const CliAuthenticationPage: React.FC = () => { const { me } = useUser(true) const styles = useStyles() @@ -40,5 +40,3 @@ const useStyles = makeStyles(() => ({ alignItems: "center", }, })) - -export default CliAuthenticationPage diff --git a/site/pages/index.tsx b/site/pages/index.tsx index 905fef83e8..e6ae6e51ff 100644 --- a/site/pages/index.tsx +++ b/site/pages/index.tsx @@ -1,18 +1,16 @@ import React from "react" -import { Redirect } from "../components" +import { Navigate } from "react-router-dom" import { FullScreenLoader } from "../components/Loader/FullScreenLoader" import { useUser } from "../contexts/UserContext" -const IndexPage: React.FC = () => { +export const IndexPage: React.FC = () => { const { me } = useUser(/* redirectOnError */ true) if (me) { // Once the user is logged in, just redirect them to /projects as the landing page - return + return } return } - -export default IndexPage diff --git a/site/pages/login.tsx b/site/pages/login.tsx index c8103fe811..eb404f04f5 100644 --- a/site/pages/login.tsx +++ b/site/pages/login.tsx @@ -26,5 +26,3 @@ export const SignInPage: React.FC = () => {
) } - -export default SignInPage diff --git a/site/pages/projects/[organization]/[project]/create.tsx b/site/pages/projects/[organization]/[project]/create.tsx index 8baa5b0c29..545c9913c6 100644 --- a/site/pages/projects/[organization]/[project]/create.tsx +++ b/site/pages/projects/[organization]/[project]/create.tsx @@ -1,6 +1,6 @@ import React, { useCallback } from "react" import { makeStyles } from "@material-ui/core/styles" -import { useRouter } from "next/router" +import { useNavigate, useParams } from "react-router-dom" import useSWR from "swr" import * as API from "../../../../api" @@ -10,11 +10,11 @@ import { FullScreenLoader } from "../../../../components/Loader/FullScreenLoader import { CreateWorkspaceForm } from "../../../../forms/CreateWorkspaceForm" import { unsafeSWRArgument } from "../../../../util" -const CreateWorkspacePage: React.FC = () => { - const { push, query } = useRouter() +export const CreateWorkspacePage: React.FC = () => { + const { organization: organizationName, project: projectName } = useParams() + const navigate = useNavigate() const styles = useStyles() const { me } = useUser(/* redirectOnError */ true) - const { organization: organizationName, project: projectName } = query const { data: organizationInfo, error: organizationError } = useSWR( () => `/api/v2/users/me/organizations/${organizationName}`, @@ -25,12 +25,12 @@ const CreateWorkspacePage: React.FC = () => { }) const onCancel = useCallback(async () => { - await push(`/projects/${organizationName}/${projectName}`) - }, [push, organizationName, projectName]) + navigate(`/projects/${organizationName}/${projectName}`) + }, [navigate, organizationName, projectName]) const onSubmit = async (req: API.CreateWorkspaceRequest) => { const workspace = await API.Workspace.create(req) - await push(`/workspaces/${workspace.id}`) + navigate(`/workspaces/${workspace.id}`) return workspace } @@ -62,5 +62,3 @@ const useStyles = makeStyles((theme) => ({ backgroundColor: theme.palette.background.paper, }, })) - -export default CreateWorkspacePage diff --git a/site/pages/projects/[organization]/[project]/index.tsx b/site/pages/projects/[organization]/[project]/index.tsx index 23c36dedf3..858a6bb87a 100644 --- a/site/pages/projects/[organization]/[project]/index.tsx +++ b/site/pages/projects/[organization]/[project]/index.tsx @@ -1,8 +1,7 @@ import React from "react" import { makeStyles } from "@material-ui/core/styles" import Paper from "@material-ui/core/Paper" -import Link from "next/link" -import { useRouter } from "next/router" +import { Link, useNavigate, useParams } from "react-router-dom" import useSWR from "swr" import { Organization, Project, Workspace } from "../../../../api" @@ -17,12 +16,11 @@ import { firstOrItem } from "../../../../util/array" import { EmptyState } from "../../../../components/EmptyState" import { unsafeSWRArgument } from "../../../../util" -const ProjectPage: React.FC = () => { +export const ProjectPage: React.FC = () => { const styles = useStyles() const { me, signOut } = useUser(true) - - const router = useRouter() - const { project: projectName, organization: organizationName } = router.query + const navigate = useNavigate() + const { project: projectName, organization: organizationName } = useParams() const { data: organizationInfo, error: organizationError } = useSWR( () => `/api/v2/users/me/organizations/${organizationName}`, @@ -54,7 +52,7 @@ const ProjectPage: React.FC = () => { } const createWorkspace = () => { - void router.push(`/projects/${organizationName}/${projectName}/create`) + navigate(`/projects/${organizationName}/${projectName}/create`) } const emptyState = ( @@ -73,7 +71,7 @@ const ProjectPage: React.FC = () => { key: "name", name: "Name", renderer: (nameField: string, workspace: Workspace) => { - return {nameField} + return {nameField} }, }, ] @@ -125,5 +123,3 @@ const useStyles = makeStyles((theme) => ({ width: "100%", }, })) - -export default ProjectPage diff --git a/site/pages/projects/index.tsx b/site/pages/projects/index.tsx index a5a69af37d..7c5aa8d957 100644 --- a/site/pages/projects/index.tsx +++ b/site/pages/projects/index.tsx @@ -1,7 +1,7 @@ import React from "react" import { makeStyles } from "@material-ui/core/styles" import Paper from "@material-ui/core/Paper" -import Link from "next/link" +import { Link } from "react-router-dom" import { EmptyState } from "../../components" import { ErrorSummary } from "../../components/ErrorSummary" import { Navbar } from "../../components/Navbar" @@ -15,7 +15,7 @@ import { Organization, Project } from "./../../api" import useSWR from "swr" import { CodeExample } from "../../components/CodeExample/CodeExample" -const ProjectsPage: React.FC = () => { +export const ProjectsPage: React.FC = () => { const styles = useStyles() const { me, signOut } = useUser(true) const { data: orgs, error: orgsError } = useSWR("/api/v2/users/me/organizations") @@ -49,7 +49,7 @@ const ProjectsPage: React.FC = () => { key: "name", name: "Name", renderer: (nameField: string, data: Project) => { - return {nameField} + return {nameField} }, }, ] @@ -93,5 +93,3 @@ const useStyles = makeStyles((theme) => ({ marginBottom: theme.spacing(1), }, })) - -export default ProjectsPage diff --git a/site/pages/workspaces/[workspace].tsx b/site/pages/workspaces/[workspace].tsx index a4c6f48197..86e3e0ba4c 100644 --- a/site/pages/workspaces/[workspace].tsx +++ b/site/pages/workspaces/[workspace].tsx @@ -1,7 +1,7 @@ import React from "react" import useSWR from "swr" import { makeStyles } from "@material-ui/core/styles" -import { useRouter } from "next/router" +import { useParams } from "react-router-dom" import { Navbar } from "../../components/Navbar" import { Footer } from "../../components/Page" import { useUser } from "../../contexts/UserContext" @@ -12,13 +12,11 @@ import { Workspace } from "../../components/Workspace" import { unsafeSWRArgument } from "../../util" import * as API from "../../api" -const WorkspacesPage: React.FC = () => { +export const WorkspacePage: React.FC = () => { const styles = useStyles() - const router = useRouter() + const { workspace: workspaceQueryParam } = useParams() const { me, signOut } = useUser(true) - const { workspace: workspaceQueryParam } = router.query - const { data: workspace, error: workspaceError } = useSWR(() => { const workspaceParam = firstOrItem(workspaceQueryParam, null) @@ -74,5 +72,3 @@ const useStyles = makeStyles(() => ({ width: "100%", }, })) - -export default WorkspacesPage diff --git a/site/test_helpers/index.tsx b/site/test_helpers/index.tsx index 6cd4183fb1..08626d442a 100644 --- a/site/test_helpers/index.tsx +++ b/site/test_helpers/index.tsx @@ -3,9 +3,17 @@ import React from "react" import ThemeProvider from "@material-ui/styles/ThemeProvider" import { dark } from "../theme" +import { createMemoryHistory } from "history" +import { unstable_HistoryRouter as HistoryRouter } from "react-router-dom" + +export const history = createMemoryHistory() export const WrapperComponent: React.FC = ({ children }) => { - return {children} + return ( + + {children} + + ) } export const render = (component: React.ReactElement): RenderResult => { diff --git a/site/tsconfig.json b/site/tsconfig.json index 765efd1652..16d7c93221 100644 --- a/site/tsconfig.json +++ b/site/tsconfig.json @@ -4,7 +4,7 @@ "noImplicitAny": true, "module": "commonjs", "target": "es5", - "jsx": "preserve", + "jsx": "react", "allowJs": true, "downlevelIteration": true, "esModuleInterop": true, @@ -15,10 +15,9 @@ "strict": true, "strictNullChecks": true, "forceConsistentCasingInFileNames": true, - "noEmit": true, "incremental": true, "moduleResolution": "node" }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], - "exclude": ["node_modules", "_jest"] + "exclude": ["node_modules", "_jest", "**/*.test.tsx"] } diff --git a/site/tsconfig.test.json b/site/tsconfig.test.json index f2966ec4f5..c205a8c2d8 100644 --- a/site/tsconfig.test.json +++ b/site/tsconfig.test.json @@ -8,5 +8,6 @@ "strict": true, "strictNullChecks": true, "esModuleInterop": true - } + }, + "exclude": ["node_modules", "_jest"] } diff --git a/site/webpack.common.ts b/site/webpack.common.ts new file mode 100644 index 0000000000..b341ece840 --- /dev/null +++ b/site/webpack.common.ts @@ -0,0 +1,58 @@ +/** + * @fileoverview This file contains a set of webpack configurations that should + * be shared between development and production. + */ + +import * as path from "path" +import { Configuration } from "webpack" +import HtmlWebpackPlugin from "html-webpack-plugin" + +const templatePath = path.join(__dirname, "html_templates") + +const plugins = [ + // The HTML webpack plugin tells webpack to use our `index.html` and inject + // the bundle script, which might have special naming. + new HtmlWebpackPlugin({ + template: path.join(templatePath, "index.html"), + publicPath: "/", + }), +] + +export const commonWebpackConfig: Configuration = { + // entry defines each "page" or "chunk". Currently, for v2, we only have one bundle - + // a bundle that is shared across all of the UI. However, we may need to eventually split + // like in v1, where there is a separate entry piont for dashboard & terminal. + entry: path.join(__dirname, "Main.tsx"), + + // modules specify how different modules are loaded + // See: https://webpack.js.org/concepts/modules/ + module: { + rules: [ + { + test: /\.tsx?$/, + use: ["ts-loader"], + exclude: [/node_modules/], + }, + ], + }, + + resolve: { + // Let webpack know to consider ts/tsx files for bundling + // See: https://webpack.js.org/guides/typescript/ + extensions: [".tsx", ".ts", ".js"], + }, + + // output defines the name and location of the final bundle + output: { + // The chunk name along with a hash of its content will be used for the + // generated bundle name. + // + // REMARK: It's important to use [contenthash] here to invalidate caches. + filename: "bundle.[contenthash].js", + path: path.resolve(__dirname, "out"), + }, + + plugins: plugins, + + target: "web", +} diff --git a/site/webpack.dev.ts b/site/webpack.dev.ts new file mode 100644 index 0000000000..ffa2f46f8f --- /dev/null +++ b/site/webpack.dev.ts @@ -0,0 +1,91 @@ +/** + * @fileoverview This file contains a development configuration for webpack + * meant for webpack-dev-server. + */ +import ReactRefreshWebpackPlugin from "@pmmmwh/react-refresh-webpack-plugin" +import { Configuration } from "webpack" +import "webpack-dev-server" + +import { commonWebpackConfig } from "./webpack.common" + +const commonPlugins = commonWebpackConfig.plugins || [] + +const config: Configuration = { + ...commonWebpackConfig, + + // devtool controls how source maps are generated. In development, we want + // more details (less optimized) for more readability and an easier time + // debugging + devtool: "eval-source-map", + + // devServer is the configuration for webpack-dev-server. + // + // REMARK: needs webpack-dev-server import at top of file for typings + devServer: { + // allowedHosts are services that can access the running server. + // Setting allowedHosts sets up the development server to spend specific headers to allow cross-origin requests. + // In v1, we use CODERD_HOST for the allowed host and origin in order to mitigate security risks. + // We don't have an equivalent in v2 - but we can allow localhost and cdr.dev, + // so that the site is accessible through dev urls. + // We don't want to use 'all' or '*' and risk a security hole in our dev environments. + allowedHosts: ["localhost", ".cdr.dev"], + + // client configures options that are observed in the browser/web-client. + client: { + // automatically sets the browser console to verbose when using HMR + logging: "verbose", + + // errors will display as a full-screen overlay + overlay: true, + + // build % progress will display in the browser + progress: true, + + // webpack-dev-server uses a webSocket to communicate with the browser + // for HMR. By setting this to auto://0.0.0.0/ws, we allow the browser + // to set the protocal, hostname and port automatically for us. + webSocketURL: "auto://0.0.0.0:0/ws", + }, + devMiddleware: { + publicPath: "/", + }, + headers: { + "Access-Control-Allow-Origin": "*", + }, + + // historyApiFallback is required when using history (react-router) for + // properly serving index.html on 404s. + historyApiFallback: true, + hot: true, + port: 8080, + proxy: { + "/api": "http://localhost:3000", + }, + static: ["./static"], + }, + + // Development mode - see: + // https://webpack.js.org/configuration/mode/#mode-development + mode: "development", + + output: { + ...commonWebpackConfig.output, + + // The chunk name will be used as-is for the bundle output + // This is simpler than production, to improve performance + // (no need to calculate hashes in development) + filename: "[name].js", + }, + + plugins: [ + ...commonPlugins, + + // The ReactRefreshWebpackPlugin enables hot-module reloading: + // https://github.com/pmmmwh/react-refresh-webpack-plugin + new ReactRefreshWebpackPlugin({ + overlay: true, + }), + ], +} + +export default config diff --git a/site/webpack.prod.ts b/site/webpack.prod.ts new file mode 100644 index 0000000000..21ce3363e2 --- /dev/null +++ b/site/webpack.prod.ts @@ -0,0 +1,36 @@ +/** + * @fileoverview This file contains a production configuration for webpack + * meant for producing optimized builds. + */ + +import CopyWebpackPlugin from "copy-webpack-plugin" +import { Configuration } from "webpack" +import { commonWebpackConfig } from "./webpack.common" + +const commonPlugins = commonWebpackConfig.plugins || [] + +export const config: Configuration = { + ...commonWebpackConfig, + mode: "production", + + // Don't produce sourcemaps in production, to minmize bundle size + devtool: false, + + output: { + ...commonWebpackConfig.output, + + // regenerate the entire out/ directory when producing production builds + clean: true, + }, + + plugins: [ + ...commonPlugins, + // For production builds, we also need to copy all the static + // files to the 'out' folder. + new CopyWebpackPlugin({ + patterns: [{ from: "static", to: "." }], + }), + ], +} + +export default config diff --git a/site/yarn.lock b/site/yarn.lock index 3b26353367..79fe6a3adc 100644 --- a/site/yarn.lock +++ b/site/yarn.lock @@ -1147,7 +1147,7 @@ dependencies: "@cspotcode/source-map-consumer" "0.8.0" -"@discoveryjs/json-ext@^0.5.3": +"@discoveryjs/json-ext@^0.5.0", "@discoveryjs/json-ext@^0.5.3": version "0.5.6" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f" integrity sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA== @@ -1665,66 +1665,6 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@next/env@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.0.tgz#73713399399b34aa5a01771fb73272b55b22c314" - integrity sha512-nrIgY6t17FQ9xxwH3jj0a6EOiQ/WDHUos35Hghtr+SWN/ntHIQ7UpuvSi0vaLzZVHQWaDupKI+liO5vANcDeTQ== - -"@next/swc-android-arm64@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.0.tgz#865ba3a9afc204ff2bdeea49dd64d58705007a39" - integrity sha512-/280MLdZe0W03stA69iL+v6I+J1ascrQ6FrXBlXGCsGzrfMaGr7fskMa0T5AhQIVQD4nA/46QQWxG//DYuFBcA== - -"@next/swc-darwin-arm64@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.0.tgz#08e8b411b8accd095009ed12efbc2f1d4d547135" - integrity sha512-R8vcXE2/iONJ1Unf5Ptqjk6LRW3bggH+8drNkkzH4FLEQkHtELhvcmJwkXcuipyQCsIakldAXhRbZmm3YN1vXg== - -"@next/swc-darwin-x64@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.0.tgz#fcd684497a76e8feaca88db3c394480ff0b007cd" - integrity sha512-ieAz0/J0PhmbZBB8+EA/JGdhRHBogF8BWaeqR7hwveb6SYEIJaDNQy0I+ZN8gF8hLj63bEDxJAs/cEhdnTq+ug== - -"@next/swc-linux-arm-gnueabihf@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.0.tgz#9ec6380a27938a5799aaa6035c205b3c478468a7" - integrity sha512-njUd9hpl6o6A5d08dC0cKAgXKCzm5fFtgGe6i0eko8IAdtAPbtHxtpre3VeSxdZvuGFh+hb0REySQP9T1ttkog== - -"@next/swc-linux-arm64-gnu@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.0.tgz#7f4196dff1049cea479607c75b81033ae2dbd093" - integrity sha512-OqangJLkRxVxMhDtcb7Qn1xjzFA3s50EIxY7mljbSCLybU+sByPaWAHY4px97ieOlr2y4S0xdPKkQ3BCAwyo6Q== - -"@next/swc-linux-arm64-musl@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.0.tgz#b445f767569cdc2dddee785ca495e1a88c025566" - integrity sha512-hB8cLSt4GdmOpcwRe2UzI5UWn6HHO/vLkr5OTuNvCJ5xGDwpPXelVkYW/0+C3g5axbDW2Tym4S+MQCkkH9QfWA== - -"@next/swc-linux-x64-gnu@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.0.tgz#67610e9be4fbc987de7535f1bcb17e45fe12f90e" - integrity sha512-OKO4R/digvrVuweSw/uBM4nSdyzsBV5EwkUeeG4KVpkIZEe64ZwRpnFB65bC6hGwxIBnTv5NMSnJ+0K/WmG78A== - -"@next/swc-linux-x64-musl@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.0.tgz#ea19a23db08a9f2e34ac30401f774cf7d1669d31" - integrity sha512-JohhgAHZvOD3rQY7tlp7NlmvtvYHBYgY0x5ZCecUT6eCCcl9lv6iV3nfu82ErkxNk1H893fqH0FUpznZ/H3pSw== - -"@next/swc-win32-arm64-msvc@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.0.tgz#eadf054fc412085659b98e145435bbba200b5283" - integrity sha512-T/3gIE6QEfKIJ4dmJk75v9hhNiYZhQYAoYm4iVo1TgcsuaKLFa+zMPh4056AHiG6n9tn2UQ1CFE8EoybEsqsSw== - -"@next/swc-win32-ia32-msvc@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.0.tgz#68faeae10c89f698bf9d28759172b74c9c21bda1" - integrity sha512-iwnKgHJdqhIW19H9PRPM9j55V6RdcOo6rX+5imx832BCWzkDbyomWnlzBfr6ByUYfhohb8QuH4hSGEikpPqI0Q== - -"@next/swc-win32-x64-msvc@12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.0.tgz#d27e7e76c87a460a4da99c5bfdb1618dcd6cd064" - integrity sha512-aBvcbMwuanDH4EMrL2TthNJy+4nP59Bimn8egqv6GHMVj0a44cU6Au4PjOhLNqEh9l+IpRGBqMTzec94UdC5xg== - "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1811,7 +1751,7 @@ stack-utils "2.0.5" yazl "2.5.1" -"@pmmmwh/react-refresh-webpack-plugin@^0.5.1": +"@pmmmwh/react-refresh-webpack-plugin@0.5.4", "@pmmmwh/react-refresh-webpack-plugin@^0.5.1": version "0.5.4" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.4.tgz#df0d0d855fc527db48aac93c218a0bf4ada41f99" integrity sha512-zZbZeHQDnoTlt2AF+diQT0wsSXpvWiaIOZwBRdltNFhG1+I3ozyaw7U/nBiUwyJ0D+zwdXp0E3bWOl38Ag2BMw== @@ -1826,6 +1766,11 @@ schema-utils "^3.0.0" source-map "^0.7.3" +"@polka/url@^1.0.0-next.20": + version "1.0.0-next.21" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" + integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + "@popperjs/core@^2.5.4", "@popperjs/core@^2.6.0": version "2.11.2" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.2.tgz#830beaec4b4091a9e9398ac50f865ddea52186b9" @@ -2844,6 +2789,13 @@ "@types/connect" "*" "@types/node" "*" +"@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + "@types/color-convert@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/color-convert/-/color-convert-2.0.0.tgz#8f5ee6b9e863dcbee5703f5a517ffb13d3ea4e22" @@ -2856,6 +2808,14 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + "@types/connect@*": version "3.4.35" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" @@ -2868,7 +2828,33 @@ resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.2.tgz#66ad9331f63fe8a3d3d9d8c6e3906dd10f6446e8" integrity sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog== -"@types/express-serve-static-core@^4.17.18": +"@types/eslint-scope@^3.7.0": + version "3.7.3" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" + integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.4.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304" + integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/estree@^0.0.50": + version "0.0.50" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" + integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== + +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": version "4.17.28" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== @@ -2877,7 +2863,7 @@ "@types/qs" "*" "@types/range-parser" "*" -"@types/express@4.17.13": +"@types/express@*", "@types/express@4.17.13", "@types/express@^4.17.13": version "4.17.13" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== @@ -2914,6 +2900,11 @@ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57" integrity sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w== +"@types/html-minifier-terser@^6.0.0": + version "6.1.0" + 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-proxy@^1.17.8": version "1.17.8" resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.8.tgz#968c66903e7e42b483608030ee85800f22d03f55" @@ -2953,7 +2944,7 @@ jest-matcher-utils "^27.0.0" pretty-format "^27.0.0" -"@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== @@ -3083,11 +3074,23 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/retry@^0.12.0": + version "0.12.1" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" + integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== + "@types/scheduler@*": version "0.16.2" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + "@types/serve-static@*": version "1.13.10" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" @@ -3096,6 +3099,13 @@ "@types/mime" "^1" "@types/node" "*" +"@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + "@types/source-list-map@*": version "0.1.2" resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" @@ -3157,6 +3167,13 @@ anymatch "^3.0.0" source-map "^0.6.0" +"@types/ws@^8.2.2": + version "8.5.1" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.1.tgz#79136958b48bc73d5165f286707ceb9f04471599" + integrity sha512-UxlLOfkuQnT2YSBCNq0x86SGOUxas6gAySFeDe2DcnEnA8655UIPoCDorWZCugcvKIL8IUI4oueUfJ1hhZSE2A== + dependencies: + "@types/node" "*" + "@types/yargs-parser@*": version "20.2.1" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" @@ -3310,6 +3327,14 @@ react-lifecycles-compat "^3.0.4" react-textarea-autosize "^6.1.0" +"@webassemblyjs/ast@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" + integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" @@ -3319,16 +3344,31 @@ "@webassemblyjs/helper-wasm-bytecode" "1.9.0" "@webassemblyjs/wast-parser" "1.9.0" +"@webassemblyjs/floating-point-hex-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" + integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== + "@webassemblyjs/floating-point-hex-parser@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== +"@webassemblyjs/helper-api-error@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" + integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== + "@webassemblyjs/helper-api-error@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== +"@webassemblyjs/helper-buffer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" + integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== + "@webassemblyjs/helper-buffer@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" @@ -3353,11 +3393,35 @@ dependencies: "@webassemblyjs/ast" "1.9.0" +"@webassemblyjs/helper-numbers@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" + integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" + integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== + "@webassemblyjs/helper-wasm-bytecode@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== +"@webassemblyjs/helper-wasm-section@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" + integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/helper-wasm-section@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" @@ -3368,6 +3432,13 @@ "@webassemblyjs/helper-wasm-bytecode" "1.9.0" "@webassemblyjs/wasm-gen" "1.9.0" +"@webassemblyjs/ieee754@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" + integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== + dependencies: + "@xtuc/ieee754" "^1.2.0" + "@webassemblyjs/ieee754@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" @@ -3375,6 +3446,13 @@ dependencies: "@xtuc/ieee754" "^1.2.0" +"@webassemblyjs/leb128@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" + integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== + dependencies: + "@xtuc/long" "4.2.2" + "@webassemblyjs/leb128@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" @@ -3382,11 +3460,30 @@ dependencies: "@xtuc/long" "4.2.2" +"@webassemblyjs/utf8@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" + integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== + "@webassemblyjs/utf8@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== +"@webassemblyjs/wasm-edit@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" + integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-wasm-section" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-opt" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wast-printer" "1.11.1" + "@webassemblyjs/wasm-edit@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" @@ -3401,6 +3498,17 @@ "@webassemblyjs/wasm-parser" "1.9.0" "@webassemblyjs/wast-printer" "1.9.0" +"@webassemblyjs/wasm-gen@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" + integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + "@webassemblyjs/wasm-gen@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" @@ -3412,6 +3520,16 @@ "@webassemblyjs/leb128" "1.9.0" "@webassemblyjs/utf8" "1.9.0" +"@webassemblyjs/wasm-opt@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" + integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-buffer" "1.11.1" + "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + "@webassemblyjs/wasm-opt@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" @@ -3422,6 +3540,18 @@ "@webassemblyjs/wasm-gen" "1.9.0" "@webassemblyjs/wasm-parser" "1.9.0" +"@webassemblyjs/wasm-parser@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" + integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/ieee754" "1.11.1" + "@webassemblyjs/leb128" "1.11.1" + "@webassemblyjs/utf8" "1.11.1" + "@webassemblyjs/wasm-parser@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" @@ -3446,6 +3576,14 @@ "@webassemblyjs/helper-fsm" "1.9.0" "@xtuc/long" "4.2.2" +"@webassemblyjs/wast-printer@1.11.1": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" + integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== + dependencies: + "@webassemblyjs/ast" "1.11.1" + "@xtuc/long" "4.2.2" + "@webassemblyjs/wast-printer@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" @@ -3455,6 +3593,23 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" +"@webpack-cli/configtest@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.1.1.tgz#9f53b1b7946a6efc2a749095a4f450e2932e8356" + integrity sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg== + +"@webpack-cli/info@^1.4.0": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.4.1.tgz#2360ea1710cbbb97ff156a3f0f24556e0fc1ebea" + integrity sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA== + dependencies: + envinfo "^7.7.3" + +"@webpack-cli/serve@^1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.6.1.tgz#0de2875ac31b46b6c5bb1ae0a7d7f0ba5678dffe" + integrity sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -3470,7 +3625,7 @@ abab@^2.0.3, abab@^2.0.5: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== -accepts@~1.3.5, accepts@~1.3.8: +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -3486,6 +3641,11 @@ acorn-globals@^6.0.0: acorn "^7.1.1" acorn-walk "^7.1.1" +acorn-import-assertions@^1.7.6: + version "1.8.0" + resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" + integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== + acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -3496,7 +3656,7 @@ acorn-walk@^7.1.1, acorn-walk@^7.2.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn-walk@^8.1.1: +acorn-walk@^8.0.0, acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== @@ -3511,7 +3671,7 @@ acorn@^7.1.1, acorn@^7.4.0, acorn@^7.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.2.4, acorn@^8.4.1: +acorn@^8.0.4, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0: version "8.7.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== @@ -3564,11 +3724,25 @@ ajv-errors@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -3579,6 +3753,16 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^8.0.0, ajv@^8.8.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" + integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ajv@^8.0.1: version "8.9.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.9.0.tgz#738019146638824dea25edcf299dcba1b0e7eb18" @@ -3628,6 +3812,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -3743,6 +3932,11 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= +array-flatten@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + array-includes@^3.0.3, array-includes@^3.1.3, array-includes@^3.1.4: version "3.1.4" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9" @@ -3766,6 +3960,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array-union@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-3.0.1.tgz#da52630d327f8b88cfbfb57728e2af5cd9b6b975" + integrity sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -3867,6 +4066,13 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== +async@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -4142,6 +4348,11 @@ batch-processor@1.0.0: resolved "https://registry.yarnpkg.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8" integrity sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg= +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= + better-opn@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/better-opn/-/better-opn-2.1.1.tgz#94a55b4695dc79288f31d7d0e5f658320759f7c6" @@ -4202,6 +4413,18 @@ body-parser@1.19.2: raw-body "2.4.3" type-is "~1.6.18" +bonjour@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" + integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= + dependencies: + array-flatten "^2.1.0" + deep-equal "^1.0.1" + dns-equal "^1.0.0" + dns-txt "^2.0.2" + multicast-dns "^6.0.1" + multicast-dns-service-types "^1.1.0" + boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" @@ -4334,6 +4557,17 @@ browserslist@^4.12.0, browserslist@^4.16.8, browserslist@^4.17.5, browserslist@^ node-releases "^2.0.1" picocolors "^1.0.0" +browserslist@^4.14.5: + version "4.19.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.3.tgz#29b7caad327ecf2859485f696f9604214bedd383" + integrity sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg== + dependencies: + caniuse-lite "^1.0.30001312" + electron-to-chromium "^1.4.71" + escalade "^3.1.1" + node-releases "^2.0.2" + picocolors "^1.0.0" + bs-logger@0.x: version "0.2.6" resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" @@ -4358,6 +4592,11 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer-indexof@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" + integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -4483,7 +4722,7 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camel-case@^4.1.1: +camel-case@^4.1.1, camel-case@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== @@ -4506,11 +4745,16 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001304: +caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001286, caniuse-lite@^1.0.30001304: version "1.0.30001304" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001304.tgz#38af55ed3fc8220cb13e35e6e7309c8c65a05559" integrity sha512-bdsfZd6K6ap87AGqSHJP/s1V+U6Z5lyrcbBu3ovbCCf8cSYpwTtGrCBObMpJqwxfTbLW6YTIdbb1jEeTelcpYQ== +caniuse-lite@^1.0.30001312: + version "1.0.30001312" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz#e11eba4b87e24d22697dae05455d5aea28550d5f" + integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -4592,7 +4836,7 @@ chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.4.1, chokidar@^3.4.2: +chokidar@^3.4.1, chokidar@^3.4.2, chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -4662,6 +4906,13 @@ clean-css@^4.2.3: dependencies: source-map "~0.6.0" +clean-css@^5.2.2: + version "5.2.4" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.4.tgz#982b058f8581adb2ae062520808fb2429bd487a4" + integrity sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg== + dependencies: + source-map "~0.6.0" + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -4804,6 +5055,11 @@ color@^3.1.2: color-convert "^1.9.3" color-string "^1.6.0" +colorette@^2.0.10, colorette@^2.0.14: + version "2.0.16" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" + integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== + colors@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" @@ -4821,7 +5077,7 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== -commander@8.3.0: +commander@8.3.0, commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== @@ -4841,6 +5097,11 @@ commander@^6.2.1: resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== +commander@^7.0.0, commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -4896,6 +5157,11 @@ concat-stream@^1.5.0: readable-stream "^2.2.2" typedarray "^0.0.6" +connect-history-api-fallback@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== + console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" @@ -4964,6 +5230,18 @@ copy-to-clipboard@^3.3.1: dependencies: toggle-selection "^1.0.6" +copy-webpack-plugin@10.2.4: + version "10.2.4" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz#6c854be3fdaae22025da34b9112ccf81c63308fe" + integrity sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg== + dependencies: + fast-glob "^3.2.7" + glob-parent "^6.0.1" + globby "^12.0.2" + normalize-path "^3.0.0" + schema-utils "^4.0.0" + serialize-javascript "^6.0.0" + core-js-compat@^3.20.0, core-js-compat@^3.20.2, core-js-compat@^3.8.1: version "3.21.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.0.tgz#bcc86aa5a589cee358e7a7fa0a4979d5a76c3885" @@ -5236,7 +5514,7 @@ debug@4, debug@4.3.3, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, de dependencies: ms "2.1.2" -debug@^3.0.0, debug@^3.2.7: +debug@^3.0.0, debug@^3.1.1, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -5258,6 +5536,18 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= +deep-equal@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + deep-equal@^2.0.2: version "2.0.5" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.5.tgz#55cd2fe326d83f9cbf7261ef0e060b3f724c5cb9" @@ -5299,6 +5589,13 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +default-gateway@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" + integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== + dependencies: + execa "^5.0.0" + 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" @@ -5333,6 +5630,20 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +del@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" + integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== + dependencies: + globby "^11.0.1" + graceful-fs "^4.2.4" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.2" + p-map "^4.0.0" + rimraf "^3.0.2" + slash "^3.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -5373,6 +5684,11 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +detect-node@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" + integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== + detect-port@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" @@ -5414,6 +5730,26 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= + +dns-packet@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" + integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== + dependencies: + ip "^1.1.0" + safe-buffer "^5.0.1" + +dns-txt@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" + integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= + dependencies: + buffer-indexof "^1.0.0" + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -5531,6 +5867,11 @@ downshift@^6.0.15: react-is "^17.0.2" tslib "^2.3.0" +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -5551,6 +5892,11 @@ electron-to-chromium@^1.4.17: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.59.tgz#657f2588c048fb95975779f8fea101fad854de89" integrity sha512-AOJ3cAE0TWxz4fQ9zkND5hWrQg16nsZKVz9INOot1oV//u4wWu5xrj9CQMmPTYskkZRunSRc9sAnr4EkexXokg== +electron-to-chromium@^1.4.71: + version "1.4.72" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.72.tgz#19b871f1da8be8199b2330d694fc84fcdb72ecd9" + integrity sha512-9LkRQwjW6/wnSfevR21a3k8sOJ+XWSH7kkzs9/EUenKmuDkndP3W9y1yCZpOxufwGbX3JV8glZZSDb4o95zwXQ== + element-resize-detector@^1.2.2: version "1.2.4" resolved "https://registry.yarnpkg.com/element-resize-detector/-/element-resize-detector-1.2.4.tgz#3e6c5982dd77508b5fa7e6d5c02170e26325c9b1" @@ -5638,6 +5984,14 @@ enhanced-resolve@^5.0.0: graceful-fs "^4.2.4" tapable "^2.2.0" +enhanced-resolve@^5.8.3: + version "5.9.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz#49ac24953ac8452ed8fed2ef1340fc8e043667ee" + integrity sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + enquirer@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -5650,6 +6004,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +envinfo@^7.7.3: + version "7.8.1" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" + integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== + errno@^0.1.3, errno@~0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" @@ -5716,6 +6075,11 @@ es-get-iterator@^1.0.2, es-get-iterator@^1.1.1: is-string "^1.0.5" isarray "^2.0.5" +es-module-lexer@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" + integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -5897,6 +6261,14 @@ eslint-plugin-react@7.29.3: semver "^6.3.0" string.prototype.matchall "^4.0.6" +eslint-scope@5.1.1, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + eslint-scope@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" @@ -5905,14 +6277,6 @@ eslint-scope@^4.0.3: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - eslint-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" @@ -6050,7 +6414,7 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -events@^3.0.0: +events@^3.0.0, events@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -6234,7 +6598,7 @@ fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.2.9: +fast-glob@^3.2.7, fast-glob@^3.2.9: version "3.2.11" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== @@ -6260,6 +6624,11 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastest-levenshtein@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" + integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== + fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -6274,6 +6643,13 @@ fault@^1.0.0: dependencies: format "^0.2.0" +faye-websocket@^0.11.3: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + fb-watchman@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" @@ -6761,6 +7137,13 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + glob-promise@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/glob-promise/-/glob-promise-3.4.0.tgz#b6b8f084504216f702dc2ce8c9bc9ac8866fdb20" @@ -6790,7 +7173,7 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -global@^4.4.0: +global@^4.3.0, global@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== @@ -6817,7 +7200,7 @@ globalthis@^1.0.0: dependencies: define-properties "^1.1.3" -globby@^11.0.2, globby@^11.0.3, globby@^11.0.4: +globby@^11.0.1, globby@^11.0.2, globby@^11.0.3, globby@^11.0.4: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -6829,6 +7212,18 @@ globby@^11.0.2, globby@^11.0.3, globby@^11.0.4: merge2 "^1.4.1" slash "^3.0.0" +globby@^12.0.2: + version "12.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-12.2.0.tgz#2ab8046b4fba4ff6eede835b29f678f90e3d3c22" + integrity sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA== + dependencies: + array-union "^3.0.1" + dir-glob "^3.0.1" + fast-glob "^3.2.7" + ignore "^5.1.9" + merge2 "^1.4.1" + slash "^4.0.0" + globby@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" @@ -6843,11 +7238,23 @@ globby@^9.2.0: pify "^4.0.1" slash "^2.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.9" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + +handle-thing@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" + integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== + handlebars@^4.7.7: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" @@ -7044,6 +7451,13 @@ history@5.0.0: dependencies: "@babel/runtime" "^7.7.6" +history@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/history/-/history-5.3.0.tgz#1548abaa245ba47992f063a0783db91ef201c73b" + integrity sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ== + dependencies: + "@babel/runtime" "^7.7.6" + history@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/history/-/history-5.2.0.tgz#7cdd31cf9bac3c5d31f09c231c9928fad0007b7c" @@ -7072,6 +7486,16 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + hsl-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" @@ -7089,7 +7513,7 @@ html-encoding-sniffer@^2.0.1: dependencies: whatwg-encoding "^1.0.5" -html-entities@^2.1.0: +html-entities@^2.1.0, html-entities@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== @@ -7112,6 +7536,19 @@ html-minifier-terser@^5.0.1: relateurl "^0.2.7" terser "^4.6.3" +html-minifier-terser@^6.0.2: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== + dependencies: + camel-case "^4.1.2" + clean-css "^5.2.2" + commander "^8.3.0" + he "^1.2.0" + param-case "^3.0.4" + relateurl "^0.2.7" + terser "^5.10.0" + html-tags@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" @@ -7122,6 +7559,17 @@ html-void-elements@^1.0.0: resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== +html-webpack-plugin@5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" + integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== + dependencies: + "@types/html-minifier-terser" "^6.0.0" + html-minifier-terser "^6.0.2" + lodash "^4.17.21" + pretty-error "^4.0.0" + tapable "^2.0.0" + html-webpack-plugin@^4.0.0: version "4.5.2" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz#76fc83fa1a0f12dd5f7da0404a54e2699666bc12" @@ -7147,6 +7595,11 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= + http-errors@1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" @@ -7158,6 +7611,21 @@ http-errors@1.8.1: statuses ">= 1.5.0 < 2" toidentifier "1.0.1" +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-parser-js@>=0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.5.tgz#d7c30d5d3c90d865b4a2e870181f9d6f22ac7ac5" + integrity sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA== + http-proxy-agent@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" @@ -7167,7 +7635,7 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-proxy-middleware@2.0.3: +http-proxy-middleware@2.0.3, http-proxy-middleware@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz#5df04f69a89f530c2284cd71eeaa51ba52243289" integrity sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA== @@ -7239,7 +7707,7 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.8, ignore@^5.2.0: +ignore@^5.1.8, ignore@^5.1.9, ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== @@ -7324,7 +7792,7 @@ invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -ip@^1.1.5: +ip@^1.1.0, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= @@ -7334,6 +7802,11 @@ ipaddr.js@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== +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + is-absolute-url@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" @@ -7606,6 +8079,16 @@ is-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" @@ -7633,7 +8116,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-regex@^1.1.1, is-regex@^1.1.2, is-regex@^1.1.4: +is-regex@^1.0.4, is-regex@^1.1.1, is-regex@^1.1.2, is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -8322,7 +8805,7 @@ jest-worker@^26.5.0, jest-worker@^26.6.2: merge-stream "^2.0.0" supports-color "^7.0.0" -jest-worker@^27.5.1: +jest-worker@^27.4.5, jest-worker@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== @@ -8644,6 +9127,11 @@ loader-runner@^2.4.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== +loader-runner@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" + integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== + loader-utils@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" @@ -8653,7 +9141,7 @@ loader-utils@2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" -loader-utils@^1.2.3, loader-utils@^1.4.0: +loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -8741,7 +9229,7 @@ lodash.uniq@4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.0.1, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: +lodash@^4.0.1, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -8898,7 +9386,7 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -memfs@^3.1.2: +memfs@^3.1.2, memfs@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.1.tgz#b78092f466a0dce054d63d39275b24c71d3f1305" integrity sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw== @@ -8993,7 +9481,7 @@ mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.34" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== @@ -9121,7 +9609,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.1, mkdirp@^0.5.3: +mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -9145,6 +9633,11 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" +mrmime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" + integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -9165,6 +9658,19 @@ ms@2.1.3, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +multicast-dns-service-types@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" + integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= + +multicast-dns@^6.0.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" + integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== + dependencies: + dns-packet "^1.3.1" + thunky "^1.0.2" + nan@^2.12.1: version "2.15.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" @@ -9175,7 +9681,7 @@ nanoclone@^0.2.1: resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== -nanoid@^3.1.23, nanoid@^3.1.30: +nanoid@^3.1.23: version "3.2.0" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== @@ -9212,7 +9718,7 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: +neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1, neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -9222,34 +9728,6 @@ nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug== -next-router-mock@^0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/next-router-mock/-/next-router-mock-0.6.5.tgz#46258e1921587a892e29a3052cb0daa2cc503185" - integrity sha512-gh6phWv4YUhFON0rWGmc02ni91m68ICG1HTj2N9bi2Y0MIlp5Z12QITXF4lNtV33wuMeUzrs/Ik6XyNOZ8rmNQ== - -next@12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/next/-/next-12.1.0.tgz#c33d753b644be92fc58e06e5a214f143da61dd5d" - integrity sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q== - dependencies: - "@next/env" "12.1.0" - caniuse-lite "^1.0.30001283" - postcss "8.4.5" - styled-jsx "5.0.0" - use-subscription "1.5.1" - optionalDependencies: - "@next/swc-android-arm64" "12.1.0" - "@next/swc-darwin-arm64" "12.1.0" - "@next/swc-darwin-x64" "12.1.0" - "@next/swc-linux-arm-gnueabihf" "12.1.0" - "@next/swc-linux-arm64-gnu" "12.1.0" - "@next/swc-linux-arm64-musl" "12.1.0" - "@next/swc-linux-x64-gnu" "12.1.0" - "@next/swc-linux-x64-musl" "12.1.0" - "@next/swc-win32-arm64-msvc" "12.1.0" - "@next/swc-win32-ia32-msvc" "12.1.0" - "@next/swc-win32-x64-msvc" "12.1.0" - nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -9277,6 +9755,11 @@ node-fetch@2.6.7, node-fetch@^2.6.1: dependencies: whatwg-url "^5.0.0" +node-forge@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.1.tgz#82794919071ef2eb5c509293325cec8afd0fd53c" + integrity sha512-Fcvtbb+zBcZXbTTVwqGA5W+MKBj56UjVRevvchv5XrcyXbmNdesfZL37nlcWOfpgHhgmxApw3tQbTr4CqNmX4w== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -9316,6 +9799,11 @@ node-releases@^2.0.1: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== +node-releases@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01" + integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== + normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -9403,7 +9891,7 @@ object-inspect@^1.11.0, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== -object-is@^1.1.4: +object-is@^1.0.1, object-is@^1.1.4: version "1.1.5" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== @@ -9489,6 +9977,11 @@ objectorarray@^1.0.5: resolved "https://registry.yarnpkg.com/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" integrity sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg== +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -9515,7 +10008,7 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -open@8.4.0: +open@8.4.0, open@^8.0.9: version "8.4.0" resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== @@ -9532,6 +10025,11 @@ open@^7.0.3: is-docker "^2.0.0" is-wsl "^2.1.1" +opener@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== + optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -9660,6 +10158,14 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" +p-retry@^4.5.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" + integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== + dependencies: + "@types/retry" "^0.12.0" + retry "^0.13.1" + p-timeout@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" @@ -9691,7 +10197,7 @@ parallel-transform@^1.1.0: inherits "^2.0.3" readable-stream "^2.1.5" -param-case@^3.0.3: +param-case@^3.0.3, param-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A== @@ -9956,6 +10462,15 @@ popper.js@^1.14.1: resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b" integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ== +portfinder@^1.0.28: + version "1.0.28" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" + integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== + dependencies: + async "^2.6.2" + debug "^3.1.1" + mkdirp "^0.5.5" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -10025,15 +10540,6 @@ postcss-value-parser@^4.1.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@8.4.5: - version "8.4.5" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" - integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== - dependencies: - nanoid "^3.1.30" - picocolors "^1.0.0" - source-map-js "^1.0.1" - postcss@^7.0.14, postcss@^7.0.26, postcss@^7.0.32, postcss@^7.0.36, postcss@^7.0.5, postcss@^7.0.6: version "7.0.39" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" @@ -10070,6 +10576,14 @@ pretty-error@^2.1.1: lodash "^4.17.20" renderkid "^2.0.4" +pretty-error@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6" + integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw== + dependencies: + lodash "^4.17.20" + renderkid "^3.0.0" + pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.2.5, pretty-format@^27.5.1: version "27.5.1" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" @@ -10150,7 +10664,7 @@ prompts@^2.0.1, prompts@^2.4.0: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -10431,6 +10945,20 @@ react-helmet-async@^1.0.7: react-fast-compare "^3.2.0" shallowequal "^1.1.0" +react-hot-loader@4.13.0: + version "4.13.0" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.13.0.tgz#c27e9408581c2a678f5316e69c061b226dc6a202" + integrity sha512-JrLlvUPqh6wIkrK2hZDfOyq/Uh/WeVEr8nc7hkn2/3Ul0sx1Kr5y4kOGNacNRoj7RhwLNcQ3Udf1KJXrqc0ZtA== + dependencies: + fast-levenshtein "^2.0.6" + global "^4.3.0" + hoist-non-react-statics "^3.3.0" + loader-utils "^1.1.0" + prop-types "^15.6.1" + react-lifecycles-compat "^3.0.4" + shallowequal "^1.1.0" + source-map "^0.7.3" + react-inspector@^5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-5.1.1.tgz#58476c78fde05d5055646ed8ec02030af42953c8" @@ -10477,7 +11005,7 @@ react-refresh@^0.11.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== -react-router-dom@^6.0.0: +react-router-dom@6.2.1, react-router-dom@^6.0.0: version "6.2.1" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.2.1.tgz#32ec81829152fbb8a7b045bf593a22eadf019bec" integrity sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA== @@ -10586,7 +11114,7 @@ read-pkg@^5.2.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.6.0: +readable-stream@^3.0.6, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -10611,6 +11139,13 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +rechoir@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" + integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== + dependencies: + resolve "^1.9.0" + refractor@^3.1.0: version "3.5.0" resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.5.0.tgz#334586f352dda4beaf354099b48c2d18e0819aec" @@ -10652,7 +11187,7 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexp.prototype.flags@^1.3.0, regexp.prototype.flags@^1.3.1: +regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0, regexp.prototype.flags@^1.3.1: version "1.4.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== @@ -10778,6 +11313,17 @@ renderkid@^2.0.4: lodash "^4.17.21" strip-ansi "^3.0.1" +renderkid@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a" + integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg== + dependencies: + css-select "^4.1.3" + dom-converter "^0.2.0" + htmlparser2 "^6.1.0" + lodash "^4.17.21" + strip-ansi "^6.0.1" + repeat-element@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" @@ -10835,7 +11381,7 @@ resolve.exports@^1.1.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.3.2: +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.3.2, resolve@^1.9.0: version "1.22.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== @@ -10862,6 +11408,11 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -10933,7 +11484,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.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: +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.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== @@ -11007,7 +11558,7 @@ schema-utils@^2.6.5, schema-utils@^2.7.0: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0: +schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== @@ -11016,6 +11567,28 @@ schema-utils@^3.0.0: ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= + +selfsigned@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.0.tgz#e927cd5377cbb0a1075302cff8df1042cc2bce5b" + integrity sha512-cUdFiCbKoa1mZ6osuJs2uDHrs0k0oprsKveFiiaBKCNq3SYyb5gs2HxhQyDNLCmL51ZZThqi4YNDpCK6GOP1iQ== + dependencies: + node-forge "^1.2.0" + "semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -11071,6 +11644,13 @@ serialize-javascript@^5.0.1: dependencies: randombytes "^2.1.0" +serialize-javascript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + serve-favicon@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.5.0.tgz#935d240cdfe0f5805307fdfe967d88942a2cbcf0" @@ -11082,6 +11662,19 @@ serve-favicon@^2.5.0: parseurl "~1.3.2" safe-buffer "5.1.1" +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + serve-static@1.14.2: version "1.14.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" @@ -11112,6 +11705,11 @@ setimmediate@^1.0.4, setimmediate@^1.0.5: resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" @@ -11182,6 +11780,15 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +sirv@^1.0.7: + version "1.0.19" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" + integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== + dependencies: + "@polka/url" "^1.0.0-next.20" + mrmime "^1.0.0" + totalist "^1.0.0" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -11197,6 +11804,11 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + slice-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" @@ -11241,6 +11853,15 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +sockjs@^0.3.21: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== + dependencies: + faye-websocket "^0.11.3" + uuid "^8.3.2" + websocket-driver "^0.7.4" + socks-proxy-agent@6.1.1: version "6.1.1" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87" @@ -11263,11 +11884,6 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-js@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -11345,6 +11961,29 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -11357,7 +11996,7 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -sql-formatter@^4.0.2: +sql-formatter@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/sql-formatter/-/sql-formatter-4.0.2.tgz#2b359e5a4c611498d327b9659da7329d71724607" integrity sha512-R6u9GJRiXZLr/lDo8p56L+OyyN2QFJPCDnsyEOsbdIpsnDKL8gubYFo7lNR7Zx7hfdWT80SfkoVS0CMaF/DE2w== @@ -11408,7 +12047,7 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= @@ -11543,6 +12182,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" + integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -11590,11 +12236,6 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" -styled-jsx@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0.tgz#816b4b92e07b1786c6b7111821750e0ba4d26e77" - integrity sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA== - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -11670,7 +12311,7 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tapable@^2.2.0: +tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== @@ -11739,6 +12380,17 @@ terser-webpack-plugin@^4.2.3: terser "^5.3.4" webpack-sources "^1.4.3" +terser-webpack-plugin@^5.1.3: + version "5.3.1" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.1.tgz#0320dcc270ad5372c1e8993fabbd927929773e54" + integrity sha512-GvlZdT6wPQKbDNW/GDQzZFg/j4vKU96yl2q6mcUkzKOgW4gwf1Z8cZToUCrz31XHlPWH8MVb1r2tFtdDtTGJ7g== + dependencies: + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.0" + source-map "^0.6.1" + terser "^5.7.2" + terser@^4.1.2, terser@^4.6.3: version "4.8.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" @@ -11748,6 +12400,16 @@ terser@^4.1.2, terser@^4.6.3: source-map "~0.6.1" source-map-support "~0.5.12" +terser@^5.10.0, terser@^5.7.2: + version "5.11.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.11.0.tgz#2da5506c02e12cd8799947f30ce9c5b760be000f" + integrity sha512-uCA9DLanzzWSsN1UirKwylhhRz3aKPInlfmpGfw8VN6jHsAtu8HJtIpeeHHK23rxnE/cDc+yvmq5wqkIC6Kn0A== + dependencies: + acorn "^8.5.0" + commander "^2.20.0" + source-map "~0.7.2" + source-map-support "~0.5.20" + terser@^5.3.4: version "5.10.0" resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" @@ -11794,6 +12456,11 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + timers-browserify@^2.0.4: version "2.0.12" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" @@ -11873,6 +12540,11 @@ toposort@^2.0.2: resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= +totalist@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" + integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== + tough-cookie@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" @@ -12282,13 +12954,6 @@ use-latest@^1.0.0: dependencies: use-isomorphic-layout-effect "^1.0.0" -use-subscription@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1" - integrity sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA== - dependencies: - object-assign "^4.1.1" - use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -12452,7 +13117,7 @@ watchpack@^1.7.4: chokidar "^3.4.1" watchpack-chokidar2 "^2.0.1" -watchpack@^2.2.0: +watchpack@^2.2.0, watchpack@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" integrity sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA== @@ -12460,6 +13125,13 @@ watchpack@^2.2.0: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + web-namespaces@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" @@ -12480,6 +13152,39 @@ webidl-conversions@^6.1.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== +webpack-bundle-analyzer@4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" + integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== + dependencies: + acorn "^8.0.4" + acorn-walk "^8.0.0" + chalk "^4.1.0" + commander "^7.2.0" + gzip-size "^6.0.0" + lodash "^4.17.20" + opener "^1.5.2" + sirv "^1.0.7" + ws "^7.3.1" + +webpack-cli@4.9.1: + version "4.9.1" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.1.tgz#b64be825e2d1b130f285c314caa3b1ba9a4632b3" + integrity sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^1.1.0" + "@webpack-cli/info" "^1.4.0" + "@webpack-cli/serve" "^1.6.0" + colorette "^2.0.14" + commander "^7.0.0" + execa "^5.0.0" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^2.2.0" + rechoir "^0.7.0" + webpack-merge "^5.7.3" + webpack-dev-middleware@^3.7.3: version "3.7.3" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" @@ -12491,6 +13196,53 @@ webpack-dev-middleware@^3.7.3: range-parser "^1.2.1" webpack-log "^2.0.0" +webpack-dev-middleware@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz#aa079a8dedd7e58bfeab358a9af7dab304cee57f" + integrity sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg== + dependencies: + colorette "^2.0.10" + memfs "^3.4.1" + mime-types "^2.1.31" + range-parser "^1.2.1" + schema-utils "^4.0.0" + +webpack-dev-server@4.7.4: + version "4.7.4" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.7.4.tgz#d0ef7da78224578384e795ac228d8efb63d5f945" + integrity sha512-nfdsb02Zi2qzkNmgtZjkrMOcXnYZ6FLKcQwpxT7MvmHKc+oTtDsBju8j+NMyAygZ9GW1jMEUpy3itHtqgEhe1A== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.2.2" + ansi-html-community "^0.0.8" + bonjour "^3.5.0" + chokidar "^3.5.3" + colorette "^2.0.10" + compression "^1.7.4" + connect-history-api-fallback "^1.6.0" + default-gateway "^6.0.3" + del "^6.0.0" + express "^4.17.1" + graceful-fs "^4.2.6" + html-entities "^2.3.2" + http-proxy-middleware "^2.0.0" + ipaddr.js "^2.0.1" + open "^8.0.9" + p-retry "^4.5.0" + portfinder "^1.0.28" + schema-utils "^4.0.0" + selfsigned "^2.0.0" + serve-index "^1.9.1" + sockjs "^0.3.21" + spdy "^4.0.2" + strip-ansi "^7.0.0" + webpack-dev-middleware "^5.3.1" + ws "^8.4.2" + webpack-filter-warnings-plugin@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz#dc61521cf4f9b4a336fbc89108a75ae1da951cdb" @@ -12514,6 +13266,14 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" +webpack-merge@^5.7.3: + version "5.8.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" + integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" @@ -12522,6 +13282,11 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: source-list-map "^2.0.0" source-map "~0.6.1" +webpack-sources@^3.2.2: + version "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-virtual-modules@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.2.2.tgz#20863dc3cb6bb2104729fff951fbe14b18bd0299" @@ -12558,6 +13323,50 @@ webpack@4: watchpack "^1.7.4" webpack-sources "^1.4.1" +webpack@5.65.0: + version "5.65.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.65.0.tgz#ed2891d9145ba1f0d318e4ea4f89c3fa18e6f9be" + integrity sha512-Q5or2o6EKs7+oKmJo7LaqZaMOlDWQse9Tm5l1WAfU/ujLGN5Pb0SqGeVkN/4bpPmEqEP5RnVhiqsOtWtUVwGRw== + dependencies: + "@types/eslint-scope" "^3.7.0" + "@types/estree" "^0.0.50" + "@webassemblyjs/ast" "1.11.1" + "@webassemblyjs/wasm-edit" "1.11.1" + "@webassemblyjs/wasm-parser" "1.11.1" + acorn "^8.4.1" + acorn-import-assertions "^1.7.6" + browserslist "^4.14.5" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.8.3" + es-module-lexer "^0.9.0" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.4" + json-parse-better-errors "^1.0.2" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.1.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.1.3" + watchpack "^2.3.1" + webpack-sources "^3.2.2" + +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" @@ -12648,6 +13457,11 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" +wildcard@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" + integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== + word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -12701,11 +13515,21 @@ ws@8.4.2, ws@^8.2.3: resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b" integrity sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA== +ws@^7.3.1: + version "7.5.7" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" + integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== + ws@^7.4.6: version "7.5.6" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== +ws@^8.4.2: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"