diff --git a/client/config/webpack.common.ts b/client/config/webpack.common.ts index 31ba243b2b..98f0dade73 100644 --- a/client/config/webpack.common.ts +++ b/client/config/webpack.common.ts @@ -186,9 +186,6 @@ const config: Configuration = { }, ], }), - // new WatchIgnorePlugin({ - // paths: [/\.js$/, /\.d\.ts$/], - // }), new MonacoWebpackPlugin({ filename: "monaco/[name].worker.js", languages: Object.values(LANGUAGES_BY_FILE_EXTENSION), diff --git a/client/config/webpack.dev.ts b/client/config/webpack.dev.ts index f1e4f6569d..7827b6748f 100644 --- a/client/config/webpack.dev.ts +++ b/client/config/webpack.dev.ts @@ -3,10 +3,11 @@ import { mergeWithRules } from "webpack-merge"; import type { Configuration as WebpackConfiguration } from "webpack"; import type { Configuration as DevServerConfiguration } from "webpack-dev-server"; +import CopyPlugin from "copy-webpack-plugin"; +import HtmlWebpackPlugin from "html-webpack-plugin"; import ReactRefreshTypeScript from "react-refresh-typescript"; import ReactRefreshWebpackPlugin from "@pmmmwh/react-refresh-webpack-plugin"; import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin"; -import HtmlWebpackPlugin from "html-webpack-plugin"; import { encodeEnv, KONVEYOR_ENV, proxyMap } from "@konveyor-ui/common"; import { stylePaths } from "./stylePaths"; @@ -79,6 +80,13 @@ const config: Configuration = mergeWithRules({ mode: "readonly", }, }), + new CopyPlugin({ + patterns: [ + { + from: pathTo("../public/mockServiceWorker.js"), + }, + ], + }), // index.html generated at compile time to inject `_env` new HtmlWebpackPlugin({ filename: "index.html", diff --git a/client/package.json b/client/package.json index d8bcab5de6..a1445f48ec 100644 --- a/client/package.json +++ b/client/package.json @@ -91,6 +91,7 @@ "jest-watch-typeahead": "^1.0.0", "mini-css-extract-plugin": "^2.5.2", "monaco-editor-webpack-plugin": "^7.0.1", + "msw": "^1.2.3", "prettier": "^2.2.1", "pretty-quick": "^3.1.3", "raw-loader": "^4.0.2", @@ -130,5 +131,8 @@ }, "nyc": { "exclude": "client/src/reportWebVitals.ts" + }, + "msw": { + "workerDirectory": "public" } } diff --git a/client/public/mockServiceWorker.js b/client/public/mockServiceWorker.js new file mode 100644 index 0000000000..e5aa935a60 --- /dev/null +++ b/client/public/mockServiceWorker.js @@ -0,0 +1,303 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker (1.2.3). + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + * - Please do NOT serve this file on production. + */ + +const INTEGRITY_CHECKSUM = "3d6b9f06410d179a7f7404d4bf4c3c70"; +const activeClientIds = new Set(); + +self.addEventListener("install", function () { + self.skipWaiting(); +}); + +self.addEventListener("activate", function (event) { + event.waitUntil(self.clients.claim()); +}); + +self.addEventListener("message", async function (event) { + const clientId = event.source.id; + + if (!clientId || !self.clients) { + return; + } + + const client = await self.clients.get(clientId); + + if (!client) { + return; + } + + const allClients = await self.clients.matchAll({ + type: "window", + }); + + switch (event.data) { + case "KEEPALIVE_REQUEST": { + sendToClient(client, { + type: "KEEPALIVE_RESPONSE", + }); + break; + } + + case "INTEGRITY_CHECK_REQUEST": { + sendToClient(client, { + type: "INTEGRITY_CHECK_RESPONSE", + payload: INTEGRITY_CHECKSUM, + }); + break; + } + + case "MOCK_ACTIVATE": { + activeClientIds.add(clientId); + + sendToClient(client, { + type: "MOCKING_ENABLED", + payload: true, + }); + break; + } + + case "MOCK_DEACTIVATE": { + activeClientIds.delete(clientId); + break; + } + + case "CLIENT_CLOSED": { + activeClientIds.delete(clientId); + + const remainingClients = allClients.filter((client) => { + return client.id !== clientId; + }); + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister(); + } + + break; + } + } +}); + +self.addEventListener("fetch", function (event) { + const { request } = event; + const accept = request.headers.get("accept") || ""; + + // Bypass server-sent events. + if (accept.includes("text/event-stream")) { + return; + } + + // Bypass navigation requests. + if (request.mode === "navigate") { + return; + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (request.cache === "only-if-cached" && request.mode !== "same-origin") { + return; + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been deleted (still remains active until the next reload). + if (activeClientIds.size === 0) { + return; + } + + // Generate unique request ID. + const requestId = Math.random().toString(16).slice(2); + + event.respondWith( + handleRequest(event, requestId).catch((error) => { + if (error.name === "NetworkError") { + console.warn( + '[MSW] Successfully emulated a network error for the "%s %s" request.', + request.method, + request.url + ); + return; + } + + // At this point, any exception indicates an issue with the original request/response. + console.error( + `\ +[MSW] Caught an exception from the "%s %s" request (%s). This is probably not a problem with Mock Service Worker. There is likely an additional logging output above.`, + request.method, + request.url, + `${error.name}: ${error.message}` + ); + }) + ); +}); + +async function handleRequest(event, requestId) { + const client = await resolveMainClient(event); + const response = await getResponse(event, client, requestId); + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + (async function () { + const clonedResponse = response.clone(); + sendToClient(client, { + type: "RESPONSE", + payload: { + requestId, + type: clonedResponse.type, + ok: clonedResponse.ok, + status: clonedResponse.status, + statusText: clonedResponse.statusText, + body: + clonedResponse.body === null ? null : await clonedResponse.text(), + headers: Object.fromEntries(clonedResponse.headers.entries()), + redirected: clonedResponse.redirected, + }, + }); + })(); + } + + return response; +} + +// Resolve the main client for the given event. +// Client that issues a request doesn't necessarily equal the client +// that registered the worker. It's with the latter the worker should +// communicate with during the response resolving phase. +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId); + + if (client?.frameType === "top-level") { + return client; + } + + const allClients = await self.clients.matchAll({ + type: "window", + }); + + return allClients + .filter((client) => { + // Get only those clients that are currently visible. + return client.visibilityState === "visible"; + }) + .find((client) => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id); + }); +} + +async function getResponse(event, client, requestId) { + const { request } = event; + const clonedRequest = request.clone(); + + function passthrough() { + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the client). + const headers = Object.fromEntries(clonedRequest.headers.entries()); + + // Remove MSW-specific request headers so the bypassed requests + // comply with the server's CORS preflight check. + // Operate with the headers as an object because request "Headers" + // are immutable. + delete headers["x-msw-bypass"]; + + return fetch(clonedRequest, { headers }); + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough(); + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough(); + } + + // Bypass requests with the explicit bypass header. + // Such requests can be issued by "ctx.fetch()". + if (request.headers.get("x-msw-bypass") === "true") { + return passthrough(); + } + + // Notify the client that a request has been intercepted. + const clientMessage = await sendToClient(client, { + type: "REQUEST", + payload: { + id: requestId, + url: request.url, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + mode: request.mode, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: await request.text(), + bodyUsed: request.bodyUsed, + keepalive: request.keepalive, + }, + }); + + switch (clientMessage.type) { + case "MOCK_RESPONSE": { + return respondWithMock(clientMessage.data); + } + + case "MOCK_NOT_FOUND": { + return passthrough(); + } + + case "NETWORK_ERROR": { + const { name, message } = clientMessage.data; + const networkError = new Error(message); + networkError.name = name; + + // Rejecting a "respondWith" promise emulates a network error. + throw networkError; + } + } + + return passthrough(); +} + +function sendToClient(client, message) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel(); + + channel.port1.onmessage = (event) => { + if (event.data && event.data.error) { + return reject(event.data.error); + } + + resolve(event.data); + }; + + client.postMessage(message, [channel.port2]); + }); +} + +function sleep(timeMs) { + return new Promise((resolve) => { + setTimeout(resolve, timeMs); + }); +} + +async function respondWithMock(response) { + await sleep(response.delay); + return new Response(response.body, response); +} diff --git a/client/src/app/api/rest.ts b/client/src/app/api/rest.ts index f6f1558998..14d1677276 100644 --- a/client/src/app/api/rest.ts +++ b/client/src/app/api/rest.ts @@ -748,9 +748,13 @@ export const updateProxy = (obj: Proxy): Promise => export const getQuestionnaires = (): Promise => axios.get(QUESTIONNAIRES).then((response) => response.data); +// TODO: The update handlers in hub don't return any content (success is a response code +// TODO: of 204 - NoContext) ... the return type does not make sense. export const updateQuestionnaire = ( obj: Questionnaire ): Promise => axios.put(`${QUESTIONNAIRES}/${obj.id}`, obj); +// TODO: The delete handlers in hub don't return any content (success is a response code +// TODO: of 204 - NoContext) ... the return type does not make sense. export const deleteQuestionnaire = (id: number): Promise => axios.delete(`${QUESTIONNAIRES}/${id}`); diff --git a/client/src/app/pages/assessment/AssessmentSettings.tsx b/client/src/app/pages/assessment/AssessmentSettings.tsx index 6f1b83bbbc..3b83122e6e 100644 --- a/client/src/app/pages/assessment/AssessmentSettings.tsx +++ b/client/src/app/pages/assessment/AssessmentSettings.tsx @@ -54,40 +54,7 @@ export const AssessmentSettings: React.FC = () => { const { pushNotification } = React.useContext(NotificationsContext); - // TODO Replace with Hub API when ready - const [mockQuestionnaires, setMockQuestionnaires] = React.useState< - Questionnaire[] - >([ - { - id: 1, - name: "System questionnaire", - questions: 42, - rating: "5% Red, 25% Yellow", - dateImported: "8 Aug. 2023, 10:20 AM EST", - required: false, - system: true, - }, - { - id: 2, - name: "Custom questionnaire", - questions: 24, - rating: "15% Red, 35% Yellow", - dateImported: "9 Aug. 2023, 03:32 PM EST", - required: true, - system: false, - }, - { - id: 3, - name: "Ruby questionnaire", - questions: 34, - rating: "7% Red, 25% Yellow", - dateImported: "10 Aug. 2023, 11:23 PM EST", - required: true, - system: false, - }, - ]); - const { questionnaires, isFetching, fetchError } = - useFetchQuestionnaires(mockQuestionnaires); + const { questionnaires, isFetching, fetchError } = useFetchQuestionnaires(); const onSaveQuestionnaireSuccess = () => {}; @@ -98,7 +65,7 @@ export const AssessmentSettings: React.FC = () => { }); }; - const { mutationFn: updateQuestionnaire } = useUpdateQuestionnaireMutation( + const { mutate: updateQuestionnaire } = useUpdateQuestionnaireMutation( onSaveQuestionnaireSuccess, onSaveQuestionnaireError ); @@ -113,7 +80,7 @@ export const AssessmentSettings: React.FC = () => { }); }; - const { mutationFn: deleteQuestionnaire } = useDeleteQuestionnaireMutation( + const { mutate: deleteQuestionnaire } = useDeleteQuestionnaireMutation( onDeleteQuestionnaireSuccess, onSaveQuestionnaireError ); @@ -126,9 +93,8 @@ export const AssessmentSettings: React.FC = () => { const [questionnaireToExport, setQuestionnaireToExport] = React.useState< number | null >(null); - const [questionnaireToDelete, setQuestionnaireToDelete] = React.useState< - number | null - >(null); + const [questionnaireToDelete, setQuestionnaireToDelete] = + React.useState(); const tableControls = useLocalTableControls({ idProperty: "id", @@ -297,15 +263,10 @@ export const AssessmentSettings: React.FC = () => { labelOff="No" isChecked={questionnaire.required} onChange={() => { - updateQuestionnaire( - { - ...questionnaire, - required: !questionnaire.required, - }, - // TODO Remove mock when Hub API is ready - mockQuestionnaires, - setMockQuestionnaires - ); + updateQuestionnaire({ + ...questionnaire, + required: !questionnaire.required, + }); }} /> @@ -380,7 +341,7 @@ export const AssessmentSettings: React.FC = () => { key="delete" isAriaDisabled={questionnaire.system === true} onClick={() => - setQuestionnaireToDelete(questionnaire.id) + setQuestionnaireToDelete(questionnaire) } > {t("actions.delete")} @@ -461,12 +422,7 @@ export const AssessmentSettings: React.FC = () => { onClose={() => setQuestionnaireToDelete(null)} onConfirm={() => { if (questionnaireToDelete) { - deleteQuestionnaire( - questionnaireToDelete, - // TODO Remove mock when Hub API is ready - mockQuestionnaires, - setMockQuestionnaires - ); + deleteQuestionnaire({ questionnaire: questionnaireToDelete }); setQuestionnaireToDelete(null); } }} diff --git a/client/src/app/queries/questionnaires.ts b/client/src/app/queries/questionnaires.ts index 76a68bd45c..38c008b8dc 100644 --- a/client/src/app/queries/questionnaires.ts +++ b/client/src/app/queries/questionnaires.ts @@ -1,7 +1,6 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { AxiosError } from "axios"; -// TODO Uncomment when Hub API is ready import { deleteQuestionnaire, getQuestionnaires, @@ -11,104 +10,54 @@ import { Questionnaire } from "@app/api/models"; export const QuestionnairesTasksQueryKey = "questionnaires"; -// TODO Remove when Hub API is ready -export const useFetchQuestionnaires = (mockQuestionnaires: Questionnaire[]) => { +export const useFetchQuestionnaires = () => { + const { isLoading, data, error } = useQuery({ + queryKey: [QuestionnairesTasksQueryKey], + queryFn: getQuestionnaires, + onError: (error: AxiosError) => console.log("error, ", error), + }); + return { - questionnaires: mockQuestionnaires, - isFetching: false, - fetchError: null, + questionnaires: data || [], + isFetching: isLoading, + fetchError: error, }; }; -// TODO Uncomment when Hub API is ready -// export const useFetchQuestionnaires = () => { -// const { isLoading, data, error } = useQuery({ -// queryKey: [QuestionnairesTasksQueryKey], -// queryFn: getQuestionnaires, -// onError: (error) => console.log("error, ", error), -// }); -// return { -// questionnaires: data || [], -// isFetching: isLoading, -// fetchError: error as AxiosErr_event - -// TODO Remove when Hub API is ready -const mockUpdateQuestionnaire = ( - obj: Questionnaire, - mockQuestionnaires: Questionnaire[], - setMockQuestionnaires: (questionnaires: Questionnaire[]) => void -) => { - const newMockQuestionnaires = mockQuestionnaires.map((questionnaire) => - questionnaire.id === obj.id ? obj : questionnaire - ); - setMockQuestionnaires(newMockQuestionnaires); -}; - -// TODO Remove when Hub API is ready export const useUpdateQuestionnaireMutation = ( onSuccess: () => void, onError: (err: AxiosError) => void ) => { - return { - mutationFn: mockUpdateQuestionnaire, - }; -}; + const queryClient = useQueryClient(); -// TODO Uncomment when Hub API is ready -// export const useUpdateQuestionnaireMutation = ( -// onSuccess: () => void, -// onError: (err: AxiosError) => void -// ) => { -// const queryClient = useQueryClient(); -// return useMutation({ -// mutationFn: updateQuestionnaire, -// onSuccess: () => { -// onSuccess(); -// queryClient.invalidateQueries([QuestionnairesTasksQueryKey]); -// }, -// onError: onError, -// }); -// }; + return useMutation({ + mutationFn: updateQuestionnaire, -// TODO Remove when Hub API is ready -const mockDeleteQuestionnaire = ( - id: number, - mockQuestionnaires: Questionnaire[], - setMockQuestionnaires: (questionnaires: Questionnaire[]) => void -) => { - const newMockQuestionnaires = mockQuestionnaires.filter( - (questionnaire) => questionnaire.id !== id - ); - setMockQuestionnaires(newMockQuestionnaires); + onSuccess: () => { + onSuccess(); + queryClient.invalidateQueries([QuestionnairesTasksQueryKey]); + }, + onError: onError, + }); }; -// TODO Remove when Hub API is ready export const useDeleteQuestionnaireMutation = ( - onSuccess: (name: string) => void, + onSuccess: (questionnaireName: string) => void, onError: (err: AxiosError) => void ) => { - return { - mutationFn: mockDeleteQuestionnaire, - }; + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({ questionnaire }: { questionnaire: Questionnaire }) => + deleteQuestionnaire(questionnaire.id), + + onSuccess: (_, { questionnaire }) => { + onSuccess(questionnaire.name); + queryClient.invalidateQueries([QuestionnairesTasksQueryKey]); + }, + onError: (err: AxiosError) => { + onError(err); + queryClient.invalidateQueries([QuestionnairesTasksQueryKey]); + }, + }); }; - -// TODO Uncomment when Hub API is ready -// export const useDeleteQuestionnaireMutation = ( -// onSuccess: (name: string) => void, -// onError: (err: AxiosError) => void -// ) => { -// const queryClient = useQueryClient(); - -// return useMutation({ -// mutationFn: ({ questionnaire }: { questionnaire: Questionnaire }) => -// deleteQuestionnaire(questionnaire.id), -// onSuccess: (_, vars) => { -// onSuccess(vars.questionnaire.name); -// queryClient.invalidateQueries([QuestionnairesTasksQueryKey]); -// }, -// onError: (err: AxiosError) => { -// onError(err); -// queryClient.invalidateQueries([QuestionnairesTasksQueryKey]); -// }, -// }); -// }; diff --git a/client/src/index.tsx b/client/src/index.tsx index cd75014e55..0cc1915b8b 100644 --- a/client/src/index.tsx +++ b/client/src/index.tsx @@ -7,6 +7,12 @@ import App from "@app/App"; import reportWebVitals from "@app/reportWebVitals"; import { KeycloakProvider } from "@app/components/KeycloakProvider"; +if (process.env.NODE_ENV === "development") { + import("./mocks/browser").then((browserMocks) => { + browserMocks.worker.start(); + }); +} + const queryClient = new QueryClient(); ReactDOM.render( diff --git a/client/src/mocks/browser.ts b/client/src/mocks/browser.ts new file mode 100644 index 0000000000..8511784712 --- /dev/null +++ b/client/src/mocks/browser.ts @@ -0,0 +1,19 @@ +import { type RestHandler, setupWorker, rest } from "msw"; + +import StubsForNewWork from "./stub-new-work"; + +const otherHandlers: RestHandler[] = [...StubsForNewWork]; + +export const worker = setupWorker( + ...otherHandlers, + + rest.all("/hub/*", (req) => { + console.log( + "%cmsw passthrough%c \u{1fa83} %s", + "font-weight: bold", + "font-weight: normal", + req.url + ); + return req.passthrough(); + }) +); diff --git a/client/src/mocks/server.ts b/client/src/mocks/server.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/client/src/mocks/stub-new-work/index.ts b/client/src/mocks/stub-new-work/index.ts new file mode 100644 index 0000000000..9a1d475551 --- /dev/null +++ b/client/src/mocks/stub-new-work/index.ts @@ -0,0 +1,5 @@ +import { type RestHandler } from "msw"; + +import questionnaires from "./questionnaires"; + +export default [...questionnaires] as RestHandler[]; diff --git a/client/src/mocks/stub-new-work/questionnaires.ts b/client/src/mocks/stub-new-work/questionnaires.ts new file mode 100644 index 0000000000..ec9ed8fa28 --- /dev/null +++ b/client/src/mocks/stub-new-work/questionnaires.ts @@ -0,0 +1,98 @@ +import { type RestHandler, rest } from "msw"; + +import * as AppRest from "@app/api/rest"; +import type { Questionnaire } from "@app/api/models"; + +/** + * Simple stub handlers as place holders until hub API is ready. + * + * Handler structure modeled after hub api handler: + * https://github.com/konveyor/tackle2-hub/blob/main/api/tag.go + */ +const handlers: RestHandler[] = [ + rest.get(AppRest.QUESTIONNAIRES, (req, res, ctx) => { + console.log( + "%cquestionnaire stub%c \u{1f916} %s", + "font-weight: bold; color: green;", + "font-weight: normal; color: auto;", + `get the list of questionnaires` + ); + + const dataAsList = Array.from(Object.values(data)); + return res(ctx.json(dataAsList)); + }), + + rest.put(`${AppRest.QUESTIONNAIRES}/:id`, async (req, res, ctx) => { + const { id } = req.params; + const updates = await req.json(); + + console.log( + "%cquestionnaire stub%c \u{1f916} %s", + "font-weight: bold; color: green;", + "font-weight: normal; color: auto;", + `update questionnaire ${id} \u{2192}`, + updates + ); + + const id_ = Array.isArray(id) ? id[0] : id; + if (id_ in data) { + data[id_] = updates; + return res(ctx.status(204)); // follow the hub handler success response == StatusNoContent + } + return res(ctx.status(404)); // hub doesn't do this, it fails silently + }), + + rest.delete(`${AppRest.QUESTIONNAIRES}/:id`, (req, res, ctx) => { + const { id } = req.params; + console.log( + "%cquestionnaire stub%c \u{1f916} %s", + "font-weight: bold; color: green;", + "font-weight: normal; color: auto;", + `delete questionnaire ${id}` + ); + + const id_ = Array.isArray(id) ? id[0] : id; + if (id_ in data) { + delete data[id_]; + return res(ctx.status(204)); // follow the hub handler success response == StatusNoContent + } + return res(ctx.status(404)); // hub doesn't do this, it fails silently + }), +]; + +/** + * The questionnaire data for the handlers! + */ +const data: Record = { + 1: { + id: 1, + name: "System questionnaire", + questions: 42, + rating: "5% Red, 25% Yellow", + dateImported: "8 Aug. 2023, 10:20 AM EST", + required: false, + system: true, + }, + + 2: { + id: 2, + name: "Custom questionnaire", + questions: 24, + rating: "15% Red, 35% Yellow", + dateImported: "9 Aug. 2023, 03:32 PM EST", + required: true, + system: false, + }, + + 3: { + id: 3, + name: "Ruby questionnaire", + questions: 34, + rating: "7% Red, 25% Yellow", + dateImported: "10 Aug. 2023, 11:23 PM EST", + required: true, + system: false, + }, +}; + +export default handlers; diff --git a/codecov.yml b/codecov.yml index 77f3b42e01..0f76d6b496 100644 --- a/codecov.yml +++ b/codecov.yml @@ -27,3 +27,6 @@ flags: server: paths: - server/ + +ignore: + - "**/mockServiceWorker.js" diff --git a/package-lock.json b/package-lock.json index b39dbb7ced..269d0d4899 100644 --- a/package-lock.json +++ b/package-lock.json @@ -114,6 +114,7 @@ "jest-watch-typeahead": "^1.0.0", "mini-css-extract-plugin": "^2.5.2", "monaco-editor-webpack-plugin": "^7.0.1", + "msw": "^1.2.3", "prettier": "^2.2.1", "pretty-quick": "^3.1.3", "raw-loader": "^4.0.2", @@ -3087,6 +3088,47 @@ "react-dom": "^17.0.1" } }, + "node_modules/@mswjs/cookies": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@mswjs/cookies/-/cookies-0.2.2.tgz", + "integrity": "sha512-mlN83YSrcFgk7Dm1Mys40DLssI1KdJji2CMKN8eOlBqsTADYzj2+jWzsANsUTFbxDMWPD5e9bfA1RGqBpS3O1g==", + "dev": true, + "dependencies": { + "@types/set-cookie-parser": "^2.4.0", + "set-cookie-parser": "^2.4.6" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@mswjs/interceptors": { + "version": "0.17.9", + "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.17.9.tgz", + "integrity": "sha512-4LVGt03RobMH/7ZrbHqRxQrS9cc2uh+iNKSj8UWr8M26A2i793ju+csaB5zaqYltqJmA2jUq4VeYfKmVqvsXQg==", + "dev": true, + "dependencies": { + "@open-draft/until": "^1.0.3", + "@types/debug": "^4.1.7", + "@xmldom/xmldom": "^0.8.3", + "debug": "^4.3.3", + "headers-polyfill": "^3.1.0", + "outvariant": "^1.2.1", + "strict-event-emitter": "^0.2.4", + "web-encoding": "^1.1.5" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@mswjs/interceptors/node_modules/strict-event-emitter": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.8.tgz", + "integrity": "sha512-KDf/ujU8Zud3YaLtMCcTI4xkZlZVIYxTLr+XIULexP+77EEVWixeXroLUXQXiVtH4XH2W7jr/3PT1v3zBuvc3A==", + "dev": true, + "dependencies": { + "events": "^3.3.0" + } + }, "node_modules/@nicolo-ribaudo/semver-v6": { "version": "6.3.3", "dev": true, @@ -3127,6 +3169,12 @@ "node": ">= 8" } }, + "node_modules/@open-draft/until": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@open-draft/until/-/until-1.0.3.tgz", + "integrity": "sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q==", + "dev": true + }, "node_modules/@patternfly/patternfly": { "version": "5.0.2", "license": "MIT" @@ -3844,6 +3892,12 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, "node_modules/@types/d3-array": { "version": "3.0.5", "license": "MIT" @@ -4027,6 +4081,12 @@ "pretty-format": "^27.0.0" } }, + "node_modules/@types/js-levenshtein": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz", + "integrity": "sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g==", + "dev": true + }, "node_modules/@types/js-yaml": { "version": "4.0.5", "dev": true, @@ -4209,6 +4269,15 @@ "@types/node": "*" } }, + "node_modules/@types/set-cookie-parser": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.3.tgz", + "integrity": "sha512-7QhnH7bi+6KAhBB+Auejz1uV9DHiopZqu7LfR/5gZZTkejJV5nYeZZpgfFoE0N8aDsXuiYpfKyfyMatCwQhyTQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/sockjs": { "version": "0.3.33", "dev": true, @@ -4447,6 +4516,15 @@ } } }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "dev": true, @@ -4457,6 +4535,13 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/@zxing/text-encoding": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", + "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", + "dev": true, + "optional": true + }, "node_modules/abab": { "version": "2.0.6", "dev": true, @@ -4957,6 +5042,60 @@ "node": ">=8" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/body-parser": { "version": "1.20.1", "license": "MIT", @@ -5100,6 +5239,30 @@ "node": ">= 0.4.0" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "dev": true, @@ -5240,6 +5403,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, "node_modules/chokidar": { "version": "3.5.3", "dev": true, @@ -5315,6 +5484,39 @@ "node": ">= 10.0" } }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", + "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/cliui": { "version": "8.0.1", "dev": true, @@ -6314,6 +6516,18 @@ "node": ">= 10" } }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "dev": true, @@ -7097,6 +7311,20 @@ "version": "3.0.2", "license": "MIT" }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fancy-log": { "version": "1.3.3", "dev": true, @@ -7228,6 +7456,30 @@ "bser": "2.1.1" } }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "dev": true, @@ -7731,6 +7983,15 @@ "dev": true, "license": "MIT" }, + "node_modules/graphql": { + "version": "16.7.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.7.1.tgz", + "integrity": "sha512-DRYR9tf+UGU0KOsMcKAlXeFfX89UiiIZ0dRU3mR0yJfu6OjZqUcp68NnFLnqQU5RexygFoDy1EW+ccOYcPfmHg==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, "node_modules/gulp-util": { "version": "3.0.8", "dev": true, @@ -7988,6 +8249,12 @@ "he": "bin/he" } }, + "node_modules/headers-polyfill": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-3.1.2.tgz", + "integrity": "sha512-tWCK4biJ6hcLqTviLXVR9DTRfYGQMXEIUj3gwJ2rZ5wO/at3XtkI4g8mCvFdUF9l1KMBNCfmNAdnahm1cgavQA==", + "dev": true + }, "node_modules/history": { "version": "4.10.1", "license": "MIT", @@ -8393,6 +8660,26 @@ "postcss": "^8.1.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.2.4", "dev": true, @@ -8467,6 +8754,46 @@ "version": "0.1.1", "license": "MIT" }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/internal-slot": { "version": "1.0.5", "dev": true, @@ -8681,6 +9008,21 @@ "node": ">=6" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "license": "MIT", @@ -8691,6 +9033,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-map": { "version": "2.0.2", "dev": true, @@ -8704,6 +9055,12 @@ "dev": true, "license": "MIT" }, + "node_modules/is-node-process": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz", + "integrity": "sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==", + "dev": true + }, "node_modules/is-number": { "version": "7.0.0", "license": "MIT", @@ -8864,6 +9221,18 @@ "license": "MIT", "peer": true }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-weakmap": { "version": "2.0.1", "dev": true, @@ -9938,6 +10307,15 @@ "node": ">= 10.13.0" } }, + "node_modules/js-levenshtein": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", + "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/js-sha256": { "version": "0.9.0", "license": "MIT" @@ -10288,6 +10666,22 @@ "dev": true, "license": "MIT" }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/loose-envify": { "version": "1.4.0", "license": "MIT", @@ -11021,6 +11415,107 @@ "version": "2.1.2", "license": "MIT" }, + "node_modules/msw": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/msw/-/msw-1.2.3.tgz", + "integrity": "sha512-Fqy/TaLKR32x4IkMwudJHJysBzVM/v/lSoMPS9f3QaHLOmb3xHN9YurSUnRt+2eEvNXLjVPij1wMBQtLmTbKsg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@mswjs/cookies": "^0.2.2", + "@mswjs/interceptors": "^0.17.5", + "@open-draft/until": "^1.0.3", + "@types/cookie": "^0.4.1", + "@types/js-levenshtein": "^1.1.1", + "chalk": "4.1.1", + "chokidar": "^3.4.2", + "cookie": "^0.4.2", + "graphql": "^15.0.0 || ^16.0.0", + "headers-polyfill": "^3.1.2", + "inquirer": "^8.2.0", + "is-node-process": "^1.2.0", + "js-levenshtein": "^1.1.6", + "node-fetch": "^2.6.7", + "outvariant": "^1.4.0", + "path-to-regexp": "^6.2.0", + "strict-event-emitter": "^0.4.3", + "type-fest": "^2.19.0", + "yargs": "^17.3.1" + }, + "bin": { + "msw": "cli/index.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mswjs" + }, + "peerDependencies": { + "typescript": ">= 4.4.x <= 5.1.x" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/msw/node_modules/chalk": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/msw/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/msw/node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", + "dev": true + }, + "node_modules/msw/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/msw/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/multicast-dns": { "version": "7.2.5", "dev": true, @@ -11064,6 +11559,12 @@ "duplexer2": "0.0.2" } }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, "node_modules/nanoclone": { "version": "0.2.1", "license": "MIT" @@ -11353,6 +11854,44 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/outvariant": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/outvariant/-/outvariant-1.4.0.tgz", + "integrity": "sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==", + "dev": true + }, "node_modules/p-finally": { "version": "1.0.0", "license": "MIT", @@ -12924,6 +13463,19 @@ "node": ">=10" } }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/retry": { "version": "0.13.1", "dev": true, @@ -13032,6 +13584,15 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "dev": true, @@ -13372,6 +13933,12 @@ "node": ">= 0.8.0" } }, + "node_modules/set-cookie-parser": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==", + "dev": true + }, "node_modules/set-immediate-shim": { "version": "1.0.1", "dev": true, @@ -13714,6 +14281,12 @@ "node": ">= 0.4" } }, + "node_modules/strict-event-emitter": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.4.6.tgz", + "integrity": "sha512-12KWeb+wixJohmnwNFerbyiBrAlq5qJLwIt38etRtKtmmHyDSoGlIqFE9wx+4IwG0aDjI7GV8tc8ZccjWZZtTg==", + "dev": true + }, "node_modules/string_decoder": { "version": "0.10.31", "dev": true, @@ -14104,6 +14677,12 @@ "license": "MIT", "peer": true }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, "node_modules/through2": { "version": "2.0.5", "dev": true, @@ -14165,6 +14744,18 @@ "version": "1.6.0", "license": "MIT" }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "dev": true, @@ -14650,6 +15241,19 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "dev": true, @@ -15155,6 +15759,27 @@ "minimalistic-assert": "^1.0.0" } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-encoding": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", + "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", + "dev": true, + "dependencies": { + "util": "^0.12.3" + }, + "optionalDependencies": { + "@zxing/text-encoding": "0.9.0" + } + }, "node_modules/web-vitals": { "version": "0.2.4", "license": "Apache-2.0"