diff --git a/admin/.eslintrc.json b/admin/.eslintrc.json index 35579b7..e2acf76 100644 --- a/admin/.eslintrc.json +++ b/admin/.eslintrc.json @@ -1,6 +1,18 @@ { "extends": ["next/core-web-vitals", "prettier"], "rules": { - "@next/next/no-css-tags": "off" - } + "@next/next/no-css-tags": "off", + "@typescript-eslint/no-unused-vars": "off", + "unused-imports/no-unused-imports": "error", + "unused-imports/no-unused-vars": [ + "warn", + { + "vars": "all", + "varsIgnorePattern": "^_", + "args": "after-used", + "argsIgnorePattern": "^_" + } + ] + }, + "plugins": ["unused-imports", "prettier"] } diff --git a/admin/gqlcodegen.yml b/admin/gqlcodegen.yml new file mode 100644 index 0000000..dbba8a0 --- /dev/null +++ b/admin/gqlcodegen.yml @@ -0,0 +1,9 @@ +overwrite: true +schema: "../pkg/api/schema.graphql" +documents: "src/**/*.graphql" +generates: + src/generated/graphql.tsx: + plugins: + - "typescript" + - "typescript-operations" + - "typescript-react-apollo" diff --git a/admin/package.json b/admin/package.json index 318a0b1..4c95497 100644 --- a/admin/package.json +++ b/admin/package.json @@ -7,7 +7,8 @@ "build": "next build", "start": "next start", "lint": "next lint", - "export": "next build && next export -o dist" + "export": "next build && next export -o dist", + "generate": "graphql-codegen --config gqlcodegen.yml" }, "dependencies": { "@apollo/client": "^3.2.0", @@ -18,6 +19,7 @@ "@mui/icons-material": "^5.3.1", "@mui/lab": "^5.0.0-alpha.66", "@mui/material": "^5.3.1", + "allotment": "^1.9.0", "deepmerge": "^4.2.2", "graphql": "^16.2.0", "lodash": "^4.17.21", @@ -29,13 +31,21 @@ }, "devDependencies": { "@babel/core": "^7.0.0", + "@graphql-codegen/cli": "2.6.1", + "@graphql-codegen/introspection": "2.1.1", + "@graphql-codegen/typescript": "2.4.3", + "@graphql-codegen/typescript-operations": "2.3.0", + "@graphql-codegen/typescript-react-apollo": "3.2.6", "@types/lodash": "^4.14.178", "@types/node": "^17.0.12", "@types/react": "^17.0.38", + "@typescript-eslint/eslint-plugin": "^5.12.0", + "@typescript-eslint/parser": "^5.12.0", "eslint": "^8.7.0", "eslint-config-next": "12.0.8", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-unused-imports": "^2.0.0", "prettier": "^2.1.2", "typescript": "^4.0.3", "webpack": "^5.67.0" diff --git a/admin/src/components/Layout.tsx b/admin/src/components/Layout.tsx index 22ce5b8..0c6302c 100644 --- a/admin/src/components/Layout.tsx +++ b/admin/src/components/Layout.tsx @@ -151,7 +151,7 @@ export function Layout({ title, page, children }: Props): JSX.Element { }); return ( - + - - + {children} diff --git a/admin/src/components/CenteredPaper.tsx b/admin/src/components/common/CenteredPaper.tsx similarity index 100% rename from admin/src/components/CenteredPaper.tsx rename to admin/src/components/common/CenteredPaper.tsx diff --git a/admin/src/components/reqlog/Editor.tsx b/admin/src/components/common/Editor.tsx similarity index 59% rename from admin/src/components/reqlog/Editor.tsx rename to admin/src/components/common/Editor.tsx index fd090e3..05bcf51 100644 --- a/admin/src/components/reqlog/Editor.tsx +++ b/admin/src/components/common/Editor.tsx @@ -1,7 +1,6 @@ -import MonacoEditor from "@monaco-editor/react"; -import monaco from "monaco-editor/esm/vs/editor/editor.api"; +import MonacoEditor, { EditorProps } from "@monaco-editor/react"; -const monacoOptions: monaco.editor.IEditorOptions = { +const defaultMonacoOptions: EditorProps["options"] = { readOnly: true, wordWrap: "on", minimap: { @@ -12,8 +11,9 @@ const monacoOptions: monaco.editor.IEditorOptions = { type language = "html" | "typescript" | "json"; function languageForContentType(contentType?: string): language | undefined { - switch (contentType) { + switch (contentType?.toLowerCase()) { case "text/html": + case "text/html; charset=utf-8": return "html"; case "application/json": case "application/json; charset=utf-8": @@ -29,16 +29,19 @@ function languageForContentType(contentType?: string): language | undefined { interface Props { content: string; contentType?: string; + monacoOptions?: EditorProps["options"]; + onChange?: EditorProps["onChange"]; } -function Editor({ content, contentType }: Props): JSX.Element { +function Editor({ content, contentType, monacoOptions, onChange }: Props): JSX.Element { + console.log(content); return ( ); } diff --git a/admin/src/components/reqlog/HttpStatusCode.tsx b/admin/src/components/common/HttpStatusIcon.tsx similarity index 100% rename from admin/src/components/reqlog/HttpStatusCode.tsx rename to admin/src/components/common/HttpStatusIcon.tsx diff --git a/admin/src/components/common/ResponseStatus.tsx b/admin/src/components/common/ResponseStatus.tsx new file mode 100644 index 0000000..c56ada9 --- /dev/null +++ b/admin/src/components/common/ResponseStatus.tsx @@ -0,0 +1,37 @@ +import { Typography } from "@mui/material"; + +import HttpStatusIcon from "./HttpStatusIcon"; +import { HttpProtocol } from "../../generated/graphql"; + +type ResponseStatusProps = { + proto: HttpProtocol; + statusCode: number; + statusReason: string; +}; + +function mapProto(proto: HttpProtocol): string { + switch (proto) { + case HttpProtocol.Http1: + return "HTTP/1.1"; + case HttpProtocol.Http2: + return "HTTP/2.0"; + default: + return proto; + } +} + +function ResponseStatus({ proto, statusCode, statusReason }: ResponseStatusProps): JSX.Element { + return ( + + {" "} + + + {mapProto(proto)} + + {" "} + {statusCode} {statusReason} + + ); +} + +export default ResponseStatus; diff --git a/admin/src/components/common/useContextMenu.tsx b/admin/src/components/common/useContextMenu.tsx new file mode 100644 index 0000000..49f5787 --- /dev/null +++ b/admin/src/components/common/useContextMenu.tsx @@ -0,0 +1,47 @@ +import * as React from "react"; +import { Menu } from "@mui/material"; + +export interface ContextMenuProps { + children?: React.ReactNode; +} + +function useContextMenu(): [(props: ContextMenuProps) => JSX.Element, (e: React.MouseEvent) => void, () => void] { + const [contextMenu, setContextMenu] = React.useState<{ + mouseX: number; + mouseY: number; + } | null>(null); + + const handleContextMenu = (event: React.MouseEvent) => { + event.preventDefault(); + setContextMenu( + contextMenu === null + ? { + mouseX: event.clientX - 2, + mouseY: event.clientY - 4, + } + : // repeated contextmenu when it is already open closes it with Chrome 84 on Ubuntu + // Other native context menus might behave different. + // With this behavior we prevent contextmenu from the backdrop to re-locale existing context menus. + null + ); + }; + + const handleClose = () => { + setContextMenu(null); + }; + + const menu = ({ children }: ContextMenuProps): JSX.Element => ( + + {children} + + ); + + return [menu, handleContextMenu, handleClose]; +} + +export default useContextMenu; diff --git a/admin/src/components/projects/ProjectList.tsx b/admin/src/components/projects/ProjectList.tsx index dbd5513..e3a6987 100644 --- a/admin/src/components/projects/ProjectList.tsx +++ b/admin/src/components/projects/ProjectList.tsx @@ -68,7 +68,13 @@ const DELETE_PROJECT = gql` function ProjectList(): JSX.Element { const theme = useTheme(); - const { loading: projLoading, error: projErr, data: projData } = useQuery<{ projects: Project[] }>(PROJECTS); + const { + loading: projLoading, + error: projErr, + data: projData, + } = useQuery<{ projects: Project[] }>(PROJECTS, { + fetchPolicy: "network-only", + }); const [openProject, { error: openProjErr, loading: openProjLoading }] = useMutation<{ openProject: Project }>( OPEN_PROJECT, { @@ -114,9 +120,12 @@ function ProjectList(): JSX.Element { }, } ); - const [closeProject, { error: closeProjErr }] = useMutation(CLOSE_PROJECT, { + const [closeProject, { error: closeProjErr, client }] = useMutation(CLOSE_PROJECT, { errorPolicy: "all", onError: () => {}, + onCompleted() { + client.resetStore(); + }, update(cache) { cache.modify({ fields: { diff --git a/admin/src/components/reqlog/LogsOverview.tsx b/admin/src/components/reqlog/LogsOverview.tsx index 0e29405..c6383e7 100644 --- a/admin/src/components/reqlog/LogsOverview.tsx +++ b/admin/src/components/reqlog/LogsOverview.tsx @@ -5,7 +5,7 @@ import Alert from "@mui/lab/Alert"; import RequestList from "./RequestList"; import LogDetail from "./LogDetail"; -import CenteredPaper from "../CenteredPaper"; +import CenteredPaper from "../common/CenteredPaper"; import { useHttpRequestLogs } from "./hooks/useHttpRequestLogs"; function LogsOverview(): JSX.Element { diff --git a/admin/src/components/reqlog/RequestDetail.tsx b/admin/src/components/reqlog/RequestDetail.tsx index 6a8d36d..01b177d 100644 --- a/admin/src/components/reqlog/RequestDetail.tsx +++ b/admin/src/components/reqlog/RequestDetail.tsx @@ -2,7 +2,7 @@ import React from "react"; import { Typography, Box, Divider } from "@mui/material"; import HttpHeadersTable from "./HttpHeadersTable"; -import Editor from "./Editor"; +import Editor from "../common/Editor"; interface Props { request: { diff --git a/admin/src/components/reqlog/RequestList.tsx b/admin/src/components/reqlog/RequestList.tsx index c72c760..e372608 100644 --- a/admin/src/components/reqlog/RequestList.tsx +++ b/admin/src/components/reqlog/RequestList.tsx @@ -9,11 +9,18 @@ import { Typography, Box, useTheme, + MenuItem, + Snackbar, + Alert, + Link, } from "@mui/material"; -import HttpStatusIcon from "./HttpStatusCode"; -import CenteredPaper from "../CenteredPaper"; +import HttpStatusIcon from "../common/HttpStatusIcon"; +import CenteredPaper from "../common/CenteredPaper"; import { RequestLog } from "../../lib/requestLogs"; +import useContextMenu from "../common/useContextMenu"; +import React, { useState } from "react"; +import { useCreateSenderRequestFromHttpRequestLogMutation } from "../../generated/graphql"; interface Props { logs: RequestLog[]; @@ -45,69 +52,117 @@ interface RequestListTableProps { function RequestListTable({ logs, selectedReqLogId, onLogClick }: RequestListTableProps): JSX.Element { const theme = useTheme(); + const [createSenderReqFromLog] = useCreateSenderRequestFromHttpRequestLogMutation({}); + + const [copyToSenderId, setCopyToSenderId] = useState(""); + const [Menu, handleContextMenu, handleContextMenuClose] = useContextMenu(); + + const handleCopyToSenderClick = () => { + createSenderReqFromLog({ + variables: { + id: copyToSenderId, + }, + onCompleted({ createSenderRequestFromHttpRequestLog }) { + const { id } = createSenderRequestFromHttpRequestLog; + setNewSenderReqId(id); + setCopiedReqNotifOpen(true); + }, + }); + handleContextMenuClose(); + }; + + const [newSenderReqId, setNewSenderReqId] = React.useState(""); + const [copiedReqNotifOpen, setCopiedReqNotifOpen] = React.useState(false); + const handleCloseCopiedNotif = (_: Event | React.SyntheticEvent, reason?: string) => { + if (reason === "clickaway") { + return; + } + setCopiedReqNotifOpen(false); + }; + return ( - - - - - Method - Origin - Path - Status - - - - {logs.map(({ id, method, url, response }) => { - const { origin, pathname, search, hash } = new URL(url); +
+ + Copy request to Sender + + + + Request was copied. Edit in Sender. + + - const cellStyle = { - whiteSpace: "nowrap", - overflow: "hidden", - textOverflow: "ellipsis", - } as any; + +
+ + + Method + Origin + Path + Status + + + + {logs.map(({ id, method, url, response }) => { + const { origin, pathname, search, hash } = new URL(url); - return ( - onLogClick(id)} - > - - {method} - - {origin} - - {decodeURIComponent(pathname + search + hash)} - - - {response && ( -
- {" "} - - {response.statusCode} {response.statusReason} - -
- )} -
-
- ); - })} -
-
-
+ const cellStyle = { + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + } as any; + + return ( + onLogClick(id)} + onContextMenu={(e) => { + setCopyToSenderId(id); + handleContextMenu(e); + }} + > + + {method} + + {origin} + + {decodeURIComponent(pathname + search + hash)} + + + {response && ( +
+ {" "} + + {response.statusCode} {response.statusReason} + +
+ )} +
+
+ ); + })} + + + + ); } diff --git a/admin/src/components/reqlog/ResponseDetail.tsx b/admin/src/components/reqlog/ResponseDetail.tsx index 7b7238d..092f6ed 100644 --- a/admin/src/components/reqlog/ResponseDetail.tsx +++ b/admin/src/components/reqlog/ResponseDetail.tsx @@ -1,7 +1,7 @@ import { Typography, Box, Divider } from "@mui/material"; -import HttpStatusIcon from "./HttpStatusCode"; -import Editor from "./Editor"; +import HttpStatusIcon from "../common/HttpStatusIcon"; +import Editor from "../common/Editor"; import HttpHeadersTable from "./HttpHeadersTable"; interface Props { diff --git a/admin/src/components/reqlog/hooks/useCreateSenderRequest.ts b/admin/src/components/reqlog/hooks/useCreateSenderRequest.ts new file mode 100644 index 0000000..aa81efe --- /dev/null +++ b/admin/src/components/reqlog/hooks/useCreateSenderRequest.ts @@ -0,0 +1,13 @@ +import { gql, useMutation } from "@apollo/client"; + +const CREATE_SENDER_REQUEST = gql` + mutation CreateSenderRequest($request: SenderRequestInput!) { + createSenderRequest(request: $request) { + id + } + } +`; + +export default function useCreateSenderRequest() { + return useMutation(CREATE_SENDER_REQUEST); +} diff --git a/admin/src/components/scope/RuleListItem.tsx b/admin/src/components/scope/RuleListItem.tsx index e5d0e87..630f111 100644 --- a/admin/src/components/scope/RuleListItem.tsx +++ b/admin/src/components/scope/RuleListItem.tsx @@ -1,4 +1,4 @@ -import { gql, useApolloClient, useMutation, useQuery } from "@apollo/client"; +import { gql, useApolloClient, useMutation } from "@apollo/client"; import { Avatar, Chip, diff --git a/admin/src/components/sender/EditRequest.tsx b/admin/src/components/sender/EditRequest.tsx new file mode 100644 index 0000000..ca0e325 --- /dev/null +++ b/admin/src/components/sender/EditRequest.tsx @@ -0,0 +1,398 @@ +import { + Alert, + Box, + BoxProps, + Button, + FormControl, + InputLabel, + MenuItem, + Select, + TextField, + Typography, +} from "@mui/material"; +import { ComponentType, FormEventHandler, useEffect, useRef, useState } from "react"; +import { AllotmentProps, PaneProps } from "allotment/dist/types/src/allotment"; + +import { KeyValuePair, sortKeyValuePairs } from "./KeyValuePair"; +import { + GetSenderRequestQuery, + HttpProtocol, + useCreateOrUpdateSenderRequestMutation, + useGetSenderRequestQuery, + useSendRequestMutation, +} from "../../generated/graphql"; +import EditRequestTabs from "./EditRequestTabs"; +import Response from "./Response"; + +import "allotment/dist/style.css"; +import { useRouter } from "next/router"; + +enum HttpMethod { + Get = "GET", + Post = "POST", + Put = "PUT", + Patch = "PATCH", + Delete = "DELETE", + Head = "HEAD", + Options = "OPTIONS", + Connect = "CONNECT", + Trace = "TRACE", +} + +enum HttpProto { + Http1 = "HTTP/1.1", + Http2 = "HTTP/2.0", +} + +const httpProtoMap = new Map([ + [HttpProto.Http1, HttpProtocol.Http1], + [HttpProto.Http2, HttpProtocol.Http2], +]); + +function updateKeyPairItem(key: string, value: string, idx: number, items: any[]): any[] { + const updated = [...items]; + updated[idx] = { key, value }; + + // Append an empty key-value pair if the last item in the array isn't blank + // anymore. + if (items.length - 1 === idx && items[idx].key === "" && items[idx].value === "") { + updated.push({ key: "", value: "" }); + } + + return updated; +} + +function updateURLQueryParams(url: string, queryParams: KeyValuePair[]) { + // Note: We don't use the `URL` interface, because we're potentially dealing + // with malformed/incorrect URLs, which would yield TypeErrors when constructed + // via `URL`. + let newURL = url; + + const questionMarkIndex = url.indexOf("?"); + if (questionMarkIndex !== -1) { + newURL = newURL.slice(0, questionMarkIndex); + } + + const searchParams = new URLSearchParams(); + for (const { key, value } of queryParams.filter(({ key }) => key !== "")) { + searchParams.append(key, value); + } + + const rawQueryParams = decodeURI(searchParams.toString()); + + if (rawQueryParams == "") { + return newURL; + } + + return newURL + "?" + rawQueryParams; +} + +function queryParamsFromURL(url: string): KeyValuePair[] { + const questionMarkIndex = url.indexOf("?"); + if (questionMarkIndex === -1) { + return []; + } + + const queryParams: KeyValuePair[] = []; + + const searchParams = new URLSearchParams(url.slice(questionMarkIndex + 1)); + for (let [key, value] of searchParams) { + queryParams.push({ key, value }); + } + + return queryParams; +} + +function EditRequest(): JSX.Element { + const router = useRouter(); + const reqId = router.query.id as string | undefined; + + const [method, setMethod] = useState(HttpMethod.Get); + const [url, setURL] = useState(""); + const [proto, setProto] = useState(HttpProto.Http2); + const [queryParams, setQueryParams] = useState([{ key: "", value: "" }]); + const [headers, setHeaders] = useState([{ key: "", value: "" }]); + const [body, setBody] = useState(""); + + const handleQueryParamChange = (key: string, value: string, idx: number) => { + setQueryParams((prev) => { + const updated = updateKeyPairItem(key, value, idx, prev); + setURL((prev) => updateURLQueryParams(prev, updated)); + return updated; + }); + }; + const handleQueryParamDelete = (idx: number) => { + setQueryParams((prev) => { + const updated = prev.slice(0, idx).concat(prev.slice(idx + 1, prev.length)); + setURL((prev) => updateURLQueryParams(prev, updated)); + return updated; + }); + }; + + const handleHeaderChange = (key: string, value: string, idx: number) => { + setHeaders((prev) => updateKeyPairItem(key, value, idx, prev)); + }; + const handleHeaderDelete = (idx: number) => { + setHeaders((prev) => prev.slice(0, idx).concat(prev.slice(idx + 1, prev.length))); + }; + + const handleURLChange = (url: string) => { + setURL(url); + + const questionMarkIndex = url.indexOf("?"); + if (questionMarkIndex === -1) { + setQueryParams([{ key: "", value: "" }]); + return; + } + + const newQueryParams = queryParamsFromURL(url); + // Push empty row. + newQueryParams.push({ key: "", value: "" }); + setQueryParams(newQueryParams); + }; + + const [response, setResponse] = useState["response"]>(null); + const getReqResult = useGetSenderRequestQuery({ + variables: { id: reqId as string }, + skip: reqId === undefined, + onCompleted: ({ senderRequest }) => { + if (!senderRequest) { + return; + } + + setURL(senderRequest.url); + setMethod(senderRequest.method); + setBody(senderRequest.body || ""); + + const newQueryParams = queryParamsFromURL(senderRequest.url); + // Push empty row. + newQueryParams.push({ key: "", value: "" }); + setQueryParams(newQueryParams); + + const newHeaders = sortKeyValuePairs(senderRequest.headers || []); + setHeaders([...newHeaders.map(({ key, value }) => ({ key, value })), { key: "", value: "" }]); + console.log(senderRequest.response); + setResponse(senderRequest.response); + }, + }); + + const [createOrUpdateRequest, createResult] = useCreateOrUpdateSenderRequestMutation(); + const [sendRequest, sendResult] = useSendRequestMutation(); + + const createOrUpdateRequestAndSend = () => { + const senderReq = getReqResult?.data?.senderRequest; + createOrUpdateRequest({ + variables: { + request: { + // Update existing sender request if it was cloned from a request log + // and it doesn't have a response body yet (e.g. not sent yet). + ...(senderReq && senderReq.sourceRequestLogID && !senderReq.response && { id: senderReq.id }), + url, + method, + proto: httpProtoMap.get(proto), + headers: headers.filter((kv) => kv.key !== ""), + body: body || undefined, + }, + }, + onCompleted: ({ createOrUpdateSenderRequest }) => { + const { id } = createOrUpdateSenderRequest; + sendRequestAndPushRoute(id); + }, + }); + }; + + const sendRequestAndPushRoute = (id: string) => { + sendRequest({ + errorPolicy: "all", + onCompleted: () => { + router.push(`/sender?id=${id}`); + }, + variables: { + id, + }, + }); + }; + + const handleFormSubmit: FormEventHandler = (e) => { + e.preventDefault(); + createOrUpdateRequestAndSend(); + }; + + const isMountedRef = useRef(false); + const [Allotment, setAllotment] = useState< + (ComponentType & { Pane: ComponentType }) | null + >(null); + useEffect(() => { + isMountedRef.current = true; + import("allotment") + .then((mod) => { + if (!isMountedRef.current) { + return; + } + setAllotment(mod.Allotment); + }) + .catch((err) => console.error(err, `could not import allotment ${err.message}`)); + return () => { + isMountedRef.current = false; + }; + }, []); + if (!Allotment) { + return
Loading...
; + } + + return ( + + + + + + + {createResult.error && ( + + {createResult.error.message} + + )} + {sendResult.error && ( + + {sendResult.error.message} + + )} + + + + + + + + Request + + + + + + + + + + + + + ); +} + +interface UrlBarProps extends BoxProps { + method: HttpMethod; + onMethodChange: (method: HttpMethod) => void; + url: string; + onUrlChange: (url: string) => void; + proto: HttpProto; + onProtoChange: (proto: HttpProto) => void; +} + +function UrlBar(props: UrlBarProps) { + const { method, onMethodChange, url, onUrlChange, proto, onProtoChange, ...other } = props; + + return ( + + + Method + + + onUrlChange(e.target.value)} + required + variant="outlined" + InputLabelProps={{ + shrink: true, + }} + InputProps={{ + sx: { + ".MuiOutlinedInput-notchedOutline": { + borderRadius: 0, + }, + }, + }} + sx={{ flexGrow: 1 }} + /> + + Protocol + + + + ); +} + +export default EditRequest; diff --git a/admin/src/components/sender/EditRequestTabs.tsx b/admin/src/components/sender/EditRequestTabs.tsx new file mode 100644 index 0000000..9f06e50 --- /dev/null +++ b/admin/src/components/sender/EditRequestTabs.tsx @@ -0,0 +1,91 @@ +import { TabContext, TabList, TabPanel } from "@mui/lab"; +import { Box, Tab } from "@mui/material"; +import { useState } from "react"; +import Editor from "../common/Editor"; + +import KeyValuePairTable, { KeyValuePair, KeyValuePairTableProps } from "./KeyValuePair"; + +enum TabValue { + QueryParams = "queryParams", + Headers = "headers", + Body = "body", +} + +export type EditRequestTabsProps = { + queryParams: KeyValuePair[]; + headers: KeyValuePair[]; + onQueryParamChange: KeyValuePairTableProps["onChange"]; + onQueryParamDelete: KeyValuePairTableProps["onDelete"]; + onHeaderChange: KeyValuePairTableProps["onChange"]; + onHeaderDelete: KeyValuePairTableProps["onDelete"]; + body: string; + onBodyChange: (value: string) => void; +}; + +function EditRequestTabs(props: EditRequestTabsProps): JSX.Element { + const { + queryParams, + onQueryParamChange, + onQueryParamDelete, + headers, + onHeaderChange, + onHeaderDelete, + body, + onBodyChange, + } = props; + const [tabValue, setTabValue] = useState(TabValue.QueryParams); + + const tabSx = { + textTransform: "none", + }; + + return ( + + + + setTabValue(value)}> + + + 1 ? "s" : "") + ")" : "")} + sx={tabSx} + /> + + + + + + + + + + + + + + + { + onBodyChange(value || ""); + }} + monacoOptions={{ readOnly: false }} + contentType={headers.find(({ key }) => key.toLowerCase() === "content-type")?.value} + /> + + + + + ); +} + +export default EditRequestTabs; diff --git a/admin/src/components/sender/History.tsx b/admin/src/components/sender/History.tsx new file mode 100644 index 0000000..596db20 --- /dev/null +++ b/admin/src/components/sender/History.tsx @@ -0,0 +1,93 @@ +import { TableContainer, Table, TableHead, TableRow, TableCell, Typography, Box, TableBody } from "@mui/material"; +import { useRouter } from "next/router"; +import { useGetSenderRequestsQuery } from "../../generated/graphql"; +import CenteredPaper from "../common/CenteredPaper"; +import HttpStatusIcon from "../common/HttpStatusIcon"; + +function History(): JSX.Element { + const { data, loading } = useGetSenderRequestsQuery({ + pollInterval: 1000, + }); + + const router = useRouter(); + const activeId = router.query.id as string | undefined; + + const handleRowClick = (id: string) => { + router.push(`/sender?id=${id}`); + }; + + return ( + + {!loading && data?.senderRequests && data?.senderRequests.length > 0 && ( + + + + + Method + Origin + Path + Status + + + + {data?.senderRequests && + data.senderRequests.map(({ id, method, url, response }) => { + const { origin, pathname, search, hash } = new URL(url); + + const cellStyle = { + whiteSpace: "nowrap", + overflow: "hidden", + textOverflow: "ellipsis", + } as any; + + return ( + handleRowClick(id)} + > + + {method} + + {origin} + + {decodeURIComponent(pathname + search + hash)} + + + {response && ( +
+ {" "} + + {response.statusCode} {response.statusReason} + +
+ )} +
+
+ ); + })} +
+
+
+ )} + + {!loading && data?.senderRequests.length === 0 && ( + + No requests created yet. + + )} + +
+ ); +} + +export default History; diff --git a/admin/src/components/sender/KeyValuePair.tsx b/admin/src/components/sender/KeyValuePair.tsx new file mode 100644 index 0000000..c159adc --- /dev/null +++ b/admin/src/components/sender/KeyValuePair.tsx @@ -0,0 +1,130 @@ +import { IconButton, InputBase, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material"; +import ClearIcon from "@mui/icons-material/Clear"; + +export type KeyValuePair = { + key: string; + value: string; +}; + +export type KeyValuePairTableProps = { + items: KeyValuePair[]; + onChange?: (key: string, value: string, index: number) => void; + onDelete?: (index: number) => void; +}; + +export function KeyValuePairTable({ items, onChange, onDelete }: KeyValuePairTableProps): JSX.Element { + const inputSx = { + fontSize: "0.875rem", + "&.MuiInputBase-root input": { + p: 0, + }, + }; + + return ( + + + + + Key + Value + {onDelete && } + + + + {items.map(({ key, value }, idx) => ( + + + {!onChange && {key}} + {onChange && ( + { + onChange && onChange(e.target.value, value, idx); + }} + sx={inputSx} + /> + )} + + + {!onChange && value} + {onChange && ( + { + onChange && onChange(key, e.target.value, idx); + }} + sx={inputSx} + /> + )} + + {onDelete && ( + +
+ { + onDelete && onDelete(idx); + }} + sx={{ + visibility: onDelete === undefined || items.length === idx + 1 ? "hidden" : "inherit", + }} + > + + +
+
+ )} +
+ ))} +
+
+
+ ); +} + +export function sortKeyValuePairs(items: KeyValuePair[]): KeyValuePair[] { + const sorted = [...items]; + + sorted.sort((a, b) => { + if (a.key < b.key) { + return -1; + } + if (a.key > b.key) { + return 1; + } + return 0; + }); + + return sorted; +} + +export default KeyValuePairTable; diff --git a/admin/src/components/sender/Response.tsx b/admin/src/components/sender/Response.tsx new file mode 100644 index 0000000..363d4b7 --- /dev/null +++ b/admin/src/components/sender/Response.tsx @@ -0,0 +1,40 @@ +import { Box, Typography } from "@mui/material"; + +import { sortKeyValuePairs } from "./KeyValuePair"; +import ResponseTabs from "./ResponseTabs"; +import ResponseStatus from "../common/ResponseStatus"; +import { HttpResponseLog } from "../../generated/graphql"; + +export type ResponseProps = { + response?: HttpResponseLog | null; +}; + +function Response({ response }: ResponseProps): JSX.Element { + return ( + +
+ + + Response + + {response && ( + + + + )} + +
+ +
+ ); +} + +export default Response; diff --git a/admin/src/components/sender/ResponseTabs.tsx b/admin/src/components/sender/ResponseTabs.tsx new file mode 100644 index 0000000..8c085e5 --- /dev/null +++ b/admin/src/components/sender/ResponseTabs.tsx @@ -0,0 +1,69 @@ +import { TabContext, TabList, TabPanel } from "@mui/lab"; +import { Box, Tab, Typography } from "@mui/material"; +import { useState } from "react"; +import { HttpResponseLog } from "../../generated/graphql"; +import CenteredPaper from "../common/CenteredPaper"; +import Editor from "../common/Editor"; + +import KeyValuePairTable from "./KeyValuePair"; + +export type ResponseTabsProps = { + headers: HttpResponseLog["headers"]; + body: HttpResponseLog["body"]; + hasResponse: boolean; +}; + +enum TabValue { + Body = "body", + Headers = "headers", +} + +const reqNotSent = ( + + Response not received yet. + +); + +function ResponseTabs(props: ResponseTabsProps): JSX.Element { + const { headers, body, hasResponse } = props; + const [tabValue, setTabValue] = useState(TabValue.Body); + + const contentType = headers.find((header) => header.key.toLowerCase() === "content-type")?.value; + + const tabSx = { + textTransform: "none", + }; + + return ( + + + + setTabValue(value)}> + 1 ? "s" : "") + ")" : "")} + sx={tabSx} + /> + + + + + + {body && } + {!hasResponse && reqNotSent} + + + {headers.length > 0 && } + {!hasResponse && reqNotSent} + + + + + ); +} + +export default ResponseTabs; diff --git a/admin/src/components/sender/createOrUpdateRequest.graphql b/admin/src/components/sender/createOrUpdateRequest.graphql new file mode 100644 index 0000000..d94c762 --- /dev/null +++ b/admin/src/components/sender/createOrUpdateRequest.graphql @@ -0,0 +1,5 @@ +mutation CreateOrUpdateSenderRequest($request: SenderRequestInput!) { + createOrUpdateSenderRequest(request: $request) { + id + } +} diff --git a/admin/src/components/sender/createSenderRequestFromRequestLog.graphql b/admin/src/components/sender/createSenderRequestFromRequestLog.graphql new file mode 100644 index 0000000..4516ada --- /dev/null +++ b/admin/src/components/sender/createSenderRequestFromRequestLog.graphql @@ -0,0 +1,5 @@ +mutation CreateSenderRequestFromHttpRequestLog($id: ID!) { + createSenderRequestFromHttpRequestLog(id: $id) { + id + } +} diff --git a/admin/src/components/sender/sendRequest.graphql b/admin/src/components/sender/sendRequest.graphql new file mode 100644 index 0000000..8c963d3 --- /dev/null +++ b/admin/src/components/sender/sendRequest.graphql @@ -0,0 +1,5 @@ +mutation SendRequest($id: ID!) { + sendRequest(id: $id) { + id + } +} diff --git a/admin/src/components/sender/senderRequest.graphql b/admin/src/components/sender/senderRequest.graphql new file mode 100644 index 0000000..9f861f1 --- /dev/null +++ b/admin/src/components/sender/senderRequest.graphql @@ -0,0 +1,26 @@ +query GetSenderRequest($id: ID!) { + senderRequest(id: $id) { + id + sourceRequestLogID + url + method + proto + headers { + key + value + } + body + timestamp + response { + id + proto + statusCode + statusReason + body + headers { + key + value + } + } + } +} diff --git a/admin/src/components/sender/senderRequests.graphql b/admin/src/components/sender/senderRequests.graphql new file mode 100644 index 0000000..a7e507b --- /dev/null +++ b/admin/src/components/sender/senderRequests.graphql @@ -0,0 +1,12 @@ +query GetSenderRequests { + senderRequests { + id + url + method + response { + id + statusCode + statusReason + } + } +} diff --git a/admin/src/generated/graphql.tsx b/admin/src/generated/graphql.tsx new file mode 100644 index 0000000..52c5bc2 --- /dev/null +++ b/admin/src/generated/graphql.tsx @@ -0,0 +1,479 @@ +import { gql } from '@apollo/client'; +import * as Apollo from '@apollo/client'; +export type Maybe = T | null; +export type InputMaybe = Maybe; +export type Exact = { [K in keyof T]: T[K] }; +export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; +export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; +const defaultOptions = {} as const; +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: string; + String: string; + Boolean: boolean; + Int: number; + Float: number; + Regexp: any; + Time: any; + URL: any; +}; + +export type ClearHttpRequestLogResult = { + __typename?: 'ClearHTTPRequestLogResult'; + success: Scalars['Boolean']; +}; + +export type CloseProjectResult = { + __typename?: 'CloseProjectResult'; + success: Scalars['Boolean']; +}; + +export type DeleteProjectResult = { + __typename?: 'DeleteProjectResult'; + success: Scalars['Boolean']; +}; + +export type DeleteSenderRequestsResult = { + __typename?: 'DeleteSenderRequestsResult'; + success: Scalars['Boolean']; +}; + +export type HttpHeader = { + __typename?: 'HttpHeader'; + key: Scalars['String']; + value: Scalars['String']; +}; + +export type HttpHeaderInput = { + key: Scalars['String']; + value: Scalars['String']; +}; + +export enum HttpMethod { + Connect = 'CONNECT', + Delete = 'DELETE', + Get = 'GET', + Head = 'HEAD', + Options = 'OPTIONS', + Patch = 'PATCH', + Post = 'POST', + Put = 'PUT', + Trace = 'TRACE' +} + +export enum HttpProtocol { + Http1 = 'HTTP1', + Http2 = 'HTTP2' +} + +export type HttpRequestLog = { + __typename?: 'HttpRequestLog'; + body?: Maybe; + headers: Array; + id: Scalars['ID']; + method: HttpMethod; + proto: Scalars['String']; + response?: Maybe; + timestamp: Scalars['Time']; + url: Scalars['String']; +}; + +export type HttpRequestLogFilter = { + __typename?: 'HttpRequestLogFilter'; + onlyInScope: Scalars['Boolean']; + searchExpression?: Maybe; +}; + +export type HttpRequestLogFilterInput = { + onlyInScope?: InputMaybe; + searchExpression?: InputMaybe; +}; + +export type HttpResponseLog = { + __typename?: 'HttpResponseLog'; + body?: Maybe; + headers: Array; + /** Will be the same ID as its related request ID. */ + id: Scalars['ID']; + proto: HttpProtocol; + statusCode: Scalars['Int']; + statusReason: Scalars['String']; +}; + +export type Mutation = { + __typename?: 'Mutation'; + clearHTTPRequestLog: ClearHttpRequestLogResult; + closeProject: CloseProjectResult; + createOrUpdateSenderRequest: SenderRequest; + createProject?: Maybe; + createSenderRequestFromHttpRequestLog: SenderRequest; + deleteProject: DeleteProjectResult; + deleteSenderRequests: DeleteSenderRequestsResult; + openProject?: Maybe; + sendRequest: SenderRequest; + setHttpRequestLogFilter?: Maybe; + setScope: Array; + setSenderRequestFilter?: Maybe; +}; + + +export type MutationCreateOrUpdateSenderRequestArgs = { + request: SenderRequestInput; +}; + + +export type MutationCreateProjectArgs = { + name: Scalars['String']; +}; + + +export type MutationCreateSenderRequestFromHttpRequestLogArgs = { + id: Scalars['ID']; +}; + + +export type MutationDeleteProjectArgs = { + id: Scalars['ID']; +}; + + +export type MutationOpenProjectArgs = { + id: Scalars['ID']; +}; + + +export type MutationSendRequestArgs = { + id: Scalars['ID']; +}; + + +export type MutationSetHttpRequestLogFilterArgs = { + filter?: InputMaybe; +}; + + +export type MutationSetScopeArgs = { + scope: Array; +}; + + +export type MutationSetSenderRequestFilterArgs = { + filter?: InputMaybe; +}; + +export type Project = { + __typename?: 'Project'; + id: Scalars['ID']; + isActive: Scalars['Boolean']; + name: Scalars['String']; +}; + +export type Query = { + __typename?: 'Query'; + activeProject?: Maybe; + httpRequestLog?: Maybe; + httpRequestLogFilter?: Maybe; + httpRequestLogs: Array; + projects: Array; + scope: Array; + senderRequest?: Maybe; + senderRequests: Array; +}; + + +export type QueryHttpRequestLogArgs = { + id: Scalars['ID']; +}; + + +export type QuerySenderRequestArgs = { + id: Scalars['ID']; +}; + +export type ScopeHeader = { + __typename?: 'ScopeHeader'; + key?: Maybe; + value?: Maybe; +}; + +export type ScopeHeaderInput = { + key?: InputMaybe; + value?: InputMaybe; +}; + +export type ScopeRule = { + __typename?: 'ScopeRule'; + body?: Maybe; + header?: Maybe; + url?: Maybe; +}; + +export type ScopeRuleInput = { + body?: InputMaybe; + header?: InputMaybe; + url?: InputMaybe; +}; + +export type SenderRequest = { + __typename?: 'SenderRequest'; + body?: Maybe; + headers?: Maybe>; + id: Scalars['ID']; + method: HttpMethod; + proto: HttpProtocol; + response?: Maybe; + sourceRequestLogID?: Maybe; + timestamp: Scalars['Time']; + url: Scalars['URL']; +}; + +export type SenderRequestFilter = { + __typename?: 'SenderRequestFilter'; + onlyInScope: Scalars['Boolean']; + searchExpression?: Maybe; +}; + +export type SenderRequestFilterInput = { + onlyInScope?: InputMaybe; + searchExpression?: InputMaybe; +}; + +export type SenderRequestInput = { + body?: InputMaybe; + headers?: InputMaybe>; + id?: InputMaybe; + method?: InputMaybe; + proto?: InputMaybe; + url: Scalars['URL']; +}; + +export type CreateOrUpdateSenderRequestMutationVariables = Exact<{ + request: SenderRequestInput; +}>; + + +export type CreateOrUpdateSenderRequestMutation = { __typename?: 'Mutation', createOrUpdateSenderRequest: { __typename?: 'SenderRequest', id: string } }; + +export type CreateSenderRequestFromHttpRequestLogMutationVariables = Exact<{ + id: Scalars['ID']; +}>; + + +export type CreateSenderRequestFromHttpRequestLogMutation = { __typename?: 'Mutation', createSenderRequestFromHttpRequestLog: { __typename?: 'SenderRequest', id: string } }; + +export type SendRequestMutationVariables = Exact<{ + id: Scalars['ID']; +}>; + + +export type SendRequestMutation = { __typename?: 'Mutation', sendRequest: { __typename?: 'SenderRequest', id: string } }; + +export type GetSenderRequestQueryVariables = Exact<{ + id: Scalars['ID']; +}>; + + +export type GetSenderRequestQuery = { __typename?: 'Query', senderRequest?: { __typename?: 'SenderRequest', id: string, sourceRequestLogID?: string | null, url: any, method: HttpMethod, proto: HttpProtocol, body?: string | null, timestamp: any, headers?: Array<{ __typename?: 'HttpHeader', key: string, value: string }> | null, response?: { __typename?: 'HttpResponseLog', id: string, proto: HttpProtocol, statusCode: number, statusReason: string, body?: string | null, headers: Array<{ __typename?: 'HttpHeader', key: string, value: string }> } | null } | null }; + +export type GetSenderRequestsQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetSenderRequestsQuery = { __typename?: 'Query', senderRequests: Array<{ __typename?: 'SenderRequest', id: string, url: any, method: HttpMethod, response?: { __typename?: 'HttpResponseLog', id: string, statusCode: number, statusReason: string } | null }> }; + + +export const CreateOrUpdateSenderRequestDocument = gql` + mutation CreateOrUpdateSenderRequest($request: SenderRequestInput!) { + createOrUpdateSenderRequest(request: $request) { + id + } +} + `; +export type CreateOrUpdateSenderRequestMutationFn = Apollo.MutationFunction; + +/** + * __useCreateOrUpdateSenderRequestMutation__ + * + * To run a mutation, you first call `useCreateOrUpdateSenderRequestMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useCreateOrUpdateSenderRequestMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [createOrUpdateSenderRequestMutation, { data, loading, error }] = useCreateOrUpdateSenderRequestMutation({ + * variables: { + * request: // value for 'request' + * }, + * }); + */ +export function useCreateOrUpdateSenderRequestMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(CreateOrUpdateSenderRequestDocument, options); + } +export type CreateOrUpdateSenderRequestMutationHookResult = ReturnType; +export type CreateOrUpdateSenderRequestMutationResult = Apollo.MutationResult; +export type CreateOrUpdateSenderRequestMutationOptions = Apollo.BaseMutationOptions; +export const CreateSenderRequestFromHttpRequestLogDocument = gql` + mutation CreateSenderRequestFromHttpRequestLog($id: ID!) { + createSenderRequestFromHttpRequestLog(id: $id) { + id + } +} + `; +export type CreateSenderRequestFromHttpRequestLogMutationFn = Apollo.MutationFunction; + +/** + * __useCreateSenderRequestFromHttpRequestLogMutation__ + * + * To run a mutation, you first call `useCreateSenderRequestFromHttpRequestLogMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useCreateSenderRequestFromHttpRequestLogMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [createSenderRequestFromHttpRequestLogMutation, { data, loading, error }] = useCreateSenderRequestFromHttpRequestLogMutation({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useCreateSenderRequestFromHttpRequestLogMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(CreateSenderRequestFromHttpRequestLogDocument, options); + } +export type CreateSenderRequestFromHttpRequestLogMutationHookResult = ReturnType; +export type CreateSenderRequestFromHttpRequestLogMutationResult = Apollo.MutationResult; +export type CreateSenderRequestFromHttpRequestLogMutationOptions = Apollo.BaseMutationOptions; +export const SendRequestDocument = gql` + mutation SendRequest($id: ID!) { + sendRequest(id: $id) { + id + } +} + `; +export type SendRequestMutationFn = Apollo.MutationFunction; + +/** + * __useSendRequestMutation__ + * + * To run a mutation, you first call `useSendRequestMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useSendRequestMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [sendRequestMutation, { data, loading, error }] = useSendRequestMutation({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useSendRequestMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(SendRequestDocument, options); + } +export type SendRequestMutationHookResult = ReturnType; +export type SendRequestMutationResult = Apollo.MutationResult; +export type SendRequestMutationOptions = Apollo.BaseMutationOptions; +export const GetSenderRequestDocument = gql` + query GetSenderRequest($id: ID!) { + senderRequest(id: $id) { + id + sourceRequestLogID + url + method + proto + headers { + key + value + } + body + timestamp + response { + id + proto + statusCode + statusReason + body + headers { + key + value + } + } + } +} + `; + +/** + * __useGetSenderRequestQuery__ + * + * To run a query within a React component, call `useGetSenderRequestQuery` and pass it any options that fit your needs. + * When your component renders, `useGetSenderRequestQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetSenderRequestQuery({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useGetSenderRequestQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetSenderRequestDocument, options); + } +export function useGetSenderRequestLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetSenderRequestDocument, options); + } +export type GetSenderRequestQueryHookResult = ReturnType; +export type GetSenderRequestLazyQueryHookResult = ReturnType; +export type GetSenderRequestQueryResult = Apollo.QueryResult; +export const GetSenderRequestsDocument = gql` + query GetSenderRequests { + senderRequests { + id + url + method + response { + id + statusCode + statusReason + } + } +} + `; + +/** + * __useGetSenderRequestsQuery__ + * + * To run a query within a React component, call `useGetSenderRequestsQuery` and pass it any options that fit your needs. + * When your component renders, `useGetSenderRequestsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetSenderRequestsQuery({ + * variables: { + * }, + * }); + */ +export function useGetSenderRequestsQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetSenderRequestsDocument, options); + } +export function useGetSenderRequestsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetSenderRequestsDocument, options); + } +export type GetSenderRequestsQueryHookResult = ReturnType; +export type GetSenderRequestsLazyQueryHookResult = ReturnType; +export type GetSenderRequestsQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/admin/src/pages/_app.tsx b/admin/src/pages/_app.tsx index 130f88b..b1c2056 100644 --- a/admin/src/pages/_app.tsx +++ b/admin/src/pages/_app.tsx @@ -9,6 +9,7 @@ import { CacheProvider, EmotionCache } from "@emotion/react"; import createEmotionCache from "../lib/createEmotionCache"; import theme from "../lib/theme"; import { useApollo } from "../lib/graphql"; +import "../styles.css"; // Client-side cache, shared for the whole session of the user in the browser. const clientSideEmotionCache = createEmotionCache(); diff --git a/admin/src/pages/sender/index.tsx b/admin/src/pages/sender/index.tsx index f24304b..1607eda 100644 --- a/admin/src/pages/sender/index.tsx +++ b/admin/src/pages/sender/index.tsx @@ -1,11 +1,47 @@ -import { Box, Typography } from "@mui/material"; +import { Box } from "@mui/system"; +import { AllotmentProps } from "allotment"; +import { PaneProps } from "allotment/dist/types/src/allotment"; +import { ComponentType, useEffect, useRef, useState } from "react"; import Layout, { Page } from "../../components/Layout"; +import EditRequest from "../../components/sender/EditRequest"; +import History from "../../components/sender/History"; function Index(): JSX.Element { + const isMountedRef = useRef(false); + const [Allotment, setAllotment] = useState< + (ComponentType & { Pane: ComponentType }) | null + >(null); + useEffect(() => { + isMountedRef.current = true; + import("allotment") + .then((mod) => { + if (!isMountedRef.current) { + return; + } + setAllotment(mod.Allotment); + }) + .catch((err) => console.error(err, `could not import allotment ${err.message}`)); + return () => { + isMountedRef.current = false; + }; + }, []); + if (!Allotment) { + return
Loading...
; + } + return ( - Coming soon… + + + + + + + + + + ); } diff --git a/admin/src/styles.css b/admin/src/styles.css new file mode 100644 index 0000000..9cb6823 --- /dev/null +++ b/admin/src/styles.css @@ -0,0 +1,5 @@ +html, +body, +#__next { + height: 100%; +} diff --git a/admin/tsconfig.json b/admin/tsconfig.json index e6bb8eb..217154d 100644 --- a/admin/tsconfig.json +++ b/admin/tsconfig.json @@ -6,6 +6,7 @@ "dom.iterable", "esnext" ], + "downlevelIteration": true, "allowJs": true, "skipLibCheck": true, "strict": true, diff --git a/admin/yarn.lock b/admin/yarn.lock index f92e604..3bf8ce6 100644 --- a/admin/yarn.lock +++ b/admin/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@ampproject/remapping@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.1.tgz#7922fb0817bf3166d8d9e258c57477e3fd1c3610" + integrity sha512-Aolwjd7HSC2PyY0fDj/wA/EimQT4HfEnFYNp5s9CQlrdhyvWTtvZ5YzrUPu6R6/1jKiUlxu8bUhkdSnKHNAHMA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.0" + "@apollo/client@^3.2.0": version "3.5.8" resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.5.8.tgz#7215b974c5988b6157530eb69369209210349fe0" @@ -53,6 +60,36 @@ semver "^6.3.0" source-map "^0.5.0" +"@babel/core@^7.14.0": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.2.tgz#2c77fc430e95139d816d39b113b31bf40fb22337" + integrity sha512-R3VH5G42VSDolRHyUO4V2cfag8WHcZyxdq5Z/m8Xyb92lW/Erm/6kM+XtRFGf3Mulre3mveni2NHfEUws8wSvw== + dependencies: + "@ampproject/remapping" "^2.0.0" + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.0" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.17.2" + "@babel/parser" "^7.17.0" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.0" + "@babel/types" "^7.17.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + +"@babel/generator@^7.14.0", "@babel/generator@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.0.tgz#7bd890ba706cd86d3e2f727322346ffdbf98f65e" + integrity sha512-I3Omiv6FGOC29dtlZhkfXO6pgkmukJSlT26QjVvS1DGZe/NzSVCPG41X0tS21oZkJYlovfj9qDWgKP+Cn4bXxw== + dependencies: + "@babel/types" "^7.17.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/generator@^7.16.8": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" @@ -62,6 +99,13 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/helper-annotate-as-pure@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862" + integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-compilation-targets@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" @@ -72,6 +116,19 @@ browserslist "^4.17.5" semver "^6.3.0" +"@babel/helper-create-class-features-plugin@^7.16.7": + version "7.17.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz#9699f14a88833a7e055ce57dcd3ffdcd25186b21" + integrity sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-environment-visitor@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" @@ -102,6 +159,13 @@ dependencies: "@babel/types" "^7.16.7" +"@babel/helper-member-expression-to-functions@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0" + integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q== + dependencies: + "@babel/types" "^7.16.7" + "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" @@ -123,11 +187,29 @@ "@babel/traverse" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7": +"@babel/helper-optimise-call-expression@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2" + integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== +"@babel/helper-replace-supers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1" + integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-member-expression-to-functions" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + "@babel/helper-simple-access@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" @@ -135,6 +217,13 @@ dependencies: "@babel/types" "^7.16.7" +"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" + integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== + dependencies: + "@babel/types" "^7.16.0" + "@babel/helper-split-export-declaration@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" @@ -161,6 +250,15 @@ "@babel/traverse" "^7.16.7" "@babel/types" "^7.16.7" +"@babel/helpers@^7.17.2": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417" + integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.17.0" + "@babel/types" "^7.17.0" + "@babel/highlight@^7.16.7": version "7.16.10" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" @@ -170,11 +268,49 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/parser@^7.14.0", "@babel/parser@^7.16.8", "@babel/parser@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.0.tgz#f0ac33eddbe214e4105363bb17c3341c5ffcc43c" + integrity sha512-VKXSCQx5D8S04ej+Dqsr1CzYvvWgf20jIw2D+YhQCrIlr2UZGaDds23Y0xg75/skOxpLCRpUZvk/1EAVkGoDOw== + "@babel/parser@^7.16.10", "@babel/parser@^7.16.12", "@babel/parser@^7.16.7": version "7.16.12" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.12.tgz#9474794f9a650cf5e2f892444227f98e28cdf8b6" integrity sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A== +"@babel/plugin-proposal-class-properties@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0" + integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-proposal-object-rest-spread@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz#94593ef1ddf37021a25bdcb5754c4a8d534b01d8" + integrity sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.16.7" + +"@babel/plugin-syntax-class-properties@^7.0.0": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-flow@^7.0.0", "@babel/plugin-syntax-flow@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.16.7.tgz#202b147e5892b8452bbb0bb269c7ed2539ab8832" + integrity sha512-UDo3YGQO0jH6ytzVwgSLv9i/CzMcUjbKenL67dTrAZPPv6GFAtDhe6jqnvmoKzC/7htNTohhos+onPtDMqJwaQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-jsx@7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz#000e2e25d8673cce49300517a3eda44c263e4201" @@ -182,13 +318,179 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-jsx@^7.12.13": +"@babel/plugin-syntax-jsx@^7.0.0", "@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665" integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q== dependencies: "@babel/helper-plugin-utils" "^7.16.7" +"@babel/plugin-syntax-object-rest-spread@^7.0.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-transform-arrow-functions@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154" + integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-block-scoped-functions@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620" + integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-block-scoping@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87" + integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-classes@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00" + integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-optimise-call-expression" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470" + integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-destructuring@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz#ca9588ae2d63978a4c29d3f33282d8603f618e23" + integrity sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-flow-strip-types@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.16.7.tgz#291fb140c78dabbf87f2427e7c7c332b126964b8" + integrity sha512-mzmCq3cNsDpZZu9FADYYyfZJIOrSONmHcop2XEKPdBNMa4PDC4eEvcOvzZaCNcjKu72v0XQlA5y1g58aLRXdYg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-flow" "^7.16.7" + +"@babel/plugin-transform-for-of@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c" + integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-function-name@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf" + integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA== + dependencies: + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-literals@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1" + integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-member-expression-literals@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384" + integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-modules-commonjs@^7.0.0": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe" + integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA== + dependencies: + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-object-super@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94" + integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-replace-supers" "^7.16.7" + +"@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f" + integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-property-literals@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55" + integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-react-display-name@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz#7b6d40d232f4c0f550ea348593db3b21e2404340" + integrity sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-react-jsx@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz#86a6a220552afd0e4e1f0388a68a372be7add0d4" + integrity sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/plugin-syntax-jsx" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/plugin-transform-shorthand-properties@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a" + integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/plugin-transform-spread@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44" + integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + +"@babel/plugin-transform-template-literals@^7.0.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab" + integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + "@babel/runtime-corejs3@^7.10.2": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.16.8.tgz#ea533d96eda6fdc76b1812248e9fbd0c11d4a1a7" @@ -197,6 +499,13 @@ core-js-pure "^3.20.2" regenerator-runtime "^0.13.4" +"@babel/runtime@^7.0.0": + version "7.17.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941" + integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/runtime@^7.10.2", "@babel/runtime@^7.13.10", "@babel/runtime@^7.16.3", "@babel/runtime@^7.16.7", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa" @@ -213,6 +522,22 @@ "@babel/parser" "^7.16.7" "@babel/types" "^7.16.7" +"@babel/traverse@^7.14.0", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.0.tgz#3143e5066796408ccc880a33ecd3184f3e75cd30" + integrity sha512-fpFIXvqD6kC7c7PUNnZ0Z8cQXlarCLtCUpt2S1Dx7PjoRtCFffvOkHHSom+m5HIxMZn5bIBVb71lhabcmjEsqg== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.17.0" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.17.0" + "@babel/types" "^7.17.0" + debug "^4.1.0" + globals "^11.1.0" + "@babel/traverse@^7.16.10", "@babel/traverse@^7.16.7": version "7.16.10" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.10.tgz#448f940defbe95b5a8029975b051f75993e8239f" @@ -237,6 +562,14 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" +"@babel/types@^7.0.0", "@babel/types@^7.16.0", "@babel/types@^7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b" + integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + "@babel/types@^7.16.7", "@babel/types@^7.16.8": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" @@ -389,6 +722,16 @@ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== +"@endemolshinegroup/cosmiconfig-typescript-loader@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz#eea4635828dde372838b0909693ebd9aafeec22d" + integrity sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA== + dependencies: + lodash.get "^4" + make-error "^1" + ts-node "^9" + tslib "^2" + "@eslint/eslintrc@^1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" @@ -404,6 +747,360 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" +"@graphql-codegen/cli@2.6.1": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/cli/-/cli-2.6.1.tgz#022a82159d263b5fbdd5da2e4d6e8e66db1e1a5b" + integrity sha512-bIpnujBEg/WRv0wl4W309hNUDK+glnSOkKQiuT2LpSN0nvJNsJsi1k4NCA4SGWs5ZbyLkWflfOXxEVkv5fVWZA== + dependencies: + "@graphql-codegen/core" "2.5.1" + "@graphql-codegen/plugin-helpers" "^2.4.1" + "@graphql-tools/apollo-engine-loader" "^7.0.5" + "@graphql-tools/code-file-loader" "^7.0.6" + "@graphql-tools/git-loader" "^7.0.5" + "@graphql-tools/github-loader" "^7.0.5" + "@graphql-tools/graphql-file-loader" "^7.0.5" + "@graphql-tools/json-file-loader" "^7.1.2" + "@graphql-tools/load" "^7.3.0" + "@graphql-tools/prisma-loader" "^7.0.6" + "@graphql-tools/url-loader" "^7.0.11" + "@graphql-tools/utils" "^8.1.1" + ansi-escapes "^4.3.1" + chalk "^4.1.0" + change-case-all "1.0.14" + chokidar "^3.5.2" + common-tags "^1.8.0" + cosmiconfig "^7.0.0" + debounce "^1.2.0" + dependency-graph "^0.11.0" + detect-indent "^6.0.0" + glob "^7.1.6" + globby "^11.0.4" + graphql-config "^4.1.0" + inquirer "^8.0.0" + is-glob "^4.0.1" + json-to-pretty-yaml "^1.2.2" + latest-version "5.1.0" + listr "^0.14.3" + listr-update-renderer "^0.5.0" + log-symbols "^4.0.0" + minimatch "^3.0.4" + mkdirp "^1.0.4" + string-env-interpolation "^1.0.1" + ts-log "^2.2.3" + tslib "~2.3.0" + valid-url "^1.0.9" + wrap-ansi "^7.0.0" + yaml "^1.10.0" + yargs "^17.0.0" + +"@graphql-codegen/core@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/core/-/core-2.5.1.tgz#e3d50d3449b8c58b74ea08e97faf656a1b7fc8a1" + integrity sha512-alctBVl2hMnBXDLwkgmnFPrZVIiBDsWJSmxJcM4GKg1PB23+xuov35GE47YAyAhQItE1B1fbYnbb1PtGiDZ4LA== + dependencies: + "@graphql-codegen/plugin-helpers" "^2.4.1" + "@graphql-tools/schema" "^8.1.2" + "@graphql-tools/utils" "^8.1.1" + tslib "~2.3.0" + +"@graphql-codegen/introspection@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/introspection/-/introspection-2.1.1.tgz#5f3aac47ef46ed817baf969e78dd2dd6d307b18a" + integrity sha512-O9zsy0IoFYDo37pBVF4pSvRMDx/AKdgOxyko4R/O+0DHEw9Nya/pQ3dbn+LDLj2n6X+xOXUBUfFvqhODTqU28w== + dependencies: + "@graphql-codegen/plugin-helpers" "^2.3.2" + tslib "~2.3.0" + +"@graphql-codegen/plugin-helpers@^2.3.2", "@graphql-codegen/plugin-helpers@^2.4.0", "@graphql-codegen/plugin-helpers@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/plugin-helpers/-/plugin-helpers-2.4.1.tgz#433845a89b0b4b3a2a0e959e0a2cfe444cf7aeac" + integrity sha512-OPMma7aUnES3Dh+M0BfiNBnJLmYuH60EnbULAhufxFDn/Y2OA0Ht/LQok9beX6VN4ASZEMCOAGItJezGJr5DJw== + dependencies: + "@graphql-tools/utils" "^8.5.2" + change-case-all "1.0.14" + common-tags "1.8.2" + import-from "4.0.0" + lodash "~4.17.0" + tslib "~2.3.0" + +"@graphql-codegen/schema-ast@^2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@graphql-codegen/schema-ast/-/schema-ast-2.4.1.tgz#ad742b53e32f7a2fbff8ea8a91ba7e617e6ef236" + integrity sha512-bIWlKk/ShoVJfghA4Rt1OWnd34/dQmZM/vAe6fu6QKyOh44aAdqPtYQ2dbTyFXoknmu504etKJGEDllYNUJRfg== + dependencies: + "@graphql-codegen/plugin-helpers" "^2.3.2" + "@graphql-tools/utils" "^8.1.1" + tslib "~2.3.0" + +"@graphql-codegen/typescript-operations@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-operations/-/typescript-operations-2.3.0.tgz#4e43785fe12f90d53cfe066e0e8b5b37bd097292" + integrity sha512-CIiNSNWKs3PT6UNC8aVvUXXcb6fa5u9NhHW6Qmfx4fXse9JKn6zwNdJio9cU/HfjwnWDCx1yWO+ngMEg3Lec4A== + dependencies: + "@graphql-codegen/plugin-helpers" "^2.4.0" + "@graphql-codegen/typescript" "^2.4.3" + "@graphql-codegen/visitor-plugin-common" "2.6.0" + auto-bind "~4.0.0" + tslib "~2.3.0" + +"@graphql-codegen/typescript-react-apollo@3.2.6": + version "3.2.6" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript-react-apollo/-/typescript-react-apollo-3.2.6.tgz#e5685bf38c3b4d2ae6ec0b11d6aac007524ab9ca" + integrity sha512-VPCjuGgEMiyRWh2lE7U95j+iQbRI7ryl5/QNmPl8NQI5q+a5OFTDXbHjZrqHliKVFuCBfXOER7iCvPwWrQiGiQ== + dependencies: + "@graphql-codegen/plugin-helpers" "^2.4.0" + "@graphql-codegen/visitor-plugin-common" "2.6.0" + auto-bind "~4.0.0" + change-case-all "1.0.14" + tslib "~2.3.0" + +"@graphql-codegen/typescript@2.4.3", "@graphql-codegen/typescript@^2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@graphql-codegen/typescript/-/typescript-2.4.3.tgz#8e4e1d12b31e925231e034da9b378045ab206040" + integrity sha512-5b+4EVA01kiKId6IbBvuvSs0/aGeuSU+Cg2pBbe9VZol49iid982p28k9knEH4Jzgu4tUp4UMQTWNNwkPB4tEQ== + dependencies: + "@graphql-codegen/plugin-helpers" "^2.4.0" + "@graphql-codegen/schema-ast" "^2.4.1" + "@graphql-codegen/visitor-plugin-common" "2.6.0" + auto-bind "~4.0.0" + tslib "~2.3.0" + +"@graphql-codegen/visitor-plugin-common@2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-2.6.0.tgz#564a60399f2db9070a5569ba96ceb0f8c0a6c2a3" + integrity sha512-MysdJ8L/dIn62D+BFbiu6HSVaZfkAt0EI1g5twkpKzLmG7qDJ8P7KemFVFU/sCW3SVuhs7XabkSjnFK9uBquwg== + dependencies: + "@graphql-codegen/plugin-helpers" "^2.4.0" + "@graphql-tools/optimize" "^1.0.1" + "@graphql-tools/relay-operation-optimizer" "^6.3.7" + "@graphql-tools/utils" "^8.3.0" + auto-bind "~4.0.0" + change-case-all "1.0.14" + dependency-graph "^0.11.0" + graphql-tag "^2.11.0" + parse-filepath "^1.0.2" + tslib "~2.3.0" + +"@graphql-tools/apollo-engine-loader@^7.0.5": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-7.2.2.tgz#1463f5d2d95b5ca2b602b35b4922b38935013860" + integrity sha512-jrtA1IvgbaHzla9nyBngNyvajudTcQAVE3//mgrK+DoN7UpUhtoXfxTOOq2tzZN67o4a6Bv/RJsxB3rSI3NLzg== + dependencies: + "@graphql-tools/utils" "^8.5.1" + cross-undici-fetch "^0.1.19" + sync-fetch "0.3.1" + tslib "~2.3.0" + +"@graphql-tools/batch-execute@^8.3.1": + version "8.3.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-8.3.1.tgz#0b74c54db5ac1c5b9a273baefc034c2343ebbb74" + integrity sha512-63kHY8ZdoO5FoeDXYHnAak1R3ysMViMPwWC2XUblFckuVLMUPmB2ONje8rjr2CvzWBHAW8c1Zsex+U3xhKtGIA== + dependencies: + "@graphql-tools/utils" "^8.5.1" + dataloader "2.0.0" + tslib "~2.3.0" + value-or-promise "1.0.11" + +"@graphql-tools/code-file-loader@^7.0.6": + version "7.2.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/code-file-loader/-/code-file-loader-7.2.3.tgz#b53e8809528da07911423c3a511e5fccf9121a12" + integrity sha512-aNVG3/VG5cUpS389rpCum+z7RY98qvPwOzd+J4LVr+f5hWQbDREnSFM+5RVTDfULujrsi7edKaGxGKp68pGmAA== + dependencies: + "@graphql-tools/graphql-tag-pluck" "^7.1.3" + "@graphql-tools/utils" "^8.5.1" + globby "^11.0.3" + tslib "~2.3.0" + unixify "^1.0.0" + +"@graphql-tools/delegate@^8.4.1", "@graphql-tools/delegate@^8.4.2": + version "8.4.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-8.4.3.tgz#ad73ed7cc3b4cad9242c6d4835a5ae0b640f7164" + integrity sha512-hKTJdJXJnKL0+2vpU+Kt7OHQTIXZ9mBmNBwHsYiG5WNArz/vNI7910r6TC2XMf/e7zhyyK+mXxMDBmDQkkJagA== + dependencies: + "@graphql-tools/batch-execute" "^8.3.1" + "@graphql-tools/schema" "^8.3.1" + "@graphql-tools/utils" "^8.5.4" + dataloader "2.0.0" + tslib "~2.3.0" + value-or-promise "1.0.11" + +"@graphql-tools/git-loader@^7.0.5": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/git-loader/-/git-loader-7.1.2.tgz#7a7b5fc366bcc9e2e14e0463ff73f1a19aafabbd" + integrity sha512-vIMrISQPKQgHS893b8K/pEE1InPV+7etzFhHoyQRhYkVHXP2RBkfI64Wq9bNPezF8Ss/dwIjI/keLaPp9EQDmA== + dependencies: + "@graphql-tools/graphql-tag-pluck" "^7.1.3" + "@graphql-tools/utils" "^8.5.1" + is-glob "4.0.3" + micromatch "^4.0.4" + tslib "~2.3.0" + unixify "^1.0.0" + +"@graphql-tools/github-loader@^7.0.5": + version "7.2.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/github-loader/-/github-loader-7.2.3.tgz#1195150078e48c1b49b5106973c5ec5c928b24c1" + integrity sha512-enbMT5lWtKaLGw0PB9RL9Xg/oc9y89e6ihuxD/ZnnNXo60J1JVNtTy3+gRgXvGOX9WtJgy3UDVudDefrOHsqaA== + dependencies: + "@graphql-tools/graphql-tag-pluck" "^7.1.3" + "@graphql-tools/utils" "^8.5.1" + cross-undici-fetch "^0.1.19" + sync-fetch "0.3.1" + tslib "~2.3.0" + +"@graphql-tools/graphql-file-loader@^7.0.5", "@graphql-tools/graphql-file-loader@^7.3.2": + version "7.3.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-file-loader/-/graphql-file-loader-7.3.3.tgz#7cee2f84f08dc13fa756820b510248b857583d36" + integrity sha512-6kUJZiNpYKVhum9E5wfl5PyLLupEDYdH7c8l6oMrk6c7EPEVs6iSUyB7yQoWrtJccJLULBW2CRQ5IHp5JYK0mA== + dependencies: + "@graphql-tools/import" "^6.5.7" + "@graphql-tools/utils" "^8.5.1" + globby "^11.0.3" + tslib "~2.3.0" + unixify "^1.0.0" + +"@graphql-tools/graphql-tag-pluck@^7.1.3": + version "7.1.5" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-7.1.5.tgz#229ed40f38430cdea750f112cbfad89fbc29129c" + integrity sha512-NKbFcjlg7cbK+scLXc6eVxXIhX4k8QL6lZ/y5Ju7yrpIN18k2vA78dI6W3Qb5qdftxbDNuC+kDmScZfzzxVPjQ== + dependencies: + "@babel/parser" "^7.16.8" + "@babel/traverse" "^7.16.8" + "@babel/types" "^7.16.8" + "@graphql-tools/utils" "^8.5.1" + tslib "~2.3.0" + +"@graphql-tools/import@^6.5.7": + version "6.6.5" + resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-6.6.5.tgz#e1ec593960288ceda7d5c56c0073c702b1bdcfa0" + integrity sha512-w0/cYuhrr2apn+iGoTToCqt65x2NN2iHQyqRNk/Zw1NJ+e8/C3eKVw0jmW4pYQvSocuPxL4UCSI56SdKO7m3+Q== + dependencies: + "@graphql-tools/utils" "8.6.1" + resolve-from "5.0.0" + tslib "~2.3.0" + +"@graphql-tools/json-file-loader@^7.1.2", "@graphql-tools/json-file-loader@^7.3.2": + version "7.3.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/json-file-loader/-/json-file-loader-7.3.3.tgz#45cfde77b9dc4ab6c21575305ae537d2814d237f" + integrity sha512-CN2Qk9rt+Gepa3rb3X/mpxYA5MIYLwZBPj2Njw6lbZ6AaxG+O1ArDCL5ACoiWiBimn1FCOM778uhRM9znd0b3Q== + dependencies: + "@graphql-tools/utils" "^8.5.1" + globby "^11.0.3" + tslib "~2.3.0" + unixify "^1.0.0" + +"@graphql-tools/load@^7.3.0", "@graphql-tools/load@^7.4.1": + version "7.5.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-7.5.1.tgz#8c7f846d2185ddc1d44fdfbf1ed9cb678f69e40b" + integrity sha512-j9XcLYZPZdl/TzzqA83qveJmwcCxgGizt5L1+C1/Z68brTEmQHLdQCOR3Ma3ewESJt6DU05kSTu2raKaunkjRg== + dependencies: + "@graphql-tools/schema" "8.3.1" + "@graphql-tools/utils" "^8.6.0" + p-limit "3.1.0" + tslib "~2.3.0" + +"@graphql-tools/merge@^8.2.1": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.2.2.tgz#433566c662a33f5a9c3cc5f3ce3753fb0019477a" + integrity sha512-2DyqhIOMUMKbCPqo8p6xSdll2OBcBxGdOrxlJJlFQvinsSaYqp/ct3dhAxNtzaIcvSVgXvttQqfD7O2ziFtE7Q== + dependencies: + "@graphql-tools/utils" "^8.5.1" + tslib "~2.3.0" + +"@graphql-tools/optimize@^1.0.1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/optimize/-/optimize-1.2.0.tgz#292d0a269f95d04bc6d822c034569bb7e591fb26" + integrity sha512-l0PTqgHeorQdeOizUor6RB49eOAng9+abSxiC5/aHRo6hMmXVaqv5eqndlmxCpx9BkgNb3URQbK+ZZHVktkP/g== + dependencies: + tslib "~2.3.0" + +"@graphql-tools/prisma-loader@^7.0.6": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/prisma-loader/-/prisma-loader-7.1.1.tgz#2a769919c97a3f7f7807668d3155c47999b0965c" + integrity sha512-9hVpG3BNsXAYMLPlZhSHubk6qBmiHLo/UlU0ldL100sMpqI46iBaHNhTNXZCSdd81hT+4HNqaDXNFqyKJ22OGQ== + dependencies: + "@graphql-tools/url-loader" "^7.4.2" + "@graphql-tools/utils" "^8.5.1" + "@types/js-yaml" "^4.0.0" + "@types/json-stable-stringify" "^1.0.32" + "@types/jsonwebtoken" "^8.5.0" + chalk "^4.1.0" + debug "^4.3.1" + dotenv "^10.0.0" + graphql-request "^3.3.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + isomorphic-fetch "^3.0.0" + js-yaml "^4.0.0" + json-stable-stringify "^1.0.1" + jsonwebtoken "^8.5.1" + lodash "^4.17.20" + replaceall "^0.1.6" + scuid "^1.1.0" + tslib "~2.3.0" + yaml-ast-parser "^0.0.43" + +"@graphql-tools/relay-operation-optimizer@^6.3.7": + version "6.4.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-6.4.1.tgz#28572444e2c00850c889a84472f3cc7405dc1ad8" + integrity sha512-2b9D5L+31sIBnvmcmIW5tfvNUV+nJFtbHpUyarTRDmFT6EZ2cXo4WZMm9XJcHQD/Z5qvMXfPHxzQ3/JUs4xI+w== + dependencies: + "@graphql-tools/utils" "^8.5.1" + relay-compiler "12.0.0" + tslib "~2.3.0" + +"@graphql-tools/schema@8.3.1", "@graphql-tools/schema@^8.1.2", "@graphql-tools/schema@^8.3.1": + version "8.3.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-8.3.1.tgz#1ee9da494d2da457643b3c93502b94c3c4b68c74" + integrity sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ== + dependencies: + "@graphql-tools/merge" "^8.2.1" + "@graphql-tools/utils" "^8.5.1" + tslib "~2.3.0" + value-or-promise "1.0.11" + +"@graphql-tools/url-loader@^7.0.11", "@graphql-tools/url-loader@^7.4.2": + version "7.7.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/url-loader/-/url-loader-7.7.1.tgz#2faabdc1d2c47edc8edc9cc938eee2767189869f" + integrity sha512-K/5amdeHtKYI976HVd/AXdSNvLL7vx5QVjMlwN0OHeYyxSgC+UOH+KkS7cshYgL13SekGu0Mxbg9ABfgQ34ECA== + dependencies: + "@graphql-tools/delegate" "^8.4.1" + "@graphql-tools/utils" "^8.5.1" + "@graphql-tools/wrap" "^8.3.1" + "@n1ru4l/graphql-live-query" "^0.9.0" + "@types/websocket" "^1.0.4" + "@types/ws" "^8.0.0" + cross-undici-fetch "^0.1.19" + dset "^3.1.0" + extract-files "^11.0.0" + graphql-sse "^1.0.1" + graphql-ws "^5.4.1" + isomorphic-ws "^4.0.1" + meros "^1.1.4" + subscriptions-transport-ws "^0.11.0" + sync-fetch "^0.3.1" + tslib "^2.3.0" + valid-url "^1.0.9" + value-or-promise "^1.0.11" + ws "^8.3.0" + +"@graphql-tools/utils@8.6.1", "@graphql-tools/utils@^8.1.1", "@graphql-tools/utils@^8.3.0", "@graphql-tools/utils@^8.5.1", "@graphql-tools/utils@^8.5.2", "@graphql-tools/utils@^8.5.3", "@graphql-tools/utils@^8.5.4", "@graphql-tools/utils@^8.6.0": + version "8.6.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.6.1.tgz#52c7eb108f2ca2fd01bdba8eef85077ead1bf882" + integrity sha512-uxcfHCocp4ENoIiovPxUWZEHOnbXqj3ekWc0rm7fUhW93a1xheARNHcNKhwMTR+UKXVJbTFQdGI1Rl5XdyvDBg== + dependencies: + tslib "~2.3.0" + +"@graphql-tools/wrap@^8.3.1": + version "8.3.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-8.3.3.tgz#014aa04a6cf671ffe477516255d1134777da056a" + integrity sha512-TpXN1S4Cv+oMA1Zsg9Nu4N9yrFxLuJkX+CTtSRrrdfETGHIxqfyDkm5slPDCckxP+RILA00g8ny2jzsYyNvX1w== + dependencies: + "@graphql-tools/delegate" "^8.4.2" + "@graphql-tools/schema" "^8.3.1" + "@graphql-tools/utils" "^8.5.3" + tslib "~2.3.0" + value-or-promise "1.0.11" + "@graphql-typed-document-node/core@^3.0.0": version "3.1.1" resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.1.tgz#076d78ce99822258cf813ecc1e7fa460fa74d052" @@ -423,6 +1120,34 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@iarna/toml@^2.2.5": + version "2.2.5" + resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c" + integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg== + +"@jridgewell/resolve-uri@^3.0.3": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" + integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.11" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" + integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== + +"@jridgewell/trace-mapping@^0.3.0": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3" + integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@juggle/resize-observer@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.3.1.tgz#b50a781709c81e10701004214340f25475a171a0" + integrity sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw== + "@monaco-editor/loader@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.2.0.tgz#373fad69973384624e3d9b60eefd786461a76acd" @@ -543,6 +1268,11 @@ prop-types "^15.7.2" react-is "^17.0.2" +"@n1ru4l/graphql-live-query@^0.9.0": + version "0.9.0" + resolved "https://registry.yarnpkg.com/@n1ru4l/graphql-live-query/-/graphql-live-query-0.9.0.tgz#defaebdd31f625bee49e6745934f36312532b2bc" + integrity sha512-BTpWy1e+FxN82RnLz4x1+JcEewVdfmUhV1C6/XYD5AjS7PQp9QFF7K8bCD6gzPTr2l+prvqOyVueQhFJxB1vfg== + "@next/env@12.0.8": version "12.0.8" resolved "https://registry.yarnpkg.com/@next/env/-/env-12.0.8.tgz#a32ca0a97d464307f2e6ff106ce09b19aac108cf" @@ -646,6 +1376,30 @@ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323" integrity sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A== +"@samverschueren/stream-to-observable@^0.3.0": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301" + integrity sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ== + dependencies: + any-observable "^0.3.0" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + "@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" @@ -667,16 +1421,33 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== -"@types/json-schema@*", "@types/json-schema@^7.0.8": +"@types/js-yaml@^4.0.0": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.5.tgz#738dd390a6ecc5442f35e7f03fa1431353f7e138" + integrity sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA== + +"@types/json-schema@*", "@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== +"@types/json-stable-stringify@^1.0.32": + version "1.0.33" + resolved "https://registry.yarnpkg.com/@types/json-stable-stringify/-/json-stable-stringify-1.0.33.tgz#099b0712d824d15e2660c20e1c16e6a8381f308c" + integrity sha512-qEWiQff6q2tA5gcJGWwzplQcXdJtm+0oy6IHGHzlOf3eFAkGE/FIPXZK9ofWgNSHVp8AFFI33PJJshS0ei3Gvw== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= +"@types/jsonwebtoken@^8.5.0": + version "8.5.8" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz#01b39711eb844777b7af1d1f2b4cf22fda1c0c44" + integrity sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A== + dependencies: + "@types/node" "*" + "@types/lodash@^4.14.178": version "4.14.178" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" @@ -725,6 +1496,35 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/websocket@^1.0.4": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/websocket/-/websocket-1.0.5.tgz#3fb80ed8e07f88e51961211cd3682a3a4a81569c" + integrity sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ== + dependencies: + "@types/node" "*" + +"@types/ws@^8.0.0": + version "8.2.2" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" + integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== + dependencies: + "@types/node" "*" + +"@typescript-eslint/eslint-plugin@^5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.12.0.tgz#bb46dd7ce7015c0928b98af1e602118e97df6c70" + integrity sha512-fwCMkDimwHVeIOKeBHiZhRUfJXU8n6xW1FL9diDxAyGAFvKcH4csy0v7twivOQdQdA0KC8TDr7GGRd3L4Lv0rQ== + dependencies: + "@typescript-eslint/scope-manager" "5.12.0" + "@typescript-eslint/type-utils" "5.12.0" + "@typescript-eslint/utils" "5.12.0" + debug "^4.3.2" + functional-red-black-tree "^1.0.1" + ignore "^5.1.8" + regexpp "^3.2.0" + semver "^7.3.5" + tsutils "^3.21.0" + "@typescript-eslint/parser@^5.0.0": version "5.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.1.tgz#4ce9633cc33fc70bc13786cb793c1a76fe5ad6bd" @@ -735,6 +1535,16 @@ "@typescript-eslint/typescript-estree" "5.10.1" debug "^4.3.2" +"@typescript-eslint/parser@^5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.12.0.tgz#0ca669861813df99ce54916f66f524c625ed2434" + integrity sha512-MfSwg9JMBojMUoGjUmX+D2stoQj1CBYTCP0qnnVtu9A+YQXVKNtLjasYh+jozOcrb/wau8TCfWOkQTiOAruBog== + dependencies: + "@typescript-eslint/scope-manager" "5.12.0" + "@typescript-eslint/types" "5.12.0" + "@typescript-eslint/typescript-estree" "5.12.0" + debug "^4.3.2" + "@typescript-eslint/scope-manager@5.10.1": version "5.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.10.1.tgz#f0539c73804d2423506db2475352a4dec36cd809" @@ -743,11 +1553,33 @@ "@typescript-eslint/types" "5.10.1" "@typescript-eslint/visitor-keys" "5.10.1" +"@typescript-eslint/scope-manager@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.12.0.tgz#59619e6e5e2b1ce6cb3948b56014d3a24da83f5e" + integrity sha512-GAMobtIJI8FGf1sLlUWNUm2IOkIjvn7laFWyRx7CLrv6nLBI7su+B7lbStqVlK5NdLvHRFiJo2HhiDF7Ki01WQ== + dependencies: + "@typescript-eslint/types" "5.12.0" + "@typescript-eslint/visitor-keys" "5.12.0" + +"@typescript-eslint/type-utils@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.12.0.tgz#aaf45765de71c6d9707c66ccff76ec2b9aa31bb6" + integrity sha512-9j9rli3zEBV+ae7rlbBOotJcI6zfc6SHFMdKI9M3Nc0sy458LJ79Os+TPWeBBL96J9/e36rdJOfCuyRSgFAA0Q== + dependencies: + "@typescript-eslint/utils" "5.12.0" + debug "^4.3.2" + tsutils "^3.21.0" + "@typescript-eslint/types@5.10.1": version "5.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.1.tgz#dca9bd4cb8c067fc85304a31f38ec4766ba2d1ea" integrity sha512-ZvxQ2QMy49bIIBpTqFiOenucqUyjTQ0WNLhBM6X1fh1NNlYAC6Kxsx8bRTY3jdYsYg44a0Z/uEgQkohbR0H87Q== +"@typescript-eslint/types@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.12.0.tgz#5b4030a28222ee01e851836562c07769eecda0b8" + integrity sha512-JowqbwPf93nvf8fZn5XrPGFBdIK8+yx5UEGs2QFAYFI8IWYfrzz+6zqlurGr2ctShMaJxqwsqmra3WXWjH1nRQ== + "@typescript-eslint/typescript-estree@5.10.1": version "5.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.1.tgz#b268e67be0553f8790ba3fe87113282977adda15" @@ -761,6 +1593,31 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.12.0.tgz#cabf545fd592722f0e2b4104711e63bf89525cd2" + integrity sha512-Dd9gVeOqt38QHR0BEA8oRaT65WYqPYbIc5tRFQPkfLquVEFPD1HAtbZT98TLBkEcCkvwDYOAvuSvAD9DnQhMfQ== + dependencies: + "@typescript-eslint/types" "5.12.0" + "@typescript-eslint/visitor-keys" "5.12.0" + debug "^4.3.2" + globby "^11.0.4" + is-glob "^4.0.3" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.12.0.tgz#92fd3193191621ab863add2f553a7b38b65646af" + integrity sha512-k4J2WovnMPGI4PzKgDtQdNrCnmBHpMUFy21qjX2CoPdoBcSBIMvVBr9P2YDP8jOqZOeK3ThOL6VO/sy6jtnvzw== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.12.0" + "@typescript-eslint/types" "5.12.0" + "@typescript-eslint/typescript-estree" "5.12.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + "@typescript-eslint/visitor-keys@5.10.1": version "5.10.1" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.1.tgz#29102de692f59d7d34ecc457ed59ab5fc558010b" @@ -769,6 +1626,14 @@ "@typescript-eslint/types" "5.10.1" eslint-visitor-keys "^3.0.0" +"@typescript-eslint/visitor-keys@5.12.0": + version "5.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.12.0.tgz#1ac9352ed140b07ba144ebf371b743fdf537ec16" + integrity sha512-cFwTlgnMV6TgezQynx2c/4/tx9Tufbuo9LPzmWqyRC3QC4qTGkAG1C6pBr0/4I10PAI/FlYunI3vJjIcu+ZHMg== + dependencies: + "@typescript-eslint/types" "5.12.0" + eslint-visitor-keys "^3.0.0" + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -921,6 +1786,13 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + 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" @@ -936,6 +1808,13 @@ acorn@^8.4.1, acorn@^8.7.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" @@ -951,11 +1830,49 @@ ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +allotment@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/allotment/-/allotment-1.9.0.tgz#4e0809c164f4f705e90b4bc83a4172e51443f5db" + integrity sha512-C7D7IpQuIEqtRrnWnIIFVO7amOWIk6v2x6YRy8pXUYVIB38ANjaPaKRvMkDRGMW7b66vBrPYNBMC4u4f9woxRQ== + dependencies: + classnames "^2.3.0" + eventemitter3 "^4.0.0" + lodash.clamp "^4.0.0" + lodash.debounce "^4.0.0" + use-resize-observer "^8.0.0" + +ansi-escapes@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + +ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -963,13 +1880,31 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" +any-observable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" + integrity sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog== + +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -1017,11 +1952,26 @@ array.prototype.flatmap@^1.2.5: define-properties "^1.1.3" es-abstract "^1.19.0" +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + ast-types-flow@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +auto-bind@~4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" + integrity sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ== + axe-core@^4.3.5: version "4.3.5" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.5.tgz#78d6911ba317a8262bfee292aeafcc1e04b49cc5" @@ -1032,6 +1982,13 @@ axobject-query@^2.2.0: resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + babel-plugin-macros@^2.6.1: version "2.8.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" @@ -1041,16 +1998,78 @@ babel-plugin-macros@^2.6.1: cosmiconfig "^6.0.0" resolve "^1.12.0" +babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: + version "7.0.0-beta.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" + integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== + +babel-preset-fbjs@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz#38a14e5a7a3b285a3f3a86552d650dca5cf6111c" + integrity sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow== + dependencies: + "@babel/plugin-proposal-class-properties" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/plugin-syntax-class-properties" "^7.0.0" + "@babel/plugin-syntax-flow" "^7.0.0" + "@babel/plugin-syntax-jsx" "^7.0.0" + "@babel/plugin-syntax-object-rest-spread" "^7.0.0" + "@babel/plugin-transform-arrow-functions" "^7.0.0" + "@babel/plugin-transform-block-scoped-functions" "^7.0.0" + "@babel/plugin-transform-block-scoping" "^7.0.0" + "@babel/plugin-transform-classes" "^7.0.0" + "@babel/plugin-transform-computed-properties" "^7.0.0" + "@babel/plugin-transform-destructuring" "^7.0.0" + "@babel/plugin-transform-flow-strip-types" "^7.0.0" + "@babel/plugin-transform-for-of" "^7.0.0" + "@babel/plugin-transform-function-name" "^7.0.0" + "@babel/plugin-transform-literals" "^7.0.0" + "@babel/plugin-transform-member-expression-literals" "^7.0.0" + "@babel/plugin-transform-modules-commonjs" "^7.0.0" + "@babel/plugin-transform-object-super" "^7.0.0" + "@babel/plugin-transform-parameters" "^7.0.0" + "@babel/plugin-transform-property-literals" "^7.0.0" + "@babel/plugin-transform-react-display-name" "^7.0.0" + "@babel/plugin-transform-react-jsx" "^7.0.0" + "@babel/plugin-transform-shorthand-properties" "^7.0.0" + "@babel/plugin-transform-spread" "^7.0.0" + "@babel/plugin-transform-template-literals" "^7.0.0" + babel-plugin-syntax-trailing-function-commas "^7.0.0-beta.0" + +backo2@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bl@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1059,7 +2078,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1: +braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1077,6 +2096,18 @@ browserslist@^4.14.5, browserslist@^4.17.5: node-releases "^2.0.1" picocolors "^1.0.0" +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -1087,6 +2118,27 @@ buffer-from@~0.1.1: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0" integrity sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg== +buffer@^5.5.0, buffer@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" @@ -1100,12 +2152,45 @@ 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.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a" + integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw== + dependencies: + pascal-case "^3.1.2" + tslib "^2.0.3" + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001286: version "1.0.30001302" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001302.tgz#da57ce61c51177ef3661eeed7faef392d3790aaa" integrity sha512-YYTMO+tfwvgUN+1ZnRViE53Ma1S/oETg+J2lISsqi/ZTNThj3ZYBOKP2rHwJc37oCsPqAzJ3w2puZHn0xlLPPw== -chalk@^2.0.0: +capital-case@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669" + integrity sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case-first "^2.0.2" + +chalk@^1.0.0, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1114,7 +2199,7 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1122,16 +2207,142 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +change-case-all@1.0.14: + version "1.0.14" + resolved "https://registry.yarnpkg.com/change-case-all/-/change-case-all-1.0.14.tgz#bac04da08ad143278d0ac3dda7eccd39280bfba1" + integrity sha512-CWVm2uT7dmSHdO/z1CXT/n47mWonyypzBbuCy5tN7uMg22BsfkhwT6oHmFCAk+gL1LOOxhdbB9SZz3J1KTY3gA== + dependencies: + change-case "^4.1.2" + is-lower-case "^2.0.2" + is-upper-case "^2.0.2" + lower-case "^2.0.2" + lower-case-first "^2.0.2" + sponge-case "^1.0.1" + swap-case "^2.0.2" + title-case "^3.0.3" + upper-case "^2.0.2" + upper-case-first "^2.0.2" + +change-case@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" + integrity sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A== + dependencies: + camel-case "^4.1.2" + capital-case "^1.0.4" + constant-case "^3.0.4" + dot-case "^3.0.4" + header-case "^2.0.4" + no-case "^3.0.4" + param-case "^3.0.4" + pascal-case "^3.1.2" + path-case "^3.0.4" + sentence-case "^3.0.4" + snake-case "^3.0.4" + tslib "^2.0.3" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chrome-trace-event@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== +classnames@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" + integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== + +cli-cursor@^2.0.0, cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" + integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== + +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + integrity sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ= + dependencies: + slice-ansi "0.0.4" + string-width "^1.0.1" + +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + clsx@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -1161,16 +2372,37 @@ colorette@^1.2.2: resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +common-tags@1.8.2, common-tags@^1.8.0: + version "1.8.2" + resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" + integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +constant-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-3.0.4.tgz#3b84a9aeaf4cf31ec45e6bf5de91bdfb0589faf1" + integrity sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case "^2.0.2" + convert-source-map@1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" @@ -1195,6 +2427,24 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +cosmiconfig-toml-loader@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig-toml-loader/-/cosmiconfig-toml-loader-1.0.0.tgz#0681383651cceff918177debe9084c0d3769509b" + integrity sha512-H/2gurFWVi7xXvCyvsWRLCMekl4tITJcX0QEsDMpzxtuxDyM59xLatYNg4s/k9AA/HdtCYfj2su8mgA0GSDLDA== + dependencies: + "@iarna/toml" "^2.2.5" + +cosmiconfig@7.0.1, cosmiconfig@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" + integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -1206,6 +2456,18 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@^3.0.6, cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== + dependencies: + node-fetch "2.6.7" + cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -1215,6 +2477,18 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +cross-undici-fetch@^0.1.19: + version "0.1.24" + resolved "https://registry.yarnpkg.com/cross-undici-fetch/-/cross-undici-fetch-0.1.24.tgz#2ad23d096ba07cfa1260b1aeb9a78d2132ea3385" + integrity sha512-83KDV6+8pYCn51zSM2cFAwqQ5UQtDaPm89RkUwHxEMDq/cdqYgqo1q+2eM/Xhmd8HeAsGTtecsC4crrQkCn0zg== + dependencies: + abort-controller "^3.0.0" + form-data-encoder "^1.7.1" + formdata-node "^4.3.1" + node-fetch "^2.6.7" + undici "^4.9.3" + web-streams-polyfill "^3.2.0" + csstype@^3.0.10, csstype@^3.0.2: version "3.0.10" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" @@ -1225,6 +2499,28 @@ damerau-levenshtein@^1.0.7: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA== +dataloader@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.0.0.tgz#41eaf123db115987e21ca93c005cd7753c55fe6f" + integrity sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ== + +date-fns@^1.27.2: + version "1.30.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" + integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== + +debounce@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" + integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== + +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -1239,12 +2535,22 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: - version "4.3.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" - integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= dependencies: - ms "2.1.2" + mimic-response "^1.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@^0.1.3: version "0.1.4" @@ -1256,6 +2562,18 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -1263,6 +2581,26 @@ define-properties@^1.1.3: dependencies: object-keys "^1.0.12" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +dependency-graph@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.11.0.tgz#ac0ce7ed68a54da22165a85e97a01d53f5eb2e27" + integrity sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg== + +detect-indent@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" + integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -1292,6 +2630,24 @@ dom-helpers@^5.0.1: "@babel/runtime" "^7.8.7" csstype "^3.0.2" +dot-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" + integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +dotenv@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" + integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== + +dset@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.1.tgz#07de5af7a8d03eab337ad1a8ba77fe17bba61a8c" + integrity sha512-hYf+jZNNqJBD2GiMYb+5mqOIX4R4RRHXU3qWMWYN+rqcR2/YpRL2bUHr8C8fU+5DNvqYjJ8YvMGSLuVPWU1cNg== + duplexer2@^0.1.2: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" @@ -1299,11 +2655,33 @@ duplexer2@^0.1.2: dependencies: readable-stream "^2.0.2" +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + electron-to-chromium@^1.4.17: version "1.4.53" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.53.tgz#5d80a91c399b44952ef485857fb5b9d4387d2e60" integrity sha512-rFveSKQczlcav+H3zkKqykU6ANseFwXwkl855jOIap5/0gnEcuIhv2ecz6aoTrXavF6I/CEBeRnBnkB51k06ew== +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" + integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + emoji-regex@^9.2.2: version "9.2.2" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" @@ -1319,6 +2697,13 @@ emojis-list@^3.0.0: resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + enhanced-resolve@^5.8.3: version "5.8.3" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" @@ -1379,7 +2764,7 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -1505,7 +2890,19 @@ eslint-plugin-react@^7.27.0: semver "^6.3.0" string.prototype.matchall "^4.0.6" -eslint-scope@5.1.1: +eslint-plugin-unused-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz#d8db8c4d0cfa0637a8b51ce3fd7d1b6bc3f08520" + integrity sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A== + dependencies: + eslint-rule-composer "^0.3.0" + +eslint-rule-composer@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" + integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== + +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== @@ -1617,11 +3014,45 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter3@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" + integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + 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== +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extract-files@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-11.0.0.tgz#b72d428712f787eef1f5193aff8ab5351ca8469a" + integrity sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ== + +extract-files@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/extract-files/-/extract-files-9.0.0.tgz#8a7744f2437f81f5ed3250ed9f1550de902fe54a" + integrity sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1660,6 +3091,53 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + +fbjs-css-vars@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" + integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== + +fbjs@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" + integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== + dependencies: + cross-fetch "^3.1.5" + fbjs-css-vars "^1.0.0" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.30" + +figures@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -1694,6 +3172,14 @@ find-up@^2.1.0: dependencies: locate-path "^2.0.0" +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -1707,11 +3193,38 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.4.tgz#28d9969ea90661b5134259f312ab6aa7929ac5e2" integrity sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw== +form-data-encoder@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.1.tgz#ac80660e4f87ee0d3d3c3638b7da8278ddb8ec96" + integrity sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg== + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +formdata-node@^4.3.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.3.2.tgz#0262e94931e36db7239c2b08bdb6aaf18ec47d21" + integrity sha512-k7lYJyzDOSL6h917favP8j1L0/wNyylzU+x+1w4p5haGVHNlP58dbpdJhiCUsDbWsa9HwEtLp89obQgXl2e0qg== + dependencies: + node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.1" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -1727,6 +3240,11 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" @@ -1736,6 +3254,20 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -1744,7 +3276,7 @@ get-symbol-description@^1.0.0: call-bind "^1.0.2" get-intrinsic "^1.1.1" -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -1775,7 +3307,7 @@ glob@7.1.7: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.3, glob@^7.1.7: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.6, glob@^7.1.7: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -1799,7 +3331,7 @@ globals@^13.6.0, globals@^13.9.0: dependencies: type-fest "^0.20.2" -globby@^11.0.4: +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== @@ -1811,23 +3343,83 @@ globby@^11.0.4: merge2 "^1.4.1" slash "^3.0.0" +got@^9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + graceful-fs@^4.1.2, graceful-fs@^4.2.4, 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== -graphql-tag@^2.12.3: +graphql-config@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/graphql-config/-/graphql-config-4.1.0.tgz#a3b28d3fb537952ebeb69c75e4430605a10695e3" + integrity sha512-Myqay6pmdcmX3KqoH+bMbeKZ1cTODpHS2CxF1ZzNnfTE+YUpGTcp01bOw6LpzamRb0T/WTYtGFbZeXGo9Hab2Q== + dependencies: + "@endemolshinegroup/cosmiconfig-typescript-loader" "3.0.2" + "@graphql-tools/graphql-file-loader" "^7.3.2" + "@graphql-tools/json-file-loader" "^7.3.2" + "@graphql-tools/load" "^7.4.1" + "@graphql-tools/merge" "^8.2.1" + "@graphql-tools/url-loader" "^7.4.2" + "@graphql-tools/utils" "^8.5.1" + cosmiconfig "7.0.1" + cosmiconfig-toml-loader "1.0.0" + minimatch "3.0.4" + string-env-interpolation "1.0.1" + +graphql-request@^3.3.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-3.7.0.tgz#c7406e537084f8b9788541e3e6704340ca13055b" + integrity sha512-dw5PxHCgBneN2DDNqpWu8QkbbJ07oOziy8z+bK/TAXufsOLaETuVO4GkXrbs0WjhdKhBMN3BkpN/RIvUHkmNUQ== + dependencies: + cross-fetch "^3.0.6" + extract-files "^9.0.0" + form-data "^3.0.0" + +graphql-sse@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/graphql-sse/-/graphql-sse-1.0.6.tgz#4f98e0a06f2020542ed054399116108491263224" + integrity sha512-y2mVBN2KwNrzxX2KBncQ6kzc6JWvecxuBernrl0j65hsr6MAS3+Yn8PTFSOgRmtolxugepxveyZVQEuaNEbw3w== + +graphql-tag@^2.11.0, graphql-tag@^2.12.3: version "2.12.6" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== dependencies: tslib "^2.1.0" +graphql-ws@^5.4.1: + version "5.5.5" + resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.5.5.tgz#f375486d3f196e2a2527b503644693ae3a8670a9" + integrity sha512-hvyIS71vs4Tu/yUYHPvGXsTgo0t3arU820+lT5VjZS2go0ewp2LqyCgxEN56CzOG7Iys52eRhHBiD1gGRdiQtw== + graphql@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.2.0.tgz#de3150e80f1fc009590b92a9d16ab1b46e12b656" integrity sha512-MuQd7XXrdOcmfwuLwC2jNvx0n3rxIuNYOxUtiee5XOmfrWo613ar2U8pE7aHAKh8VwfpifubpD9IP+EdEAEOsA== +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + has-bigints@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" @@ -1862,6 +3454,14 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +header-case@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.4.tgz#5a42e63b55177349cf405beb8d775acabb92c063" + integrity sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q== + dependencies: + capital-case "^1.0.4" + tslib "^2.0.3" + hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -1880,16 +3480,55 @@ html-tokenize@^2.0.0: readable-stream "~1.0.27-1" through2 "~0.4.1" +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore@^4.0.6: version "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.2.0: +ignore@^5.1.8, 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== +immutable@~3.7.6: + version "3.7.6" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b" + integrity sha1-E7TTyxK++hVIKib+Gy665kAHHks= + import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -1898,11 +3537,21 @@ import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-from@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-4.0.0.tgz#2710b8d66817d232e16f4166e319248d3d5492e2" + integrity sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ== + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1911,11 +3560,36 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +inquirer@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.0.tgz#f44f008dd344bbfc4b30031f45d984e034a3ac3a" + integrity sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ== + 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.2.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -1925,6 +3599,21 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -1937,6 +3626,13 @@ is-bigint@^1.0.1: dependencies: has-bigints "^1.0.1" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-boolean-object@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" @@ -1969,13 +3665,42 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@4.0.3, is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-lower-case/-/is-lower-case-2.0.2.tgz#1c0884d3012c841556243483aa5d522f47396d2a" + integrity sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ== + dependencies: + tslib "^2.0.3" + is-negative-zero@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -1993,6 +3718,18 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-observable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e" + integrity sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA== + dependencies: + symbol-observable "^1.1.0" + +is-promise@^2.1.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -2001,11 +3738,23 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + is-shared-array-buffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -2020,6 +3769,25 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-upper-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-2.0.2.tgz#f1105ced1fe4de906a5f39553e7d3803fd804649" + integrity sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ== + dependencies: + tslib "^2.0.3" + is-weakref@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" @@ -2027,6 +3795,11 @@ is-weakref@^1.0.1: dependencies: call-bind "^1.0.2" +is-windows@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -2042,6 +3815,24 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= +isomorphic-fetch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" + integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== + dependencies: + node-fetch "^2.6.1" + whatwg-fetch "^3.4.1" + +isomorphic-ws@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#55fd4cd6c5e6491e76dc125938dd863f5cd4f2dc" + integrity sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w== + +iterall@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" + integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== + jest-worker@27.0.0-next.5: version "27.0.0-next.5" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.0-next.5.tgz#5985ee29b12a4e191f4aae4bb73b97971d86ec28" @@ -2065,7 +3856,7 @@ jest-worker@^27.4.1: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^4.1.0: +js-yaml@^4.0.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -2077,6 +3868,11 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -2097,6 +3893,21 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + +json-to-pretty-yaml@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz#f4cd0bd0a5e8fe1df25aaf5ba118b099fd992d5b" + integrity sha1-9M0L0KXo/h3yWq9boRiwmf2ZLVs= + dependencies: + remedial "^1.0.7" + remove-trailing-spaces "^1.0.6" + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -2111,6 +3922,27 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsonwebtoken@^8.5.1: + version "8.5.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" + integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^5.6.0" + "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b" @@ -2119,6 +3951,30 @@ json5@^2.1.2: array-includes "^3.1.3" object.assign "^4.1.2" +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + language-subtag-registry@~0.3.2: version "0.3.21" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" @@ -2131,6 +3987,13 @@ language-tags@^1.0.5: dependencies: language-subtag-registry "~0.3.2" +latest-version@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" + integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== + dependencies: + package-json "^6.3.0" + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -2144,6 +4007,50 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4= + +listr-update-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" + integrity sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA== + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^2.3.0" + strip-ansi "^3.0.1" + +listr-verbose-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" + integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== + dependencies: + chalk "^2.4.1" + cli-cursor "^2.1.0" + date-fns "^1.27.2" + figures "^2.0.0" + +listr@^0.14.3: + version "0.14.3" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" + integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== + dependencies: + "@samverschueren/stream-to-observable" "^0.3.0" + is-observable "^1.1.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.5.0" + listr-verbose-renderer "^0.5.0" + p-map "^2.0.0" + rxjs "^6.3.3" + loader-runner@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" @@ -2175,23 +4082,128 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash.clamp@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lodash.clamp/-/lodash.clamp-4.0.3.tgz#5c24bedeeeef0753560dc2b4cb4671f90a6ddfaa" + integrity sha1-XCS+3u7vB1NWDcK0y0Zx+Qpt36o= + +lodash.debounce@^4.0.0: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + +lodash.get@^4: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.21: +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + +lodash@^4.17.20, lodash@^4.17.21, lodash@~4.17.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -loose-envify@^1.1.0, loose-envify@^1.4.0: +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg= + dependencies: + chalk "^1.0.0" + +log-symbols@^4.0.0, log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +log-update@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" + integrity sha1-iDKP19HOeTiykoN0bwsbwSayRwg= + dependencies: + ansi-escapes "^3.0.0" + cli-cursor "^2.0.0" + wrap-ansi "^3.0.1" + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" +lower-case-first@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-2.0.2.tgz#64c2324a2250bf7c37c5901e76a5b5309301160b" + integrity sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg== + dependencies: + tslib "^2.0.3" + +lower-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" + integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg== + dependencies: + tslib "^2.0.3" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -2199,6 +4211,16 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +make-error@^1, make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +map-cache@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -2209,6 +4231,11 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +meros@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/meros/-/meros-1.1.4.tgz#c17994d3133db8b23807f62bec7f0cb276cfd948" + integrity sha512-E9ZXfK9iQfG9s73ars9qvvvbSIkJZF5yOo9j4tcwM5tN8mUKfj/EKN5PzOr3ZH0y5wL7dLAHw3RVEfpQV9Q7VQ== + micromatch@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" @@ -2222,14 +4249,29 @@ mime-db@1.51.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== -mime-types@^2.1.27: +mime-types@^2.1.12, mime-types@^2.1.27: 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== dependencies: mime-db "1.51.0" -minimatch@^3.0.4: +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -2241,6 +4283,11 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + monaco-editor@^0.31.1: version "0.31.1" resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.31.1.tgz#67f597b3e45679d1f551237e12a3a42c4438b97b" @@ -2269,6 +4316,11 @@ multipipe@^1.0.2: duplexer2 "^0.1.2" object-assign "^4.1.0" +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + nanoid@^3.1.23: version "3.2.0" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" @@ -2321,16 +4373,68 @@ next@^12.0.8: "@next/swc-win32-ia32-msvc" "12.0.8" "@next/swc-win32-x64-msvc" "12.0.8" +no-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d" + integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg== + dependencies: + lower-case "^2.0.2" + tslib "^2.0.3" + +node-domexception@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-fetch@2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== +node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + node-releases@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +nullthrows@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -2351,7 +4455,7 @@ object-keys@~0.4.0: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= -object.assign@^4.1.2: +object.assign@^4.1.0, object.assign@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== @@ -2396,13 +4500,27 @@ object.values@^1.1.5: define-properties "^1.1.3" es-abstract "^1.19.1" -once@^1.3.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + optimism@^0.16.1: version "0.16.1" resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.16.1.tgz#7c8efc1f3179f18307b887e18c15c5b7133f6e7d" @@ -2423,6 +4541,38 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-limit@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -2430,6 +4580,13 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -2437,11 +4594,46 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + p-try@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json@^6.3.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" + integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== + dependencies: + got "^9.6.0" + registry-auth-token "^4.0.0" + registry-url "^5.0.0" + semver "^6.2.0" + +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== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2449,6 +4641,15 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-filepath@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" + integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= + dependencies: + is-absolute "^1.0.0" + map-cache "^0.2.0" + path-root "^0.1.1" + parse-json@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -2459,11 +4660,32 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +pascal-case@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb" + integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + +path-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.4.tgz#9168645334eb942658375c56f80b4c0cb5f82c6f" + integrity sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -2479,6 +4701,18 @@ path-parse@^1.0.6, path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= + dependencies: + path-root-regex "^0.1.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -2489,7 +4723,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -2508,6 +4742,11 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + prettier-linter-helpers@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" @@ -2525,6 +4764,13 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== + dependencies: + asap "~2.0.3" + prop-types@^15.6.2, prop-types@^15.7.2: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -2534,6 +4780,14 @@ prop-types@^15.6.2, prop-types@^15.7.2: object-assign "^4.1.1" react-is "^16.13.1" +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -2551,6 +4805,16 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" +rc@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-dom@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" @@ -2606,7 +4870,7 @@ readable-stream@^2.0.2: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.5.0: +readable-stream@^3.4.0, readable-stream@^3.5.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== @@ -2625,6 +4889,13 @@ readable-stream@~1.0.17, readable-stream@~1.0.27-1: isarray "0.0.1" string_decoder "~0.10.x" +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + regenerator-runtime@^0.13.4: version "0.13.9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" @@ -2643,6 +4914,87 @@ regexpp@^3.2.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== +registry-auth-token@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" + integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + dependencies: + rc "^1.2.8" + +registry-url@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" + integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== + dependencies: + rc "^1.2.8" + +relay-compiler@12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/relay-compiler/-/relay-compiler-12.0.0.tgz#9f292d483fb871976018704138423a96c8a45439" + integrity sha512-SWqeSQZ+AMU/Cr7iZsHi1e78Z7oh00I5SvR092iCJq79aupqJ6Ds+I1Pz/Vzo5uY5PY0jvC4rBJXzlIN5g9boQ== + dependencies: + "@babel/core" "^7.14.0" + "@babel/generator" "^7.14.0" + "@babel/parser" "^7.14.0" + "@babel/runtime" "^7.0.0" + "@babel/traverse" "^7.14.0" + "@babel/types" "^7.0.0" + babel-preset-fbjs "^3.4.0" + chalk "^4.0.0" + fb-watchman "^2.0.0" + fbjs "^3.0.0" + glob "^7.1.1" + immutable "~3.7.6" + invariant "^2.2.4" + nullthrows "^1.1.1" + relay-runtime "12.0.0" + signedsource "^1.0.0" + yargs "^15.3.1" + +relay-runtime@12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/relay-runtime/-/relay-runtime-12.0.0.tgz#1e039282bdb5e0c1b9a7dc7f6b9a09d4f4ff8237" + integrity sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug== + dependencies: + "@babel/runtime" "^7.0.0" + fbjs "^3.0.0" + invariant "^2.2.4" + +remedial@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/remedial/-/remedial-1.0.8.tgz#a5e4fd52a0e4956adbaf62da63a5a46a78c578a0" + integrity sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg== + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +remove-trailing-spaces@^1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz#4354d22f3236374702f58ee373168f6d6887ada7" + integrity sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA== + +replaceall@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/replaceall/-/replaceall-0.1.6.tgz#81d81ac7aeb72d7f5c4942adf2697a3220688d8e" + integrity sha1-gdgax663LX9cSUKt8ml6MiBojY4= + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-from@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -2665,6 +5017,29 @@ resolve@^2.0.0-next.3: is-core-module "^2.2.0" path-parse "^1.0.6" +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -2682,6 +5057,11 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -2689,7 +5069,21 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.1.0, safe-buffer@~5.2.0: +rxjs@^6.3.3: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + +rxjs@^7.2.0: + version "7.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.4.tgz#3d6bd407e6b7ce9a123e76b1e770dc5761aa368d" + integrity sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ== + dependencies: + tslib "^2.1.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.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== @@ -2699,6 +5093,11 @@ 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== +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + scheduler@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" @@ -2716,7 +5115,17 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" -semver@^6.3.0: +scuid@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/scuid/-/scuid-1.1.0.tgz#d3f9f920956e737a60f72d0e4ad280bf324d5dab" + integrity sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg== + +semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -2728,6 +5137,15 @@ semver@^7.3.5: dependencies: lru-cache "^6.0.0" +sentence-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-3.0.4.tgz#3645a7b8c117c787fde8702056225bb62a45131f" + integrity sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg== + dependencies: + no-case "^3.0.4" + tslib "^2.0.3" + upper-case-first "^2.0.2" + serialize-javascript@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -2735,6 +5153,16 @@ serialize-javascript@^6.0.0: dependencies: randombytes "^2.1.0" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -2756,12 +5184,35 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signedsource@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/signedsource/-/signedsource-1.0.0.tgz#1ddace4981798f93bd833973803d80d52e93ad6a" + integrity sha1-HdrOSYF5j5O9gzlzgD2A1S6TrWo= + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -source-map-support@~0.5.20: +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= + +snake-case@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.4.tgz#4f2bbd568e9935abdfd593f34c691dadb49c452c" + integrity sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg== + dependencies: + dot-case "^3.0.4" + tslib "^2.0.3" + +source-map-support@^0.5.17, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -2784,6 +5235,13 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +sponge-case@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sponge-case/-/sponge-case-1.0.1.tgz#260833b86453883d974f84854cdb63aecc5aef4c" + integrity sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA== + dependencies: + tslib "^2.0.3" + state-local@^1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/state-local/-/state-local-1.0.7.tgz#da50211d07f05748d53009bee46307a37db386d5" @@ -2797,11 +5255,42 @@ stream-browserify@3.0.0: inherits "~2.0.4" readable-stream "^3.5.0" +string-env-interpolation@1.0.1, string-env-interpolation@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz#ad4397ae4ac53fe6c91d1402ad6f6a52862c7152" + integrity sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg== + string-hash@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs= +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string.prototype.matchall@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa" @@ -2851,7 +5340,21 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^6.0.1: +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -2868,6 +5371,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + styled-jsx@5.0.0-beta.6: version "5.0.0-beta.6" resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0-beta.6.tgz#666552f8831a06f80c9084a47afc4b32b0c9f461" @@ -2897,6 +5405,22 @@ stylis@4.0.13: resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== +subscriptions-transport-ws@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/subscriptions-transport-ws/-/subscriptions-transport-ws-0.11.0.tgz#baf88f050cba51d52afe781de5e81b3c31f89883" + integrity sha512-8D4C6DIH5tGiAIpp5I0wD/xRlNiZAPGHygzCe7VzyzUoxHtawzjNAY9SUTXU05/EY2NMY9/9GF0ycizkXr1CWQ== + dependencies: + backo2 "^1.0.2" + eventemitter3 "^3.1.0" + iterall "^1.2.1" + symbol-observable "^1.0.4" + ws "^5.2.0 || ^6.0.0 || ^7.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -2923,11 +5447,31 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +swap-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-2.0.2.tgz#671aedb3c9c137e2985ef51c51f9e98445bf70d9" + integrity sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw== + dependencies: + tslib "^2.0.3" + +symbol-observable@^1.0.4, symbol-observable@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== + symbol-observable@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-4.0.0.tgz#5b425f192279e87f2f9b937ac8540d1984b39205" integrity sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ== +sync-fetch@0.3.1, sync-fetch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/sync-fetch/-/sync-fetch-0.3.1.tgz#62aa82c4b4d43afd6906bfd7b5f92056458509f0" + integrity sha512-xj5qiCDap/03kpci5a+qc5wSJjc8ZSixgG2EUmH1B8Ea2sfWclQA7eH40hiHPCtkCn6MCk4Wb+dqcXdCy2PP3g== + dependencies: + buffer "^5.7.0" + node-fetch "^2.6.1" + tapable@^2.1.1, tapable@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" @@ -2966,16 +5510,35 @@ through2@~0.4.1: readable-stream "~1.0.17" xtend "~2.1.1" -through@^2.3.8: +through@^2.3.6, through@^2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= +title-case@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982" + integrity sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA== + dependencies: + tslib "^2.0.3" + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -2983,6 +5546,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + ts-invariant@^0.9.4: version "0.9.4" resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.9.4.tgz#42ac6c791aade267dd9dc65276549df5c5d71cac" @@ -2990,6 +5558,23 @@ ts-invariant@^0.9.4: dependencies: tslib "^2.1.0" +ts-log@^2.2.3: + version "2.2.4" + resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.2.4.tgz#d672cf904b33735eaba67a7395c93d45fba475b3" + integrity sha512-DEQrfv6l7IvN2jlzc/VTdZJYsWUnQNCsueYjMkC/iXoEoi5fNan6MjeDqkvhfzbmHgdz9UxDUluX3V5HdjTydQ== + +ts-node@^9: + version "9.1.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" + integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== + dependencies: + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + tsconfig-paths@^3.12.0, tsconfig-paths@^3.9.0: version "3.12.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b" @@ -3000,12 +5585,12 @@ tsconfig-paths@^3.12.0, tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.8.1: +tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0, tslib@^2.3.0: +tslib@^2, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@~2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== @@ -3029,11 +5614,21 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + typescript@^4.0.3: version "4.5.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== +ua-parser-js@^0.7.30: + version "0.7.31" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6" + integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ== + unbox-primitive@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" @@ -3044,6 +5639,37 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + +undici@^4.9.3: + version "4.14.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-4.14.1.tgz#7633b143a8a10d6d63335e00511d071e8d52a1d9" + integrity sha512-WJ+g+XqiZcATcBaUeluCajqy4pEDcQfK1vy+Fo+bC4/mqXI9IIQD/XWHLS70fkGUT6P52Drm7IFslO651OdLPQ== + +unixify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090" + integrity sha1-OmQcjC/7zk2mg6XHDwOkYpQMIJA= + dependencies: + normalize-path "^2.1.1" + +upper-case-first@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-2.0.2.tgz#992c3273f882abd19d1e02894cc147117f844324" + integrity sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg== + dependencies: + tslib "^2.0.3" + +upper-case@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-2.0.2.tgz#d89810823faab1df1549b7d97a76f8662bae6f7a" + integrity sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg== + dependencies: + tslib "^2.0.3" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -3060,6 +5686,20 @@ url-loader@^4.0.0: mime-types "^2.1.27" schema-utils "^3.0.0" +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +use-resize-observer@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/use-resize-observer/-/use-resize-observer-8.0.0.tgz#69bd80c1ddd94f3758563fe107efb25fed85067a" + integrity sha512-n0iKSeiQpJCyaFh5JA0qsVLBIovsF4EIIR1G6XiBwKJN66ZrD4Oj62bjcuTAATPKiSp6an/2UZZxCf/67fk3sQ== + dependencies: + "@juggle/resize-observer" "^3.3.1" + use-subscription@1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1" @@ -3077,6 +5717,16 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== +valid-url@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" + integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA= + +value-or-promise@1.0.11, value-or-promise@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.11.tgz#3e90299af31dd014fe843fe309cefa7c1d94b140" + integrity sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg== + watchpack@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.3.1.tgz#4200d9447b401156eeca7767ee610f8809bc9d25" @@ -3085,6 +5735,28 @@ watchpack@^2.3.1: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + +web-streams-polyfill@4.0.0-beta.1: + version "4.0.0-beta.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.1.tgz#3b19b9817374b7cee06d374ba7eeb3aeb80e8c95" + integrity sha512-3ux37gEX670UUphBF9AMCq8XM6iQ8Ac6A+DSRRjDoRBm1ufCkaCDdNVbaqq60PsEkdNlLKrGtv/YBP4EJXqNtQ== + +web-streams-polyfill@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965" + integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" @@ -3120,6 +5792,19 @@ webpack@^5.67.0: watchpack "^2.3.1" webpack-sources "^3.2.3" +whatwg-fetch@^3.4.1: + version "3.6.2" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" + integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -3131,6 +5816,11 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -3143,11 +5833,47 @@ word-wrap@^1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +wrap-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" + integrity sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo= + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +"ws@^5.2.0 || ^6.0.0 || ^7.0.0": + version "7.5.7" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" + integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== + +ws@^8.3.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + xtend@~2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" @@ -3155,16 +5881,84 @@ xtend@~2.1.1: dependencies: object-keys "~0.4.0" +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.7.2: +yaml-ast-parser@^0.0.43: + version "0.0.43" + resolved "https://registry.yarnpkg.com/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz#e8a23e6fb4c38076ab92995c5dca33f3d3d7c9bb" + integrity sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A== + +yaml@^1.10.0, yaml@^1.7.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.0.tgz#a485d3966be4317426dd56bdb6a30131b281dc55" + integrity sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA== + +yargs@^15.3.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^17.0.0: + version "17.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" + integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + zen-observable-ts@^1.2.0: version "1.2.3" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.3.tgz#c2f5ccebe812faf0cfcde547e6004f65b1a6d769" diff --git a/cmd/hetty/main.go b/cmd/hetty/main.go index 8b9c1b0..fb3f72c 100644 --- a/cmd/hetty/main.go +++ b/cmd/hetty/main.go @@ -25,6 +25,7 @@ import ( "github.com/dstotijn/hetty/pkg/proxy" "github.com/dstotijn/hetty/pkg/reqlog" "github.com/dstotijn/hetty/pkg/scope" + "github.com/dstotijn/hetty/pkg/sender" ) var version = "0.0.0" @@ -94,9 +95,15 @@ func run() error { Repository: badger, }) + senderService := sender.NewService(sender.Config{ + Repository: badger, + ReqLogService: reqLogService, + }) + projService, err := proj.NewService(proj.Config{ Repository: badger, ReqLogService: reqLogService, + SenderService: senderService, Scope: scope, }) if err != nil { @@ -128,8 +135,9 @@ func run() error { adminRouter.Path("/api/playground/").Handler(playground.Handler("GraphQL Playground", "/api/graphql/")) adminRouter.Path("/api/graphql/").Handler( handler.NewDefaultServer(api.NewExecutableSchema(api.Config{Resolvers: &api.Resolver{ - RequestLogService: reqLogService, ProjectService: projService, + RequestLogService: reqLogService, + SenderService: senderService, }}))) // Admin interface. diff --git a/gqlgen.yml b/gqlgen.yml index 34b5781..85ebbfe 100644 --- a/gqlgen.yml +++ b/gqlgen.yml @@ -46,6 +46,9 @@ models: ID: model: - github.com/dstotijn/hetty/pkg/api.ULID + URL: + model: + - github.com/dstotijn/hetty/pkg/api.URL # Int: # model: # - github.com/99designs/gqlgen/graphql.Int diff --git a/pkg/api/generated.go b/pkg/api/generated.go index ec29089..bce9a12 100644 --- a/pkg/api/generated.go +++ b/pkg/api/generated.go @@ -6,6 +6,7 @@ import ( "bytes" "context" "errors" + "net/url" "strconv" "sync" "sync/atomic" @@ -13,6 +14,7 @@ import ( "github.com/99designs/gqlgen/graphql" "github.com/99designs/gqlgen/graphql/introspection" + "github.com/oklog/ulid" gqlparser "github.com/vektah/gqlparser/v2" "github.com/vektah/gqlparser/v2/ast" ) @@ -55,6 +57,10 @@ type ComplexityRoot struct { Success func(childComplexity int) int } + DeleteSenderRequestsResult struct { + Success func(childComplexity int) int + } + HTTPHeader struct { Key func(childComplexity int) int Value func(childComplexity int) int @@ -79,19 +85,25 @@ type ComplexityRoot struct { HTTPResponseLog struct { Body func(childComplexity int) int Headers func(childComplexity int) int + ID func(childComplexity int) int Proto func(childComplexity int) int StatusCode func(childComplexity int) int StatusReason func(childComplexity int) int } Mutation struct { - ClearHTTPRequestLog func(childComplexity int) int - CloseProject func(childComplexity int) int - CreateProject func(childComplexity int, name string) int - DeleteProject func(childComplexity int, id ULID) int - OpenProject func(childComplexity int, id ULID) int - SetHTTPRequestLogFilter func(childComplexity int, filter *HTTPRequestLogFilterInput) int - SetScope func(childComplexity int, scope []ScopeRuleInput) int + ClearHTTPRequestLog func(childComplexity int) int + CloseProject func(childComplexity int) int + CreateOrUpdateSenderRequest func(childComplexity int, request SenderRequestInput) int + CreateProject func(childComplexity int, name string) int + CreateSenderRequestFromHTTPRequestLog func(childComplexity int, id ulid.ULID) int + DeleteProject func(childComplexity int, id ulid.ULID) int + DeleteSenderRequests func(childComplexity int) int + OpenProject func(childComplexity int, id ulid.ULID) int + SendRequest func(childComplexity int, id ulid.ULID) int + SetHTTPRequestLogFilter func(childComplexity int, filter *HTTPRequestLogFilterInput) int + SetScope func(childComplexity int, scope []ScopeRuleInput) int + SetSenderRequestFilter func(childComplexity int, filter *SenderRequestFilterInput) int } Project struct { @@ -102,11 +114,13 @@ type ComplexityRoot struct { Query struct { ActiveProject func(childComplexity int) int - HTTPRequestLog func(childComplexity int, id ULID) int + HTTPRequestLog func(childComplexity int, id ulid.ULID) int HTTPRequestLogFilter func(childComplexity int) int HTTPRequestLogs func(childComplexity int) int Projects func(childComplexity int) int Scope func(childComplexity int) int + SenderRequest func(childComplexity int, id ulid.ULID) int + SenderRequests func(childComplexity int) int } ScopeHeader struct { @@ -119,24 +133,48 @@ type ComplexityRoot struct { Header func(childComplexity int) int URL func(childComplexity int) int } + + SenderRequest struct { + Body func(childComplexity int) int + Headers func(childComplexity int) int + ID func(childComplexity int) int + Method func(childComplexity int) int + Proto func(childComplexity int) int + Response func(childComplexity int) int + SourceRequestLogID func(childComplexity int) int + Timestamp func(childComplexity int) int + URL func(childComplexity int) int + } + + SenderRequestFilter struct { + OnlyInScope func(childComplexity int) int + SearchExpression func(childComplexity int) int + } } type MutationResolver interface { CreateProject(ctx context.Context, name string) (*Project, error) - OpenProject(ctx context.Context, id ULID) (*Project, error) + OpenProject(ctx context.Context, id ulid.ULID) (*Project, error) CloseProject(ctx context.Context) (*CloseProjectResult, error) - DeleteProject(ctx context.Context, id ULID) (*DeleteProjectResult, error) + DeleteProject(ctx context.Context, id ulid.ULID) (*DeleteProjectResult, error) ClearHTTPRequestLog(ctx context.Context) (*ClearHTTPRequestLogResult, error) SetScope(ctx context.Context, scope []ScopeRuleInput) ([]ScopeRule, error) SetHTTPRequestLogFilter(ctx context.Context, filter *HTTPRequestLogFilterInput) (*HTTPRequestLogFilter, error) + SetSenderRequestFilter(ctx context.Context, filter *SenderRequestFilterInput) (*SenderRequestFilter, error) + CreateOrUpdateSenderRequest(ctx context.Context, request SenderRequestInput) (*SenderRequest, error) + CreateSenderRequestFromHTTPRequestLog(ctx context.Context, id ulid.ULID) (*SenderRequest, error) + SendRequest(ctx context.Context, id ulid.ULID) (*SenderRequest, error) + DeleteSenderRequests(ctx context.Context) (*DeleteSenderRequestsResult, error) } type QueryResolver interface { - HTTPRequestLog(ctx context.Context, id ULID) (*HTTPRequestLog, error) + HTTPRequestLog(ctx context.Context, id ulid.ULID) (*HTTPRequestLog, error) HTTPRequestLogs(ctx context.Context) ([]HTTPRequestLog, error) HTTPRequestLogFilter(ctx context.Context) (*HTTPRequestLogFilter, error) ActiveProject(ctx context.Context) (*Project, error) Projects(ctx context.Context) ([]Project, error) Scope(ctx context.Context) ([]ScopeRule, error) + SenderRequest(ctx context.Context, id ulid.ULID) (*SenderRequest, error) + SenderRequests(ctx context.Context) ([]SenderRequest, error) } type executableSchema struct { @@ -175,6 +213,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.DeleteProjectResult.Success(childComplexity), true + case "DeleteSenderRequestsResult.success": + if e.complexity.DeleteSenderRequestsResult.Success == nil { + break + } + + return e.complexity.DeleteSenderRequestsResult.Success(childComplexity), true + case "HttpHeader.key": if e.complexity.HTTPHeader.Key == nil { break @@ -273,6 +318,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.HTTPResponseLog.Headers(childComplexity), true + case "HttpResponseLog.id": + if e.complexity.HTTPResponseLog.ID == nil { + break + } + + return e.complexity.HTTPResponseLog.ID(childComplexity), true + case "HttpResponseLog.proto": if e.complexity.HTTPResponseLog.Proto == nil { break @@ -308,6 +360,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.CloseProject(childComplexity), true + case "Mutation.createOrUpdateSenderRequest": + if e.complexity.Mutation.CreateOrUpdateSenderRequest == nil { + break + } + + args, err := ec.field_Mutation_createOrUpdateSenderRequest_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CreateOrUpdateSenderRequest(childComplexity, args["request"].(SenderRequestInput)), true + case "Mutation.createProject": if e.complexity.Mutation.CreateProject == nil { break @@ -320,6 +384,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.CreateProject(childComplexity, args["name"].(string)), true + case "Mutation.createSenderRequestFromHttpRequestLog": + if e.complexity.Mutation.CreateSenderRequestFromHTTPRequestLog == nil { + break + } + + args, err := ec.field_Mutation_createSenderRequestFromHttpRequestLog_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.CreateSenderRequestFromHTTPRequestLog(childComplexity, args["id"].(ulid.ULID)), true + case "Mutation.deleteProject": if e.complexity.Mutation.DeleteProject == nil { break @@ -330,7 +406,14 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Mutation.DeleteProject(childComplexity, args["id"].(ULID)), true + return e.complexity.Mutation.DeleteProject(childComplexity, args["id"].(ulid.ULID)), true + + case "Mutation.deleteSenderRequests": + if e.complexity.Mutation.DeleteSenderRequests == nil { + break + } + + return e.complexity.Mutation.DeleteSenderRequests(childComplexity), true case "Mutation.openProject": if e.complexity.Mutation.OpenProject == nil { @@ -342,7 +425,19 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Mutation.OpenProject(childComplexity, args["id"].(ULID)), true + return e.complexity.Mutation.OpenProject(childComplexity, args["id"].(ulid.ULID)), true + + case "Mutation.sendRequest": + if e.complexity.Mutation.SendRequest == nil { + break + } + + args, err := ec.field_Mutation_sendRequest_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.SendRequest(childComplexity, args["id"].(ulid.ULID)), true case "Mutation.setHttpRequestLogFilter": if e.complexity.Mutation.SetHTTPRequestLogFilter == nil { @@ -368,6 +463,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Mutation.SetScope(childComplexity, args["scope"].([]ScopeRuleInput)), true + case "Mutation.setSenderRequestFilter": + if e.complexity.Mutation.SetSenderRequestFilter == nil { + break + } + + args, err := ec.field_Mutation_setSenderRequestFilter_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Mutation.SetSenderRequestFilter(childComplexity, args["filter"].(*SenderRequestFilterInput)), true + case "Project.id": if e.complexity.Project.ID == nil { break @@ -406,7 +513,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return 0, false } - return e.complexity.Query.HTTPRequestLog(childComplexity, args["id"].(ULID)), true + return e.complexity.Query.HTTPRequestLog(childComplexity, args["id"].(ulid.ULID)), true case "Query.httpRequestLogFilter": if e.complexity.Query.HTTPRequestLogFilter == nil { @@ -436,6 +543,25 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.Query.Scope(childComplexity), true + case "Query.senderRequest": + if e.complexity.Query.SenderRequest == nil { + break + } + + args, err := ec.field_Query_senderRequest_args(context.TODO(), rawArgs) + if err != nil { + return 0, false + } + + return e.complexity.Query.SenderRequest(childComplexity, args["id"].(ulid.ULID)), true + + case "Query.senderRequests": + if e.complexity.Query.SenderRequests == nil { + break + } + + return e.complexity.Query.SenderRequests(childComplexity), true + case "ScopeHeader.key": if e.complexity.ScopeHeader.Key == nil { break @@ -471,6 +597,83 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.ScopeRule.URL(childComplexity), true + case "SenderRequest.body": + if e.complexity.SenderRequest.Body == nil { + break + } + + return e.complexity.SenderRequest.Body(childComplexity), true + + case "SenderRequest.headers": + if e.complexity.SenderRequest.Headers == nil { + break + } + + return e.complexity.SenderRequest.Headers(childComplexity), true + + case "SenderRequest.id": + if e.complexity.SenderRequest.ID == nil { + break + } + + return e.complexity.SenderRequest.ID(childComplexity), true + + case "SenderRequest.method": + if e.complexity.SenderRequest.Method == nil { + break + } + + return e.complexity.SenderRequest.Method(childComplexity), true + + case "SenderRequest.proto": + if e.complexity.SenderRequest.Proto == nil { + break + } + + return e.complexity.SenderRequest.Proto(childComplexity), true + + case "SenderRequest.response": + if e.complexity.SenderRequest.Response == nil { + break + } + + return e.complexity.SenderRequest.Response(childComplexity), true + + case "SenderRequest.sourceRequestLogID": + if e.complexity.SenderRequest.SourceRequestLogID == nil { + break + } + + return e.complexity.SenderRequest.SourceRequestLogID(childComplexity), true + + case "SenderRequest.timestamp": + if e.complexity.SenderRequest.Timestamp == nil { + break + } + + return e.complexity.SenderRequest.Timestamp(childComplexity), true + + case "SenderRequest.url": + if e.complexity.SenderRequest.URL == nil { + break + } + + return e.complexity.SenderRequest.URL(childComplexity), true + + case "SenderRequestFilter.onlyInScope": + if e.complexity.SenderRequestFilter.OnlyInScope == nil { + break + } + + return e.complexity.SenderRequestFilter.OnlyInScope(childComplexity), true + + case "SenderRequestFilter.searchExpression": + if e.complexity.SenderRequestFilter.SearchExpression == nil { + break + } + + return e.complexity.SenderRequestFilter.SearchExpression(childComplexity), true + } return 0, false } @@ -547,7 +750,11 @@ var sources = []*ast.Source{ } type HttpResponseLog { - proto: String! + """ + Will be the same ID as its related request ID. + """ + id: ID! + proto: HttpProtocol! statusCode: Int! statusReason: String! body: String @@ -599,6 +806,10 @@ type ClearHTTPRequestLogResult { success: Boolean! } +type DeleteSenderRequestsResult { + success: Boolean! +} + input HttpRequestLogFilterInput { onlyInScope: Boolean searchExpression: String @@ -609,6 +820,42 @@ type HttpRequestLogFilter { searchExpression: String } +input SenderRequestInput { + id: ID + url: URL! + method: HttpMethod + proto: HttpProtocol + headers: [HttpHeaderInput!] + body: String +} + +input HttpHeaderInput { + key: String! + value: String! +} + +type SenderRequest { + id: ID! + sourceRequestLogID: ID + url: URL! + method: HttpMethod! + proto: HttpProtocol! + headers: [HttpHeader!] + body: String + timestamp: Time! + response: HttpResponseLog +} + +input SenderRequestFilterInput { + onlyInScope: Boolean + searchExpression: String +} + +type SenderRequestFilter { + onlyInScope: Boolean! + searchExpression: String +} + type Query { httpRequestLog(id: ID!): HttpRequestLog httpRequestLogs: [HttpRequestLog!]! @@ -616,6 +863,8 @@ type Query { activeProject: Project projects: [Project!]! scope: [ScopeRule!]! + senderRequest(id: ID!): SenderRequest + senderRequests: [SenderRequest!]! } type Mutation { @@ -628,6 +877,11 @@ type Mutation { setHttpRequestLogFilter( filter: HttpRequestLogFilterInput ): HttpRequestLogFilter + setSenderRequestFilter(filter: SenderRequestFilterInput): SenderRequestFilter + createOrUpdateSenderRequest(request: SenderRequestInput!): SenderRequest! + createSenderRequestFromHttpRequestLog(id: ID!): SenderRequest! + sendRequest(id: ID!): SenderRequest! + deleteSenderRequests: DeleteSenderRequestsResult! } enum HttpMethod { @@ -642,8 +896,14 @@ enum HttpMethod { PATCH } +enum HttpProtocol { + HTTP1 + HTTP2 +} + scalar Time scalar Regexp +scalar URL `, BuiltIn: false}, } var parsedSchema = gqlparser.MustLoadSchema(sources...) @@ -652,6 +912,21 @@ var parsedSchema = gqlparser.MustLoadSchema(sources...) // region ***************************** args.gotpl ***************************** +func (ec *executionContext) field_Mutation_createOrUpdateSenderRequest_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 SenderRequestInput + if tmp, ok := rawArgs["request"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("request")) + arg0, err = ec.unmarshalNSenderRequestInput2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequestInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["request"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_createProject_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -667,13 +942,28 @@ func (ec *executionContext) field_Mutation_createProject_args(ctx context.Contex return args, nil } +func (ec *executionContext) field_Mutation_createSenderRequestFromHttpRequestLog_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 ulid.ULID + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + func (ec *executionContext) field_Mutation_deleteProject_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 ULID + var arg0 ulid.ULID if tmp, ok := rawArgs["id"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - arg0, err = ec.unmarshalNID2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐULID(ctx, tmp) + arg0, err = ec.unmarshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx, tmp) if err != nil { return nil, err } @@ -685,10 +975,25 @@ func (ec *executionContext) field_Mutation_deleteProject_args(ctx context.Contex func (ec *executionContext) field_Mutation_openProject_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 ULID + var arg0 ulid.ULID if tmp, ok := rawArgs["id"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - arg0, err = ec.unmarshalNID2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐULID(ctx, tmp) + arg0, err = ec.unmarshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Mutation_sendRequest_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 ulid.ULID + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx, tmp) if err != nil { return nil, err } @@ -727,6 +1032,21 @@ func (ec *executionContext) field_Mutation_setScope_args(ctx context.Context, ra return args, nil } +func (ec *executionContext) field_Mutation_setSenderRequestFilter_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 *SenderRequestFilterInput + if tmp, ok := rawArgs["filter"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filter")) + arg0, err = ec.unmarshalOSenderRequestFilterInput2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequestFilterInput(ctx, tmp) + if err != nil { + return nil, err + } + } + args["filter"] = arg0 + return args, nil +} + func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} @@ -745,10 +1065,25 @@ func (ec *executionContext) field_Query___type_args(ctx context.Context, rawArgs func (ec *executionContext) field_Query_httpRequestLog_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { var err error args := map[string]interface{}{} - var arg0 ULID + var arg0 ulid.ULID if tmp, ok := rawArgs["id"]; ok { ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) - arg0, err = ec.unmarshalNID2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐULID(ctx, tmp) + arg0, err = ec.unmarshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx, tmp) + if err != nil { + return nil, err + } + } + args["id"] = arg0 + return args, nil +} + +func (ec *executionContext) field_Query_senderRequest_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) { + var err error + args := map[string]interface{}{} + var arg0 ulid.ULID + if tmp, ok := rawArgs["id"]; ok { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + arg0, err = ec.unmarshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx, tmp) if err != nil { return nil, err } @@ -900,6 +1235,41 @@ func (ec *executionContext) _DeleteProjectResult_success(ctx context.Context, fi return ec.marshalNBoolean2bool(ctx, field.Selections, res) } +func (ec *executionContext) _DeleteSenderRequestsResult_success(ctx context.Context, field graphql.CollectedField, obj *DeleteSenderRequestsResult) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "DeleteSenderRequestsResult", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Success, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + func (ec *executionContext) _HttpHeader_key(ctx context.Context, field graphql.CollectedField, obj *HTTPHeader) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -1000,9 +1370,9 @@ func (ec *executionContext) _HttpRequestLog_id(ctx context.Context, field graphq } return graphql.Null } - res := resTmp.(ULID) + res := resTmp.(ulid.ULID) fc.Result = res - return ec.marshalNID2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐULID(ctx, field.Selections, res) + return ec.marshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx, field.Selections, res) } func (ec *executionContext) _HttpRequestLog_url(ctx context.Context, field graphql.CollectedField, obj *HTTPRequestLog) (ret graphql.Marshaler) { @@ -1311,6 +1681,41 @@ func (ec *executionContext) _HttpRequestLogFilter_searchExpression(ctx context.C return ec.marshalOString2ᚖstring(ctx, field.Selections, res) } +func (ec *executionContext) _HttpResponseLog_id(ctx context.Context, field graphql.CollectedField, obj *HTTPResponseLog) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "HttpResponseLog", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(ulid.ULID) + fc.Result = res + return ec.marshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx, field.Selections, res) +} + func (ec *executionContext) _HttpResponseLog_proto(ctx context.Context, field graphql.CollectedField, obj *HTTPResponseLog) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -1341,9 +1746,9 @@ func (ec *executionContext) _HttpResponseLog_proto(ctx context.Context, field gr } return graphql.Null } - res := resTmp.(string) + res := resTmp.(HTTPProtocol) fc.Result = res - return ec.marshalNString2string(ctx, field.Selections, res) + return ec.marshalNHttpProtocol2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPProtocol(ctx, field.Selections, res) } func (ec *executionContext) _HttpResponseLog_statusCode(ctx context.Context, field graphql.CollectedField, obj *HTTPResponseLog) (ret graphql.Marshaler) { @@ -1547,7 +1952,7 @@ func (ec *executionContext) _Mutation_openProject(ctx context.Context, field gra fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().OpenProject(rctx, args["id"].(ULID)) + return ec.resolvers.Mutation().OpenProject(rctx, args["id"].(ulid.ULID)) }) if err != nil { ec.Error(ctx, err) @@ -1621,7 +2026,7 @@ func (ec *executionContext) _Mutation_deleteProject(ctx context.Context, field g fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Mutation().DeleteProject(rctx, args["id"].(ULID)) + return ec.resolvers.Mutation().DeleteProject(rctx, args["id"].(ulid.ULID)) }) if err != nil { ec.Error(ctx, err) @@ -1754,6 +2159,206 @@ func (ec *executionContext) _Mutation_setHttpRequestLogFilter(ctx context.Contex return ec.marshalOHttpRequestLogFilter2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPRequestLogFilter(ctx, field.Selections, res) } +func (ec *executionContext) _Mutation_setSenderRequestFilter(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_setSenderRequestFilter_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().SetSenderRequestFilter(rctx, args["filter"].(*SenderRequestFilterInput)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*SenderRequestFilter) + fc.Result = res + return ec.marshalOSenderRequestFilter2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequestFilter(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_createOrUpdateSenderRequest(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createOrUpdateSenderRequest_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CreateOrUpdateSenderRequest(rctx, args["request"].(SenderRequestInput)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*SenderRequest) + fc.Result = res + return ec.marshalNSenderRequest2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequest(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_createSenderRequestFromHttpRequestLog(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_createSenderRequestFromHttpRequestLog_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().CreateSenderRequestFromHTTPRequestLog(rctx, args["id"].(ulid.ULID)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*SenderRequest) + fc.Result = res + return ec.marshalNSenderRequest2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequest(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_sendRequest(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Mutation_sendRequest_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().SendRequest(rctx, args["id"].(ulid.ULID)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*SenderRequest) + fc.Result = res + return ec.marshalNSenderRequest2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequest(ctx, field.Selections, res) +} + +func (ec *executionContext) _Mutation_deleteSenderRequests(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Mutation", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Mutation().DeleteSenderRequests(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*DeleteSenderRequestsResult) + fc.Result = res + return ec.marshalNDeleteSenderRequestsResult2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐDeleteSenderRequestsResult(ctx, field.Selections, res) +} + func (ec *executionContext) _Project_id(ctx context.Context, field graphql.CollectedField, obj *Project) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -1784,9 +2389,9 @@ func (ec *executionContext) _Project_id(ctx context.Context, field graphql.Colle } return graphql.Null } - res := resTmp.(ULID) + res := resTmp.(ulid.ULID) fc.Result = res - return ec.marshalNID2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐULID(ctx, field.Selections, res) + return ec.marshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx, field.Selections, res) } func (ec *executionContext) _Project_name(ctx context.Context, field graphql.CollectedField, obj *Project) (ret graphql.Marshaler) { @@ -1884,7 +2489,7 @@ func (ec *executionContext) _Query_httpRequestLog(ctx context.Context, field gra fc.Args = args resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { ctx = rctx // use context from middleware stack in children - return ec.resolvers.Query().HTTPRequestLog(rctx, args["id"].(ULID)) + return ec.resolvers.Query().HTTPRequestLog(rctx, args["id"].(ulid.ULID)) }) if err != nil { ec.Error(ctx, err) @@ -2067,6 +2672,80 @@ func (ec *executionContext) _Query_scope(ctx context.Context, field graphql.Coll return ec.marshalNScopeRule2ᚕgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐScopeRuleᚄ(ctx, field.Selections, res) } +func (ec *executionContext) _Query_senderRequest(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + rawArgs := field.ArgumentMap(ec.Variables) + args, err := ec.field_Query_senderRequest_args(ctx, rawArgs) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + fc.Args = args + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().SenderRequest(rctx, args["id"].(ulid.ULID)) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*SenderRequest) + fc.Result = res + return ec.marshalOSenderRequest2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequest(ctx, field.Selections, res) +} + +func (ec *executionContext) _Query_senderRequests(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "Query", + Field: field, + Args: nil, + IsMethod: true, + IsResolver: true, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.Query().SenderRequests(rctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.([]SenderRequest) + fc.Result = res + return ec.marshalNSenderRequest2ᚕgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequestᚄ(ctx, field.Selections, res) +} + func (ec *executionContext) _Query___type(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -2298,6 +2977,376 @@ func (ec *executionContext) _ScopeRule_body(ctx context.Context, field graphql.C return ec.marshalORegexp2ᚖstring(ctx, field.Selections, res) } +func (ec *executionContext) _SenderRequest_id(ctx context.Context, field graphql.CollectedField, obj *SenderRequest) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequest", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.ID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(ulid.ULID) + fc.Result = res + return ec.marshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx, field.Selections, res) +} + +func (ec *executionContext) _SenderRequest_sourceRequestLogID(ctx context.Context, field graphql.CollectedField, obj *SenderRequest) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequest", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SourceRequestLogID, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*ulid.ULID) + fc.Result = res + return ec.marshalOID2ᚖgithubᚗcomᚋoklogᚋulidᚐULID(ctx, field.Selections, res) +} + +func (ec *executionContext) _SenderRequest_url(ctx context.Context, field graphql.CollectedField, obj *SenderRequest) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequest", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.URL, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*url.URL) + fc.Result = res + return ec.marshalNURL2ᚖnetᚋurlᚐURL(ctx, field.Selections, res) +} + +func (ec *executionContext) _SenderRequest_method(ctx context.Context, field graphql.CollectedField, obj *SenderRequest) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequest", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Method, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(HTTPMethod) + fc.Result = res + return ec.marshalNHttpMethod2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPMethod(ctx, field.Selections, res) +} + +func (ec *executionContext) _SenderRequest_proto(ctx context.Context, field graphql.CollectedField, obj *SenderRequest) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequest", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Proto, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(HTTPProtocol) + fc.Result = res + return ec.marshalNHttpProtocol2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPProtocol(ctx, field.Selections, res) +} + +func (ec *executionContext) _SenderRequest_headers(ctx context.Context, field graphql.CollectedField, obj *SenderRequest) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequest", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Headers, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.([]HTTPHeader) + fc.Result = res + return ec.marshalOHttpHeader2ᚕgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPHeaderᚄ(ctx, field.Selections, res) +} + +func (ec *executionContext) _SenderRequest_body(ctx context.Context, field graphql.CollectedField, obj *SenderRequest) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequest", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Body, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) _SenderRequest_timestamp(ctx context.Context, field graphql.CollectedField, obj *SenderRequest) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequest", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Timestamp, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(time.Time) + fc.Result = res + return ec.marshalNTime2timeᚐTime(ctx, field.Selections, res) +} + +func (ec *executionContext) _SenderRequest_response(ctx context.Context, field graphql.CollectedField, obj *SenderRequest) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequest", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.Response, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*HTTPResponseLog) + fc.Result = res + return ec.marshalOHttpResponseLog2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPResponseLog(ctx, field.Selections, res) +} + +func (ec *executionContext) _SenderRequestFilter_onlyInScope(ctx context.Context, field graphql.CollectedField, obj *SenderRequestFilter) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequestFilter", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.OnlyInScope, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + fc.Result = res + return ec.marshalNBoolean2bool(ctx, field.Selections, res) +} + +func (ec *executionContext) _SenderRequestFilter_searchExpression(ctx context.Context, field graphql.CollectedField, obj *SenderRequestFilter) (ret graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + fc := &graphql.FieldContext{ + Object: "SenderRequestFilter", + Field: field, + Args: nil, + IsMethod: false, + IsResolver: false, + } + + ctx = graphql.WithFieldContext(ctx, fc) + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.SearchExpression, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOString2ᚖstring(ctx, field.Selections, res) +} + func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { defer func() { if r := recover(); r != nil { @@ -3420,6 +4469,37 @@ func (ec *executionContext) ___Type_ofType(ctx context.Context, field graphql.Co // region **************************** input.gotpl ***************************** +func (ec *executionContext) unmarshalInputHttpHeaderInput(ctx context.Context, obj interface{}) (HTTPHeaderInput, error) { + var it HTTPHeaderInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "key": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("key")) + it.Key, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + case "value": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("value")) + it.Value, err = ec.unmarshalNString2string(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputHttpRequestLogFilterInput(ctx context.Context, obj interface{}) (HTTPRequestLogFilterInput, error) { var it HTTPRequestLogFilterInput asMap := map[string]interface{}{} @@ -3521,6 +4601,100 @@ func (ec *executionContext) unmarshalInputScopeRuleInput(ctx context.Context, ob return it, nil } +func (ec *executionContext) unmarshalInputSenderRequestFilterInput(ctx context.Context, obj interface{}) (SenderRequestFilterInput, error) { + var it SenderRequestFilterInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "onlyInScope": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("onlyInScope")) + it.OnlyInScope, err = ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + case "searchExpression": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("searchExpression")) + it.SearchExpression, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + +func (ec *executionContext) unmarshalInputSenderRequestInput(ctx context.Context, obj interface{}) (SenderRequestInput, error) { + var it SenderRequestInput + asMap := map[string]interface{}{} + for k, v := range obj.(map[string]interface{}) { + asMap[k] = v + } + + for k, v := range asMap { + switch k { + case "id": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + it.ID, err = ec.unmarshalOID2ᚖgithubᚗcomᚋoklogᚋulidᚐULID(ctx, v) + if err != nil { + return it, err + } + case "url": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("url")) + it.URL, err = ec.unmarshalNURL2ᚖnetᚋurlᚐURL(ctx, v) + if err != nil { + return it, err + } + case "method": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("method")) + it.Method, err = ec.unmarshalOHttpMethod2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPMethod(ctx, v) + if err != nil { + return it, err + } + case "proto": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("proto")) + it.Proto, err = ec.unmarshalOHttpProtocol2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPProtocol(ctx, v) + if err != nil { + return it, err + } + case "headers": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("headers")) + it.Headers, err = ec.unmarshalOHttpHeaderInput2ᚕgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPHeaderInputᚄ(ctx, v) + if err != nil { + return it, err + } + case "body": + var err error + + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("body")) + it.Body, err = ec.unmarshalOString2ᚖstring(ctx, v) + if err != nil { + return it, err + } + } + } + + return it, nil +} + // endregion **************************** input.gotpl ***************************** // region ************************** interface.gotpl *************************** @@ -3610,6 +4784,33 @@ func (ec *executionContext) _DeleteProjectResult(ctx context.Context, sel ast.Se return out } +var deleteSenderRequestsResultImplementors = []string{"DeleteSenderRequestsResult"} + +func (ec *executionContext) _DeleteSenderRequestsResult(ctx context.Context, sel ast.SelectionSet, obj *DeleteSenderRequestsResult) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, deleteSenderRequestsResultImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("DeleteSenderRequestsResult") + case "success": + out.Values[i] = ec._DeleteSenderRequestsResult_success(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var httpHeaderImplementors = []string{"HttpHeader"} func (ec *executionContext) _HttpHeader(ctx context.Context, sel ast.SelectionSet, obj *HTTPHeader) graphql.Marshaler { @@ -3738,6 +4939,11 @@ func (ec *executionContext) _HttpResponseLog(ctx context.Context, sel ast.Select switch field.Name { case "__typename": out.Values[i] = graphql.MarshalString("HttpResponseLog") + case "id": + out.Values[i] = ec._HttpResponseLog_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } case "proto": out.Values[i] = ec._HttpResponseLog_proto(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -3812,6 +5018,28 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet) } case "setHttpRequestLogFilter": out.Values[i] = ec._Mutation_setHttpRequestLogFilter(ctx, field) + case "setSenderRequestFilter": + out.Values[i] = ec._Mutation_setSenderRequestFilter(ctx, field) + case "createOrUpdateSenderRequest": + out.Values[i] = ec._Mutation_createOrUpdateSenderRequest(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "createSenderRequestFromHttpRequestLog": + out.Values[i] = ec._Mutation_createSenderRequestFromHttpRequestLog(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "sendRequest": + out.Values[i] = ec._Mutation_sendRequest(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } + case "deleteSenderRequests": + out.Values[i] = ec._Mutation_deleteSenderRequests(ctx, field) + if out.Values[i] == graphql.Null { + invalids++ + } default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -3950,6 +5178,31 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr } return res }) + case "senderRequest": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_senderRequest(ctx, field) + return res + }) + case "senderRequests": + field := field + out.Concurrently(i, func() (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Query_senderRequests(ctx, field) + if res == graphql.Null { + atomic.AddUint32(&invalids, 1) + } + return res + }) case "__type": out.Values[i] = ec._Query___type(ctx, field) case "__schema": @@ -4019,6 +5272,90 @@ func (ec *executionContext) _ScopeRule(ctx context.Context, sel ast.SelectionSet return out } +var senderRequestImplementors = []string{"SenderRequest"} + +func (ec *executionContext) _SenderRequest(ctx context.Context, sel ast.SelectionSet, obj *SenderRequest) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, senderRequestImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("SenderRequest") + case "id": + out.Values[i] = ec._SenderRequest_id(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "sourceRequestLogID": + out.Values[i] = ec._SenderRequest_sourceRequestLogID(ctx, field, obj) + case "url": + out.Values[i] = ec._SenderRequest_url(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "method": + out.Values[i] = ec._SenderRequest_method(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "proto": + out.Values[i] = ec._SenderRequest_proto(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "headers": + out.Values[i] = ec._SenderRequest_headers(ctx, field, obj) + case "body": + out.Values[i] = ec._SenderRequest_body(ctx, field, obj) + case "timestamp": + out.Values[i] = ec._SenderRequest_timestamp(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "response": + out.Values[i] = ec._SenderRequest_response(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + +var senderRequestFilterImplementors = []string{"SenderRequestFilter"} + +func (ec *executionContext) _SenderRequestFilter(ctx context.Context, sel ast.SelectionSet, obj *SenderRequestFilter) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, senderRequestFilterImplementors) + + out := graphql.NewFieldSet(fields) + var invalids uint32 + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("SenderRequestFilter") + case "onlyInScope": + out.Values[i] = ec._SenderRequestFilter_onlyInScope(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalids++ + } + case "searchExpression": + out.Values[i] = ec._SenderRequestFilter_searchExpression(ctx, field, obj) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch() + if invalids > 0 { + return graphql.Null + } + return out +} + var __DirectiveImplementors = []string{"__Directive"} func (ec *executionContext) ___Directive(ctx context.Context, sel ast.SelectionSet, obj *introspection.Directive) graphql.Marshaler { @@ -4326,6 +5663,20 @@ func (ec *executionContext) marshalNDeleteProjectResult2ᚖgithubᚗcomᚋdstoti return ec._DeleteProjectResult(ctx, sel, v) } +func (ec *executionContext) marshalNDeleteSenderRequestsResult2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐDeleteSenderRequestsResult(ctx context.Context, sel ast.SelectionSet, v DeleteSenderRequestsResult) graphql.Marshaler { + return ec._DeleteSenderRequestsResult(ctx, sel, &v) +} + +func (ec *executionContext) marshalNDeleteSenderRequestsResult2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐDeleteSenderRequestsResult(ctx context.Context, sel ast.SelectionSet, v *DeleteSenderRequestsResult) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._DeleteSenderRequestsResult(ctx, sel, v) +} + func (ec *executionContext) marshalNHttpHeader2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPHeader(ctx context.Context, sel ast.SelectionSet, v HTTPHeader) graphql.Marshaler { return ec._HttpHeader(ctx, sel, &v) } @@ -4374,6 +5725,11 @@ func (ec *executionContext) marshalNHttpHeader2ᚕgithubᚗcomᚋdstotijnᚋhett return ret } +func (ec *executionContext) unmarshalNHttpHeaderInput2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPHeaderInput(ctx context.Context, v interface{}) (HTTPHeaderInput, error) { + res, err := ec.unmarshalInputHttpHeaderInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalNHttpMethod2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPMethod(ctx context.Context, v interface{}) (HTTPMethod, error) { var res HTTPMethod err := res.UnmarshalGQL(v) @@ -4384,6 +5740,16 @@ func (ec *executionContext) marshalNHttpMethod2githubᚗcomᚋdstotijnᚋhetty return v } +func (ec *executionContext) unmarshalNHttpProtocol2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPProtocol(ctx context.Context, v interface{}) (HTTPProtocol, error) { + var res HTTPProtocol + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNHttpProtocol2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPProtocol(ctx context.Context, sel ast.SelectionSet, v HTTPProtocol) graphql.Marshaler { + return v +} + func (ec *executionContext) marshalNHttpRequestLog2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPRequestLog(ctx context.Context, sel ast.SelectionSet, v HTTPRequestLog) graphql.Marshaler { return ec._HttpRequestLog(ctx, sel, &v) } @@ -4432,14 +5798,19 @@ func (ec *executionContext) marshalNHttpRequestLog2ᚕgithubᚗcomᚋdstotijnᚋ return ret } -func (ec *executionContext) unmarshalNID2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐULID(ctx context.Context, v interface{}) (ULID, error) { - var res ULID - err := res.UnmarshalGQL(v) +func (ec *executionContext) unmarshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx context.Context, v interface{}) (ulid.ULID, error) { + res, err := UnmarshalULID(v) return res, graphql.ErrorOnPath(ctx, err) } -func (ec *executionContext) marshalNID2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐULID(ctx context.Context, sel ast.SelectionSet, v ULID) graphql.Marshaler { - return v +func (ec *executionContext) marshalNID2githubᚗcomᚋoklogᚋulidᚐULID(ctx context.Context, sel ast.SelectionSet, v ulid.ULID) graphql.Marshaler { + res := MarshalULID(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res } func (ec *executionContext) unmarshalNInt2int(ctx context.Context, v interface{}) (int, error) { @@ -4579,6 +5950,69 @@ func (ec *executionContext) unmarshalNScopeRuleInput2ᚕgithubᚗcomᚋdstotijn return res, nil } +func (ec *executionContext) marshalNSenderRequest2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequest(ctx context.Context, sel ast.SelectionSet, v SenderRequest) graphql.Marshaler { + return ec._SenderRequest(ctx, sel, &v) +} + +func (ec *executionContext) marshalNSenderRequest2ᚕgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequestᚄ(ctx context.Context, sel ast.SelectionSet, v []SenderRequest) graphql.Marshaler { + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNSenderRequest2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequest(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) marshalNSenderRequest2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequest(ctx context.Context, sel ast.SelectionSet, v *SenderRequest) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + return ec._SenderRequest(ctx, sel, v) +} + +func (ec *executionContext) unmarshalNSenderRequestInput2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequestInput(ctx context.Context, v interface{}) (SenderRequestInput, error) { + res, err := ec.unmarshalInputSenderRequestInput(ctx, v) + return res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalNString2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalString(v) return res, graphql.ErrorOnPath(ctx, err) @@ -4609,6 +6043,27 @@ func (ec *executionContext) marshalNTime2timeᚐTime(ctx context.Context, sel as return res } +func (ec *executionContext) unmarshalNURL2ᚖnetᚋurlᚐURL(ctx context.Context, v interface{}) (*url.URL, error) { + res, err := UnmarshalURL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalNURL2ᚖnetᚋurlᚐURL(ctx context.Context, sel ast.SelectionSet, v *url.URL) graphql.Marshaler { + if v == nil { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := MarshalURL(v) + if res == graphql.Null { + if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) { + ec.Errorf(ctx, "must not be null") + } + } + return res +} + func (ec *executionContext) marshalN__Directive2githubᚗcomᚋ99designsᚋgqlgenᚋgraphqlᚋintrospectionᚐDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler { return ec.___Directive(ctx, sel, &v) } @@ -4890,6 +6345,109 @@ func (ec *executionContext) marshalOBoolean2ᚖbool(ctx context.Context, sel ast return graphql.MarshalBoolean(*v) } +func (ec *executionContext) marshalOHttpHeader2ᚕgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPHeaderᚄ(ctx context.Context, sel ast.SelectionSet, v []HTTPHeader) graphql.Marshaler { + if v == nil { + return graphql.Null + } + ret := make(graphql.Array, len(v)) + var wg sync.WaitGroup + isLen1 := len(v) == 1 + if !isLen1 { + wg.Add(len(v)) + } + for i := range v { + i := i + fc := &graphql.FieldContext{ + Index: &i, + Result: &v[i], + } + ctx := graphql.WithFieldContext(ctx, fc) + f := func(i int) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = nil + } + }() + if !isLen1 { + defer wg.Done() + } + ret[i] = ec.marshalNHttpHeader2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPHeader(ctx, sel, v[i]) + } + if isLen1 { + f(i) + } else { + go f(i) + } + + } + wg.Wait() + + for _, e := range ret { + if e == graphql.Null { + return graphql.Null + } + } + + return ret +} + +func (ec *executionContext) unmarshalOHttpHeaderInput2ᚕgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPHeaderInputᚄ(ctx context.Context, v interface{}) ([]HTTPHeaderInput, error) { + if v == nil { + return nil, nil + } + var vSlice []interface{} + if v != nil { + if tmp1, ok := v.([]interface{}); ok { + vSlice = tmp1 + } else { + vSlice = []interface{}{v} + } + } + var err error + res := make([]HTTPHeaderInput, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNHttpHeaderInput2githubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPHeaderInput(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) unmarshalOHttpMethod2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPMethod(ctx context.Context, v interface{}) (*HTTPMethod, error) { + if v == nil { + return nil, nil + } + var res = new(HTTPMethod) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOHttpMethod2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPMethod(ctx context.Context, sel ast.SelectionSet, v *HTTPMethod) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + +func (ec *executionContext) unmarshalOHttpProtocol2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPProtocol(ctx context.Context, v interface{}) (*HTTPProtocol, error) { + if v == nil { + return nil, nil + } + var res = new(HTTPProtocol) + err := res.UnmarshalGQL(v) + return res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOHttpProtocol2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPProtocol(ctx context.Context, sel ast.SelectionSet, v *HTTPProtocol) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return v +} + func (ec *executionContext) marshalOHttpRequestLog2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐHTTPRequestLog(ctx context.Context, sel ast.SelectionSet, v *HTTPRequestLog) graphql.Marshaler { if v == nil { return graphql.Null @@ -4919,6 +6477,21 @@ func (ec *executionContext) marshalOHttpResponseLog2ᚖgithubᚗcomᚋdstotijn return ec._HttpResponseLog(ctx, sel, v) } +func (ec *executionContext) unmarshalOID2ᚖgithubᚗcomᚋoklogᚋulidᚐULID(ctx context.Context, v interface{}) (*ulid.ULID, error) { + if v == nil { + return nil, nil + } + res, err := UnmarshalULID(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOID2ᚖgithubᚗcomᚋoklogᚋulidᚐULID(ctx context.Context, sel ast.SelectionSet, v *ulid.ULID) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return MarshalULID(*v) +} + func (ec *executionContext) marshalOProject2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐProject(ctx context.Context, sel ast.SelectionSet, v *Project) graphql.Marshaler { if v == nil { return graphql.Null @@ -4956,6 +6529,28 @@ func (ec *executionContext) unmarshalOScopeHeaderInput2ᚖgithubᚗcomᚋdstotij return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalOSenderRequest2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequest(ctx context.Context, sel ast.SelectionSet, v *SenderRequest) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._SenderRequest(ctx, sel, v) +} + +func (ec *executionContext) marshalOSenderRequestFilter2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequestFilter(ctx context.Context, sel ast.SelectionSet, v *SenderRequestFilter) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._SenderRequestFilter(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOSenderRequestFilterInput2ᚖgithubᚗcomᚋdstotijnᚋhettyᚋpkgᚋapiᚐSenderRequestFilterInput(ctx context.Context, v interface{}) (*SenderRequestFilterInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputSenderRequestFilterInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOString2string(ctx context.Context, v interface{}) (string, error) { res, err := graphql.UnmarshalString(v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/pkg/api/models.go b/pkg/api/models.go index faa99ae..c0109c9 100644 --- a/pkg/api/models.go +++ b/pkg/api/models.go @@ -3,29 +3,49 @@ package api import ( "fmt" "io" + "net/url" "strconv" + "github.com/99designs/gqlgen/graphql" "github.com/oklog/ulid" ) -type ULID ulid.ULID +func MarshalULID(u ulid.ULID) graphql.Marshaler { + return graphql.WriterFunc(func(w io.Writer) { + fmt.Fprint(w, strconv.Quote(u.String())) + }) +} -func (u *ULID) UnmarshalGQL(v interface{}) (err error) { - str, ok := v.(string) +func UnmarshalULID(v interface{}) (ulid.ULID, error) { + rawULID, ok := v.(string) if !ok { - return fmt.Errorf("ulid must be a string") + return ulid.ULID{}, fmt.Errorf("ulid must be a string") } - id, err := ulid.Parse(str) + u, err := ulid.Parse(rawULID) if err != nil { - return fmt.Errorf("failed to parse ULID: %w", err) + return ulid.ULID{}, fmt.Errorf("failed to parse ULID: %w", err) } - *u = ULID(id) - - return nil + return u, nil } -func (u ULID) MarshalGQL(w io.Writer) { - fmt.Fprint(w, strconv.Quote(ulid.ULID(u).String())) +func MarshalURL(u *url.URL) graphql.Marshaler { + return graphql.WriterFunc(func(w io.Writer) { + fmt.Fprint(w, strconv.Quote(u.String())) + }) +} + +func UnmarshalURL(v interface{}) (*url.URL, error) { + rawURL, ok := v.(string) + if !ok { + return nil, fmt.Errorf("url must be a string") + } + + u, err := url.Parse(rawURL) + if err != nil { + return nil, fmt.Errorf("failed to parse URL: %w", err) + } + + return u, nil } diff --git a/pkg/api/models_gen.go b/pkg/api/models_gen.go index d365b81..5f32f68 100644 --- a/pkg/api/models_gen.go +++ b/pkg/api/models_gen.go @@ -5,8 +5,11 @@ package api import ( "fmt" "io" + "net/url" "strconv" "time" + + "github.com/oklog/ulid" ) type ClearHTTPRequestLogResult struct { @@ -21,13 +24,22 @@ type DeleteProjectResult struct { Success bool `json:"success"` } +type DeleteSenderRequestsResult struct { + Success bool `json:"success"` +} + type HTTPHeader struct { Key string `json:"key"` Value string `json:"value"` } +type HTTPHeaderInput struct { + Key string `json:"key"` + Value string `json:"value"` +} + type HTTPRequestLog struct { - ID ULID `json:"id"` + ID ulid.ULID `json:"id"` URL string `json:"url"` Method HTTPMethod `json:"method"` Proto string `json:"proto"` @@ -48,7 +60,9 @@ type HTTPRequestLogFilterInput struct { } type HTTPResponseLog struct { - Proto string `json:"proto"` + // Will be the same ID as its related request ID. + ID ulid.ULID `json:"id"` + Proto HTTPProtocol `json:"proto"` StatusCode int `json:"statusCode"` StatusReason string `json:"statusReason"` Body *string `json:"body"` @@ -56,9 +70,9 @@ type HTTPResponseLog struct { } type Project struct { - ID ULID `json:"id"` - Name string `json:"name"` - IsActive bool `json:"isActive"` + ID ulid.ULID `json:"id"` + Name string `json:"name"` + IsActive bool `json:"isActive"` } type ScopeHeader struct { @@ -83,6 +97,37 @@ type ScopeRuleInput struct { Body *string `json:"body"` } +type SenderRequest struct { + ID ulid.ULID `json:"id"` + SourceRequestLogID *ulid.ULID `json:"sourceRequestLogID"` + URL *url.URL `json:"url"` + Method HTTPMethod `json:"method"` + Proto HTTPProtocol `json:"proto"` + Headers []HTTPHeader `json:"headers"` + Body *string `json:"body"` + Timestamp time.Time `json:"timestamp"` + Response *HTTPResponseLog `json:"response"` +} + +type SenderRequestFilter struct { + OnlyInScope bool `json:"onlyInScope"` + SearchExpression *string `json:"searchExpression"` +} + +type SenderRequestFilterInput struct { + OnlyInScope *bool `json:"onlyInScope"` + SearchExpression *string `json:"searchExpression"` +} + +type SenderRequestInput struct { + ID *ulid.ULID `json:"id"` + URL *url.URL `json:"url"` + Method *HTTPMethod `json:"method"` + Proto *HTTPProtocol `json:"proto"` + Headers []HTTPHeaderInput `json:"headers"` + Body *string `json:"body"` +} + type HTTPMethod string const ( @@ -137,3 +182,44 @@ func (e *HTTPMethod) UnmarshalGQL(v interface{}) error { func (e HTTPMethod) MarshalGQL(w io.Writer) { fmt.Fprint(w, strconv.Quote(e.String())) } + +type HTTPProtocol string + +const ( + HTTPProtocolHTTP1 HTTPProtocol = "HTTP1" + HTTPProtocolHTTP2 HTTPProtocol = "HTTP2" +) + +var AllHTTPProtocol = []HTTPProtocol{ + HTTPProtocolHTTP1, + HTTPProtocolHTTP2, +} + +func (e HTTPProtocol) IsValid() bool { + switch e { + case HTTPProtocolHTTP1, HTTPProtocolHTTP2: + return true + } + return false +} + +func (e HTTPProtocol) String() string { + return string(e) +} + +func (e *HTTPProtocol) UnmarshalGQL(v interface{}) error { + str, ok := v.(string) + if !ok { + return fmt.Errorf("enums must be strings") + } + + *e = HTTPProtocol(str) + if !e.IsValid() { + return fmt.Errorf("%s is not a valid HttpProtocol", str) + } + return nil +} + +func (e HTTPProtocol) MarshalGQL(w io.Writer) { + fmt.Fprint(w, strconv.Quote(e.String())) +} diff --git a/pkg/api/resolvers.go b/pkg/api/resolvers.go index 31cdf8c..db3c8b9 100644 --- a/pkg/api/resolvers.go +++ b/pkg/api/resolvers.go @@ -6,6 +6,7 @@ import ( "context" "errors" "fmt" + "net/http" "regexp" "strings" @@ -17,11 +18,23 @@ import ( "github.com/dstotijn/hetty/pkg/reqlog" "github.com/dstotijn/hetty/pkg/scope" "github.com/dstotijn/hetty/pkg/search" + "github.com/dstotijn/hetty/pkg/sender" ) +var httpProtocolMap = map[string]HTTPProtocol{ + sender.HTTPProto1: HTTPProtocolHTTP1, + sender.HTTPProto2: HTTPProtocolHTTP2, +} + +var revHTTPProtocolMap = map[HTTPProtocol]string{ + HTTPProtocolHTTP1: sender.HTTPProto1, + HTTPProtocolHTTP2: sender.HTTPProto2, +} + type Resolver struct { ProjectService proj.Service - RequestLogService *reqlog.Service + RequestLogService reqlog.Service + SenderService sender.Service } type ( @@ -54,8 +67,8 @@ func (r *queryResolver) HTTPRequestLogs(ctx context.Context) ([]HTTPRequestLog, return logs, nil } -func (r *queryResolver) HTTPRequestLog(ctx context.Context, id ULID) (*HTTPRequestLog, error) { - log, err := r.RequestLogService.FindRequestLogByID(ctx, ulid.ULID(id)) +func (r *queryResolver) HTTPRequestLog(ctx context.Context, id ulid.ULID) (*HTTPRequestLog, error) { + log, err := r.RequestLogService.FindRequestLogByID(ctx, id) if errors.Is(err, reqlog.ErrRequestNotFound) { return nil, nil } else if err != nil { @@ -77,7 +90,7 @@ func parseRequestLog(reqLog reqlog.RequestLog) (HTTPRequestLog, error) { } log := HTTPRequestLog{ - ID: ULID(reqLog.ID), + ID: reqLog.ID, Proto: reqLog.Proto, Method: method, Timestamp: ulid.Time(reqLog.ID.Time()), @@ -106,36 +119,54 @@ func parseRequestLog(reqLog reqlog.RequestLog) (HTTPRequestLog, error) { } if reqLog.Response != nil { - log.Response = &HTTPResponseLog{ - Proto: reqLog.Response.Proto, - StatusCode: reqLog.Response.StatusCode, - } - statusReasonSubs := strings.SplitN(reqLog.Response.Status, " ", 2) - - if len(statusReasonSubs) == 2 { - log.Response.StatusReason = statusReasonSubs[1] + resLog, err := parseResponseLog(*reqLog.Response) + if err != nil { + return HTTPRequestLog{}, err } - if len(reqLog.Response.Body) > 0 { - bodyStr := string(reqLog.Response.Body) - log.Response.Body = &bodyStr - } + resLog.ID = reqLog.ID - if reqLog.Response.Header != nil { - log.Response.Headers = make([]HTTPHeader, 0) + log.Response = &resLog + } - for key, values := range reqLog.Response.Header { - for _, value := range values { - log.Response.Headers = append(log.Response.Headers, HTTPHeader{ - Key: key, - Value: value, - }) - } + return log, nil +} + +func parseResponseLog(resLog reqlog.ResponseLog) (HTTPResponseLog, error) { + proto := httpProtocolMap[resLog.Proto] + if !proto.IsValid() { + return HTTPResponseLog{}, fmt.Errorf("sender response has invalid protocol: %v", resLog.Proto) + } + + httpResLog := HTTPResponseLog{ + Proto: proto, + StatusCode: resLog.StatusCode, + } + statusReasonSubs := strings.SplitN(resLog.Status, " ", 2) + + if len(statusReasonSubs) == 2 { + httpResLog.StatusReason = statusReasonSubs[1] + } + + if len(resLog.Body) > 0 { + bodyStr := string(resLog.Body) + httpResLog.Body = &bodyStr + } + + if resLog.Header != nil { + httpResLog.Headers = make([]HTTPHeader, 0) + + for key, values := range resLog.Header { + for _, value := range values { + httpResLog.Headers = append(httpResLog.Headers, HTTPHeader{ + Key: key, + Value: value, + }) } } } - return log, nil + return httpResLog, nil } func (r *mutationResolver) CreateProject(ctx context.Context, name string) (*Project, error) { @@ -147,14 +178,14 @@ func (r *mutationResolver) CreateProject(ctx context.Context, name string) (*Pro } return &Project{ - ID: ULID(p.ID), + ID: p.ID, Name: p.Name, IsActive: r.ProjectService.IsProjectActive(p.ID), }, nil } -func (r *mutationResolver) OpenProject(ctx context.Context, id ULID) (*Project, error) { - p, err := r.ProjectService.OpenProject(ctx, ulid.ULID(id)) +func (r *mutationResolver) OpenProject(ctx context.Context, id ulid.ULID) (*Project, error) { + p, err := r.ProjectService.OpenProject(ctx, id) if errors.Is(err, proj.ErrInvalidName) { return nil, gqlerror.Errorf("Project name must only contain alphanumeric or space chars.") } else if err != nil { @@ -162,7 +193,7 @@ func (r *mutationResolver) OpenProject(ctx context.Context, id ULID) (*Project, } return &Project{ - ID: ULID(p.ID), + ID: p.ID, Name: p.Name, IsActive: r.ProjectService.IsProjectActive(p.ID), }, nil @@ -177,7 +208,7 @@ func (r *queryResolver) ActiveProject(ctx context.Context) (*Project, error) { } return &Project{ - ID: ULID(p.ID), + ID: p.ID, Name: p.Name, IsActive: r.ProjectService.IsProjectActive(p.ID), }, nil @@ -192,7 +223,7 @@ func (r *queryResolver) Projects(ctx context.Context) ([]Project, error) { projects := make([]Project, len(p)) for i, proj := range p { projects[i] = Project{ - ID: ULID(proj.ID), + ID: proj.ID, Name: proj.Name, IsActive: r.ProjectService.IsProjectActive(proj.ID), } @@ -224,8 +255,8 @@ func (r *mutationResolver) CloseProject(ctx context.Context) (*CloseProjectResul return &CloseProjectResult{true}, nil } -func (r *mutationResolver) DeleteProject(ctx context.Context, id ULID) (*DeleteProjectResult, error) { - if err := r.ProjectService.DeleteProject(ctx, ulid.ULID(id)); err != nil { +func (r *mutationResolver) DeleteProject(ctx context.Context, id ulid.ULID) (*DeleteProjectResult, error) { + if err := r.ProjectService.DeleteProject(ctx, id); err != nil { return nil, fmt.Errorf("could not delete project: %w", err) } @@ -296,7 +327,7 @@ func (r *mutationResolver) SetScope(ctx context.Context, input []ScopeRuleInput) } func (r *queryResolver) HTTPRequestLogFilter(ctx context.Context) (*HTTPRequestLogFilter, error) { - return findReqFilterToHTTPReqLogFilter(r.RequestLogService.FindReqsFilter), nil + return findReqFilterToHTTPReqLogFilter(r.RequestLogService.FindReqsFilter()), nil } func (r *mutationResolver) SetHTTPRequestLogFilter( @@ -318,6 +349,221 @@ func (r *mutationResolver) SetHTTPRequestLogFilter( return findReqFilterToHTTPReqLogFilter(filter), nil } +func (r *queryResolver) SenderRequest(ctx context.Context, id ulid.ULID) (*SenderRequest, error) { + senderReq, err := r.SenderService.FindRequestByID(ctx, id) + if errors.Is(err, sender.ErrRequestNotFound) { + return nil, nil + } else if err != nil { + return nil, fmt.Errorf("could not get request by ID: %w", err) + } + + req, err := parseSenderRequest(senderReq) + if err != nil { + return nil, err + } + + return &req, nil +} + +func (r *queryResolver) SenderRequests(ctx context.Context) ([]SenderRequest, error) { + reqs, err := r.SenderService.FindRequests(ctx) + if errors.Is(err, proj.ErrNoProject) { + return nil, noActiveProjectErr(ctx) + } else if err != nil { + return nil, fmt.Errorf("failed to find sender requests: %w", err) + } + + senderReqs := make([]SenderRequest, len(reqs)) + + for i, req := range reqs { + req, err := parseSenderRequest(req) + if err != nil { + return nil, err + } + + senderReqs[i] = req + } + + return senderReqs, nil +} + +func (r *mutationResolver) SetSenderRequestFilter( + ctx context.Context, + input *SenderRequestFilterInput, +) (*SenderRequestFilter, error) { + filter, err := findSenderRequestsFilterFromInput(input) + if err != nil { + return nil, fmt.Errorf("could not parse request log filter: %w", err) + } + + err = r.ProjectService.SetSenderRequestFindFilter(ctx, filter) + if errors.Is(err, proj.ErrNoProject) { + return nil, noActiveProjectErr(ctx) + } else if err != nil { + return nil, fmt.Errorf("could not set request log filter: %w", err) + } + + return findReqFilterToSenderReqFilter(filter), nil +} + +func (r *mutationResolver) CreateOrUpdateSenderRequest(ctx context.Context, input SenderRequestInput) (*SenderRequest, error) { + req := sender.Request{ + URL: input.URL, + Header: make(http.Header), + } + + if input.ID != nil { + req.ID = *input.ID + } + + if input.Method != nil { + req.Method = input.Method.String() + } + + if input.Proto != nil { + req.Proto = revHTTPProtocolMap[*input.Proto] + } + + for _, header := range input.Headers { + req.Header.Add(header.Key, header.Value) + } + + if input.Body != nil { + req.Body = []byte(*input.Body) + } + + req, err := r.SenderService.CreateOrUpdateRequest(ctx, req) + if errors.Is(err, proj.ErrNoProject) { + return nil, noActiveProjectErr(ctx) + } else if err != nil { + return nil, fmt.Errorf("could not create sender request: %w", err) + } + + senderReq, err := parseSenderRequest(req) + if err != nil { + return nil, err + } + + return &senderReq, nil +} + +func (r *mutationResolver) CreateSenderRequestFromHTTPRequestLog(ctx context.Context, id ulid.ULID) (*SenderRequest, error) { + req, err := r.SenderService.CloneFromRequestLog(ctx, id) + if errors.Is(err, proj.ErrNoProject) { + return nil, noActiveProjectErr(ctx) + } else if err != nil { + return nil, fmt.Errorf("could not create sender request from http request log: %w", err) + } + + senderReq, err := parseSenderRequest(req) + if err != nil { + return nil, err + } + + return &senderReq, nil +} + +func (r *mutationResolver) SendRequest(ctx context.Context, id ulid.ULID) (*SenderRequest, error) { + // Use new context, because we don't want to risk interrupting sending the request + // or the subsequent storing of the response, e.g. if ctx gets cancelled or + // times out. + ctx2 := context.Background() + + var sendErr *sender.SendError + + req, err := r.SenderService.SendRequest(ctx2, id) + if errors.Is(err, proj.ErrNoProject) { + return nil, noActiveProjectErr(ctx) + } else if errors.As(err, &sendErr) { + return nil, &gqlerror.Error{ + Path: graphql.GetPath(ctx), + Message: fmt.Sprintf("Sending request failed: %v", sendErr.Unwrap()), + Extensions: map[string]interface{}{ + "code": "send_request_failed", + }, + } + } else if err != nil { + return nil, fmt.Errorf("could not send request: %w", err) + } + + senderReq, err := parseSenderRequest(req) + if err != nil { + return nil, err + } + + return &senderReq, nil +} + +func (r *mutationResolver) DeleteSenderRequests(ctx context.Context) (*DeleteSenderRequestsResult, error) { + project, err := r.ProjectService.ActiveProject(ctx) + if errors.Is(err, proj.ErrNoProject) { + return nil, noActiveProjectErr(ctx) + } else if err != nil { + return nil, fmt.Errorf("could not get active project: %w", err) + } + + if err := r.SenderService.DeleteRequests(ctx, project.ID); err != nil { + return nil, fmt.Errorf("could not clear request log: %w", err) + } + + return &DeleteSenderRequestsResult{true}, nil +} + +func parseSenderRequest(req sender.Request) (SenderRequest, error) { + method := HTTPMethod(req.Method) + if method != "" && !method.IsValid() { + return SenderRequest{}, fmt.Errorf("sender request has invalid method: %v", method) + } + + reqProto := httpProtocolMap[req.Proto] + if !reqProto.IsValid() { + return SenderRequest{}, fmt.Errorf("sender request has invalid protocol: %v", req.Proto) + } + + senderReq := SenderRequest{ + ID: req.ID, + URL: req.URL, + Method: method, + Proto: HTTPProtocol(req.Proto), + Timestamp: ulid.Time(req.ID.Time()), + } + + if req.SourceRequestLogID.Compare(ulid.ULID{}) != 0 { + senderReq.SourceRequestLogID = &req.SourceRequestLogID + } + + if req.Header != nil { + senderReq.Headers = make([]HTTPHeader, 0) + + for key, values := range req.Header { + for _, value := range values { + senderReq.Headers = append(senderReq.Headers, HTTPHeader{ + Key: key, + Value: value, + }) + } + } + } + + if len(req.Body) > 0 { + bodyStr := string(req.Body) + senderReq.Body = &bodyStr + } + + if req.Response != nil { + resLog, err := parseResponseLog(*req.Response) + if err != nil { + return SenderRequest{}, err + } + + resLog.ID = req.ID + + senderReq.Response = &resLog + } + + return senderReq, nil +} + func stringPtrToRegexp(s *string) (*regexp.Regexp, error) { if s == nil { return nil, nil @@ -364,6 +610,27 @@ func findRequestsFilterFromInput(input *HTTPRequestLogFilterInput) (filter reqlo return } +func findSenderRequestsFilterFromInput(input *SenderRequestFilterInput) (filter sender.FindRequestsFilter, err error) { + if input == nil { + return + } + + if input.OnlyInScope != nil { + filter.OnlyInScope = *input.OnlyInScope + } + + if input.SearchExpression != nil && *input.SearchExpression != "" { + expr, err := search.ParseQuery(*input.SearchExpression) + if err != nil { + return sender.FindRequestsFilter{}, fmt.Errorf("could not parse search query: %w", err) + } + + filter.SearchExpr = expr + } + + return +} + func findReqFilterToHTTPReqLogFilter(findReqFilter reqlog.FindRequestsFilter) *HTTPRequestLogFilter { empty := reqlog.FindRequestsFilter{} if findReqFilter == empty { @@ -382,6 +649,24 @@ func findReqFilterToHTTPReqLogFilter(findReqFilter reqlog.FindRequestsFilter) *H return httpReqLogFilter } +func findReqFilterToSenderReqFilter(findReqFilter sender.FindRequestsFilter) *SenderRequestFilter { + empty := sender.FindRequestsFilter{} + if findReqFilter == empty { + return nil + } + + senderReqFilter := &SenderRequestFilter{ + OnlyInScope: findReqFilter.OnlyInScope, + } + + if findReqFilter.SearchExpr != nil { + searchExpr := findReqFilter.SearchExpr.String() + senderReqFilter.SearchExpression = &searchExpr + } + + return senderReqFilter +} + func noActiveProjectErr(ctx context.Context) error { return &gqlerror.Error{ Path: graphql.GetPath(ctx), diff --git a/pkg/api/schema.graphql b/pkg/api/schema.graphql index 1ba1ed6..33e63d3 100644 --- a/pkg/api/schema.graphql +++ b/pkg/api/schema.graphql @@ -10,7 +10,11 @@ type HttpRequestLog { } type HttpResponseLog { - proto: String! + """ + Will be the same ID as its related request ID. + """ + id: ID! + proto: HttpProtocol! statusCode: Int! statusReason: String! body: String @@ -62,6 +66,10 @@ type ClearHTTPRequestLogResult { success: Boolean! } +type DeleteSenderRequestsResult { + success: Boolean! +} + input HttpRequestLogFilterInput { onlyInScope: Boolean searchExpression: String @@ -72,6 +80,42 @@ type HttpRequestLogFilter { searchExpression: String } +input SenderRequestInput { + id: ID + url: URL! + method: HttpMethod + proto: HttpProtocol + headers: [HttpHeaderInput!] + body: String +} + +input HttpHeaderInput { + key: String! + value: String! +} + +type SenderRequest { + id: ID! + sourceRequestLogID: ID + url: URL! + method: HttpMethod! + proto: HttpProtocol! + headers: [HttpHeader!] + body: String + timestamp: Time! + response: HttpResponseLog +} + +input SenderRequestFilterInput { + onlyInScope: Boolean + searchExpression: String +} + +type SenderRequestFilter { + onlyInScope: Boolean! + searchExpression: String +} + type Query { httpRequestLog(id: ID!): HttpRequestLog httpRequestLogs: [HttpRequestLog!]! @@ -79,6 +123,8 @@ type Query { activeProject: Project projects: [Project!]! scope: [ScopeRule!]! + senderRequest(id: ID!): SenderRequest + senderRequests: [SenderRequest!]! } type Mutation { @@ -91,6 +137,11 @@ type Mutation { setHttpRequestLogFilter( filter: HttpRequestLogFilterInput ): HttpRequestLogFilter + setSenderRequestFilter(filter: SenderRequestFilterInput): SenderRequestFilter + createOrUpdateSenderRequest(request: SenderRequestInput!): SenderRequest! + createSenderRequestFromHttpRequestLog(id: ID!): SenderRequest! + sendRequest(id: ID!): SenderRequest! + deleteSenderRequests: DeleteSenderRequestsResult! } enum HttpMethod { @@ -105,5 +156,11 @@ enum HttpMethod { PATCH } +enum HttpProtocol { + HTTP1 + HTTP2 +} + scalar Time scalar Regexp +scalar URL diff --git a/pkg/db/badger/badger.go b/pkg/db/badger/badger.go index 16a19f6..696eeac 100644 --- a/pkg/db/badger/badger.go +++ b/pkg/db/badger/badger.go @@ -8,12 +8,16 @@ import ( const ( // Key prefixes. Each prefix value should be unique. - projectPrefix = 0x00 - reqLogPrefix = 0x01 - resLogPrefix = 0x02 + projectPrefix = 0x00 + reqLogPrefix = 0x01 + resLogPrefix = 0x02 + senderReqPrefix = 0x03 // Request log indices. reqLogProjectIDIndex = 0x00 + + // Sender request indices. + senderReqProjectIDIndex = 0x00 ) // Database is used to store and retrieve data from an underlying Badger database. diff --git a/pkg/db/badger/proj.go b/pkg/db/badger/proj.go index 4b802df..699767d 100644 --- a/pkg/db/badger/proj.go +++ b/pkg/db/badger/proj.go @@ -65,6 +65,11 @@ func (db *Database) DeleteProject(ctx context.Context, projectID ulid.ULID) erro return fmt.Errorf("badger: failed to delete project request logs: %w", err) } + err = db.DeleteSenderRequests(ctx, projectID) + if err != nil { + return fmt.Errorf("badger: failed to delete project sender requests: %w", err) + } + err = db.badger.Update(func(txn *badger.Txn) error { return txn.Delete(entryKey(projectPrefix, 0, projectID[:])) }) diff --git a/pkg/db/badger/proj_test.go b/pkg/db/badger/proj_test.go index ff374f3..9e83b2a 100644 --- a/pkg/db/badger/proj_test.go +++ b/pkg/db/badger/proj_test.go @@ -56,6 +56,7 @@ func TestUpsertProject(t *testing.T) { Settings: proj.Settings{ ReqLogBypassOutOfScope: true, ReqLogOnlyFindInScope: true, + ReqLogSearchExpr: searchExpr, ScopeRules: []scope.Rule{ { URL: regexp.MustCompile("^https://(.*)example.com(.*)$"), @@ -66,7 +67,6 @@ func TestUpsertProject(t *testing.T) { Body: regexp.MustCompile("^foo(.*)"), }, }, - SearchExpr: searchExpr, }, } @@ -178,21 +178,38 @@ func TestDeleteProject(t *testing.T) { // Store fixtures. projectID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) reqLogID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) + senderReqID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) err = badgerDB.Update(func(txn *badgerdb.Txn) error { + // Project item. if err := txn.Set(entryKey(projectPrefix, 0, projectID[:]), nil); err != nil { return err } + + // Sender request items. + if err := txn.Set(entryKey(senderReqPrefix, 0, senderReqID[:]), nil); err != nil { + return err + } + if err := txn.Set(entryKey(resLogPrefix, 0, senderReqID[:]), nil); err != nil { + return err + } + err := txn.Set(entryKey(senderReqPrefix, senderReqProjectIDIndex, append(projectID[:], senderReqID[:]...)), nil) + if err != nil { + return err + } + + // Request log items. if err := txn.Set(entryKey(reqLogPrefix, 0, reqLogID[:]), nil); err != nil { return err } if err := txn.Set(entryKey(resLogPrefix, 0, reqLogID[:]), nil); err != nil { return err } - err := txn.Set(entryKey(reqLogPrefix, reqLogProjectIDIndex, append(projectID[:], reqLogID[:]...)), nil) + err = txn.Set(entryKey(reqLogPrefix, reqLogProjectIDIndex, append(projectID[:], reqLogID[:]...)), nil) if err != nil { return err } + return nil }) if err != nil { @@ -222,7 +239,7 @@ func TestDeleteProject(t *testing.T) { t.Fatalf("expected `badger.ErrKeyNotFound`, got: %v", err) } - // Assert response log item was deleted. + // Assert response log item related to request log was deleted. err = badgerDB.View(func(txn *badgerdb.Txn) error { _, err := txn.Get(entryKey(resLogPrefix, 0, reqLogID[:])) return err @@ -239,6 +256,33 @@ func TestDeleteProject(t *testing.T) { if !errors.Is(err, badgerdb.ErrKeyNotFound) { t.Fatalf("expected `badger.ErrKeyNotFound`, got: %v", err) } + + // Assert sender request item was deleted. + err = badgerDB.View(func(txn *badgerdb.Txn) error { + _, err := txn.Get(entryKey(senderReqPrefix, 0, senderReqID[:])) + return err + }) + if !errors.Is(err, badgerdb.ErrKeyNotFound) { + t.Fatalf("expected `badger.ErrKeyNotFound`, got: %v", err) + } + + // Assert response log item related to sender request was deleted. + err = badgerDB.View(func(txn *badgerdb.Txn) error { + _, err := txn.Get(entryKey(resLogPrefix, 0, senderReqID[:])) + return err + }) + if !errors.Is(err, badgerdb.ErrKeyNotFound) { + t.Fatalf("expected `badger.ErrKeyNotFound`, got: %v", err) + } + + // Assert sender request project ID index key was deleted. + err = badgerDB.View(func(txn *badgerdb.Txn) error { + _, err := txn.Get(entryKey(senderReqPrefix, senderReqProjectIDIndex, append(projectID[:], senderReqID[:]...))) + return err + }) + if !errors.Is(err, badgerdb.ErrKeyNotFound) { + t.Fatalf("expected `badger.ErrKeyNotFound`, got: %v", err) + } } func TestProjects(t *testing.T) { diff --git a/pkg/db/badger/reqlog.go b/pkg/db/badger/reqlog.go index 6a8a1dc..4ce64f2 100644 --- a/pkg/db/badger/reqlog.go +++ b/pkg/db/badger/reqlog.go @@ -66,7 +66,11 @@ func (db *Database) FindRequestLogs(ctx context.Context, filter reqlog.FindReque func getRequestLogWithResponse(txn *badger.Txn, reqLogID ulid.ULID) (reqlog.RequestLog, error) { item, err := txn.Get(entryKey(reqLogPrefix, 0, reqLogID[:])) - if err != nil { + + switch { + case errors.Is(err, badger.ErrKeyNotFound): + return reqlog.RequestLog{}, reqlog.ErrRequestNotFound + case err != nil: return reqlog.RequestLog{}, fmt.Errorf("failed to lookup request log item: %w", err) } diff --git a/pkg/db/badger/sender.go b/pkg/db/badger/sender.go new file mode 100644 index 0000000..b224a12 --- /dev/null +++ b/pkg/db/badger/sender.go @@ -0,0 +1,236 @@ +package badger + +import ( + "bytes" + "context" + "encoding/gob" + "errors" + "fmt" + + "github.com/dgraph-io/badger/v3" + "github.com/oklog/ulid" + + "github.com/dstotijn/hetty/pkg/reqlog" + "github.com/dstotijn/hetty/pkg/scope" + "github.com/dstotijn/hetty/pkg/sender" +) + +func (db *Database) StoreSenderRequest(ctx context.Context, req sender.Request) error { + buf := bytes.Buffer{} + + err := gob.NewEncoder(&buf).Encode(req) + if err != nil { + return fmt.Errorf("badger: failed to encode sender request: %w", err) + } + + entries := []*badger.Entry{ + // Sender request itself. + { + Key: entryKey(senderReqPrefix, 0, req.ID[:]), + Value: buf.Bytes(), + }, + // Index by project ID. + { + Key: entryKey(senderReqPrefix, senderReqProjectIDIndex, append(req.ProjectID[:], req.ID[:]...)), + }, + } + + err = db.badger.Update(func(txn *badger.Txn) error { + for i := range entries { + err := txn.SetEntry(entries[i]) + if err != nil { + return err + } + } + return nil + }) + if err != nil { + return fmt.Errorf("badger: failed to commit transaction: %w", err) + } + + return nil +} + +func (db *Database) FindSenderRequestByID(ctx context.Context, senderReqID ulid.ULID) (sender.Request, error) { + txn := db.badger.NewTransaction(false) + defer txn.Discard() + + req, err := getSenderRequestWithResponseLog(txn, senderReqID) + if err != nil { + return sender.Request{}, fmt.Errorf("badger: failed to get sender request: %w", err) + } + + return req, nil +} + +func (db *Database) FindSenderRequests(ctx context.Context, filter sender.FindRequestsFilter, scope *scope.Scope) ([]sender.Request, error) { + if filter.ProjectID.Compare(ulid.ULID{}) == 0 { + return nil, sender.ErrProjectIDMustBeSet + } + + txn := db.badger.NewTransaction(false) + defer txn.Discard() + + senderReqIDs, err := findSenderRequestIDsByProjectID(txn, filter.ProjectID) + if err != nil { + return nil, fmt.Errorf("badger: failed to find sender request IDs: %w", err) + } + + senderReqs := make([]sender.Request, 0, len(senderReqIDs)) + + for _, id := range senderReqIDs { + senderReq, err := getSenderRequestWithResponseLog(txn, id) + if err != nil { + return nil, fmt.Errorf("badger: failed to get sender request (id: %v): %w", id.String(), err) + } + + if filter.OnlyInScope { + if !senderReq.MatchScope(scope) { + continue + } + } + + // Filter by search expression. + // TODO: Once pagination is introduced, this filter logic should be done + // as items are retrieved (e.g. when using a `badger.Iterator`). + if filter.SearchExpr != nil { + match, err := senderReq.Matches(filter.SearchExpr) + if err != nil { + return nil, fmt.Errorf( + "badger: failed to match search expression for sender request (id: %v): %w", + id.String(), err, + ) + } + + if !match { + continue + } + } + + senderReqs = append(senderReqs, senderReq) + } + + return senderReqs, nil +} + +func (db *Database) DeleteSenderRequests(ctx context.Context, projectID ulid.ULID) error { + // Note: this transaction is used just for reading; we use the `badger.WriteBatch` + // API to bulk delete items. + txn := db.badger.NewTransaction(false) + defer txn.Discard() + + senderReqIDs, err := findSenderRequestIDsByProjectID(txn, projectID) + if err != nil { + return fmt.Errorf("badger: failed to find sender request IDs: %w", err) + } + + writeBatch := db.badger.NewWriteBatch() + defer writeBatch.Cancel() + + for _, senderReqID := range senderReqIDs { + // Delete sender requests. + err := writeBatch.Delete(entryKey(senderReqPrefix, 0, senderReqID[:])) + if err != nil { + return fmt.Errorf("badger: failed to delete sender requests: %w", err) + } + + // Delete related response log. + err = writeBatch.Delete(entryKey(resLogPrefix, 0, senderReqID[:])) + if err != nil { + return fmt.Errorf("badger: failed to delete request log: %w", err) + } + } + + if err := writeBatch.Flush(); err != nil { + return fmt.Errorf("badger: failed to commit batch write: %w", err) + } + + err = db.badger.DropPrefix(entryKey(senderReqPrefix, senderReqProjectIDIndex, projectID[:])) + if err != nil { + return fmt.Errorf("badger: failed to drop sender request project ID index items: %w", err) + } + + return nil +} + +func getSenderRequestWithResponseLog(txn *badger.Txn, senderReqID ulid.ULID) (sender.Request, error) { + item, err := txn.Get(entryKey(senderReqPrefix, 0, senderReqID[:])) + + switch { + case errors.Is(err, badger.ErrKeyNotFound): + return sender.Request{}, sender.ErrRequestNotFound + case err != nil: + return sender.Request{}, fmt.Errorf("failed to lookup sender request item: %w", err) + } + + req := sender.Request{ + ID: senderReqID, + } + + err = item.Value(func(rawSenderReq []byte) error { + err = gob.NewDecoder(bytes.NewReader(rawSenderReq)).Decode(&req) + if err != nil { + return fmt.Errorf("failed to decode sender request: %w", err) + } + + return nil + }) + if err != nil { + return sender.Request{}, fmt.Errorf("failed to retrieve or parse sender request value: %w", err) + } + + item, err = txn.Get(entryKey(resLogPrefix, 0, senderReqID[:])) + + if errors.Is(err, badger.ErrKeyNotFound) { + return req, nil + } + + if err != nil { + return sender.Request{}, fmt.Errorf("failed to get response log: %w", err) + } + + err = item.Value(func(rawReslog []byte) error { + var resLog reqlog.ResponseLog + err = gob.NewDecoder(bytes.NewReader(rawReslog)).Decode(&resLog) + if err != nil { + return fmt.Errorf("failed to decode response log: %w", err) + } + + req.Response = &resLog + + return nil + }) + if err != nil { + return sender.Request{}, fmt.Errorf("failed to retrieve or parse response log value: %w", err) + } + + return req, nil +} + +func findSenderRequestIDsByProjectID(txn *badger.Txn, projectID ulid.ULID) ([]ulid.ULID, error) { + senderReqIDs := make([]ulid.ULID, 0) + opts := badger.DefaultIteratorOptions + opts.PrefetchValues = false + opts.Reverse = true + iterator := txn.NewIterator(opts) + defer iterator.Close() + + var projectIndexKey []byte + + prefix := entryKey(senderReqPrefix, senderReqProjectIDIndex, projectID[:]) + + for iterator.Seek(append(prefix, 255)); iterator.ValidForPrefix(prefix); iterator.Next() { + projectIndexKey = iterator.Item().KeyCopy(projectIndexKey) + + var id ulid.ULID + // The request log ID starts *after* the first 2 prefix and index bytes + // and the 16 byte project ID. + if err := id.UnmarshalBinary(projectIndexKey[18:]); err != nil { + return nil, fmt.Errorf("failed to parse sender request ID: %w", err) + } + + senderReqIDs = append(senderReqIDs, id) + } + + return senderReqIDs, nil +} diff --git a/pkg/db/badger/sender_test.go b/pkg/db/badger/sender_test.go new file mode 100644 index 0000000..99810cc --- /dev/null +++ b/pkg/db/badger/sender_test.go @@ -0,0 +1,204 @@ +package badger_test + +import ( + "context" + "errors" + "math/rand" + "net/http" + "net/url" + "testing" + "time" + + badgerdb "github.com/dgraph-io/badger/v3" + "github.com/google/go-cmp/cmp" + "github.com/oklog/ulid" + + "github.com/dstotijn/hetty/pkg/db/badger" + "github.com/dstotijn/hetty/pkg/reqlog" + "github.com/dstotijn/hetty/pkg/sender" +) + +//nolint:gosec +var ulidEntropy = rand.New(rand.NewSource(time.Now().UnixNano())) + +var exampleURL = func() *url.URL { + u, err := url.Parse("https://example.com/foobar") + if err != nil { + panic(err) + } + + return u +}() + +func TestFindRequestByID(t *testing.T) { + t.Parallel() + + database, err := badger.OpenDatabase(badgerdb.DefaultOptions("").WithInMemory(true)) + if err != nil { + t.Fatalf("failed to open badger database: %v", err) + } + defer database.Close() + + // See: https://go.dev/blog/subtests#cleaning-up-after-a-group-of-parallel-tests + t.Run("group", func(t *testing.T) { + t.Run("sender request not found", func(t *testing.T) { + t.Parallel() + + _, err := database.FindSenderRequestByID(context.Background(), ulid.ULID{}) + if !errors.Is(err, sender.ErrRequestNotFound) { + t.Fatalf("expected `sender.ErrRequestNotFound`, got: %v", err) + } + }) + + t.Run("sender request found", func(t *testing.T) { + t.Parallel() + + exp := sender.Request{ + ID: ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy), + ProjectID: ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy), + SourceRequestLogID: ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy), + + URL: exampleURL, + Method: http.MethodGet, + Proto: sender.HTTPProto2, + Header: http.Header{ + "X-Foo": []string{"bar"}, + }, + Body: []byte("foo"), + } + + err := database.StoreSenderRequest(context.Background(), exp) + if err != nil { + t.Fatalf("unexpected error (expected: nil, got: %v)", err) + } + + resLog := reqlog.ResponseLog{ + Proto: "HTTP/2.0", + Status: "200 OK", + StatusCode: 200, + Header: http.Header{ + "X-Yolo": []string{"swag"}, + }, + Body: []byte("bar"), + } + + err = database.StoreResponseLog(context.Background(), exp.ID, resLog) + if err != nil { + t.Fatalf("unexpected error (expected: nil, got: %v)", err) + } + + exp.Response = &resLog + + got, err := database.FindSenderRequestByID(context.Background(), exp.ID) + if err != nil { + t.Fatalf("unexpected error (expected: nil, got: %v)", err) + } + + if diff := cmp.Diff(exp, got); diff != "" { + t.Fatalf("sender request not equal (-exp, +got):\n%v", diff) + } + }) + }) +} + +func TestFindSenderRequests(t *testing.T) { + t.Parallel() + + t.Run("without project ID in filter", func(t *testing.T) { + t.Parallel() + + database, err := badger.OpenDatabase(badgerdb.DefaultOptions("").WithInMemory(true)) + if err != nil { + t.Fatalf("failed to open badger database: %v", err) + } + defer database.Close() + + filter := sender.FindRequestsFilter{} + + _, err = database.FindSenderRequests(context.Background(), filter, nil) + if !errors.Is(err, sender.ErrProjectIDMustBeSet) { + t.Fatalf("expected `sender.ErrProjectIDMustBeSet`, got: %v", err) + } + }) + + t.Run("returns sender requests and related response logs", func(t *testing.T) { + t.Parallel() + + database, err := badger.OpenDatabase(badgerdb.DefaultOptions("").WithInMemory(true)) + if err != nil { + t.Fatalf("failed to open badger database: %v", err) + } + defer database.Close() + + projectID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) + + fixtures := []sender.Request{ + { + ID: ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy), + ProjectID: projectID, + SourceRequestLogID: ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy), + URL: exampleURL, + Method: http.MethodPost, + Proto: "HTTP/1.1", + Header: http.Header{ + "X-Foo": []string{"baz"}, + }, + Body: []byte("foo"), + Response: &reqlog.ResponseLog{ + Proto: "HTTP/1.1", + Status: "200 OK", + StatusCode: 200, + Header: http.Header{ + "X-Yolo": []string{"swag"}, + }, + Body: []byte("bar"), + }, + }, + { + ID: ulid.MustNew(ulid.Timestamp(time.Now())+100, ulidEntropy), + ProjectID: projectID, + SourceRequestLogID: ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy), + URL: exampleURL, + Method: http.MethodGet, + Proto: "HTTP/1.1", + Header: http.Header{ + "X-Foo": []string{"baz"}, + }, + }, + } + + // Store fixtures. + for _, senderReq := range fixtures { + err = database.StoreSenderRequest(context.Background(), senderReq) + if err != nil { + t.Fatalf("unexpected error creating request log fixture: %v", err) + } + + if senderReq.Response != nil { + err = database.StoreResponseLog(context.Background(), senderReq.ID, *senderReq.Response) + if err != nil { + t.Fatalf("unexpected error creating response log fixture: %v", err) + } + } + } + + filter := sender.FindRequestsFilter{ + ProjectID: projectID, + } + + got, err := database.FindSenderRequests(context.Background(), filter, nil) + if err != nil { + t.Fatalf("unexpected error finding sender requests: %v", err) + } + + // We expect the found sender requests are *reversed*, e.g. newest first. + exp := make([]sender.Request, len(fixtures)) + for i, j := 0, len(fixtures)-1; i < j; i, j = i+1, j-1 { + exp[i], exp[j] = fixtures[j], fixtures[i] + } + + if diff := cmp.Diff(exp, got); diff != "" { + t.Fatalf("sender requests not equal (-exp, +got):\n%v", diff) + } + }) +} diff --git a/pkg/proj/proj.go b/pkg/proj/proj.go index c808a35..fa9b7ac 100644 --- a/pkg/proj/proj.go +++ b/pkg/proj/proj.go @@ -15,6 +15,7 @@ import ( "github.com/dstotijn/hetty/pkg/reqlog" "github.com/dstotijn/hetty/pkg/scope" "github.com/dstotijn/hetty/pkg/search" + "github.com/dstotijn/hetty/pkg/sender" ) //nolint:gosec @@ -37,13 +38,15 @@ type Service interface { Scope() *scope.Scope SetScopeRules(ctx context.Context, rules []scope.Rule) error SetRequestLogFindFilter(ctx context.Context, filter reqlog.FindRequestsFilter) error + SetSenderRequestFindFilter(ctx context.Context, filter sender.FindRequestsFilter) error OnProjectOpen(fn OnProjectOpenFn) OnProjectClose(fn OnProjectCloseFn) } type service struct { repo Repository - reqLogSvc *reqlog.Service + reqLogSvc reqlog.Service + senderSvc sender.Service scope *scope.Scope activeProjectID ulid.ULID onProjectOpenFns []OnProjectOpenFn @@ -62,8 +65,12 @@ type Project struct { type Settings struct { ReqLogBypassOutOfScope bool ReqLogOnlyFindInScope bool - ScopeRules []scope.Rule - SearchExpr search.Expression + ReqLogSearchExpr search.Expression + + SenderOnlyFindInScope bool + SenderSearchExpr search.Expression + + ScopeRules []scope.Rule } var ( @@ -77,7 +84,8 @@ var nameRegexp = regexp.MustCompile(`^[\w\d\s]+$`) type Config struct { Repository Repository - ReqLogService *reqlog.Service + ReqLogService reqlog.Service + SenderService sender.Service Scope *scope.Scope } @@ -86,6 +94,7 @@ func NewService(cfg Config) (Service, error) { return &service{ repo: cfg.Repository, reqLogSvc: cfg.ReqLogService, + senderSvc: cfg.SenderService, scope: cfg.Scope, }, nil } @@ -120,9 +129,11 @@ func (svc *service) CloseProject() error { closedProjectID := svc.activeProjectID svc.activeProjectID = ulid.ULID{} - svc.reqLogSvc.ActiveProjectID = ulid.ULID{} - svc.reqLogSvc.BypassOutOfScopeRequests = false - svc.reqLogSvc.FindReqsFilter = reqlog.FindRequestsFilter{} + svc.reqLogSvc.SetActiveProjectID(ulid.ULID{}) + svc.reqLogSvc.SetBypassOutOfScopeRequests(false) + svc.reqLogSvc.SetFindReqsFilter(reqlog.FindRequestsFilter{}) + svc.senderSvc.SetActiveProjectID(ulid.ULID{}) + svc.senderSvc.SetFindReqsFilter(sender.FindRequestsFilter{}) svc.scope.SetRules(nil) svc.emitProjectClosed(closedProjectID) @@ -154,13 +165,21 @@ func (svc *service) OpenProject(ctx context.Context, projectID ulid.ULID) (Proje } svc.activeProjectID = project.ID - svc.reqLogSvc.FindReqsFilter = reqlog.FindRequestsFilter{ + + svc.reqLogSvc.SetFindReqsFilter(reqlog.FindRequestsFilter{ ProjectID: project.ID, OnlyInScope: project.Settings.ReqLogOnlyFindInScope, - SearchExpr: project.Settings.SearchExpr, - } - svc.reqLogSvc.BypassOutOfScopeRequests = project.Settings.ReqLogBypassOutOfScope - svc.reqLogSvc.ActiveProjectID = project.ID + SearchExpr: project.Settings.ReqLogSearchExpr, + }) + svc.reqLogSvc.SetBypassOutOfScopeRequests(project.Settings.ReqLogBypassOutOfScope) + svc.reqLogSvc.SetActiveProjectID(project.ID) + + svc.senderSvc.SetActiveProjectID(project.ID) + svc.senderSvc.SetFindReqsFilter(sender.FindRequestsFilter{ + ProjectID: project.ID, + OnlyInScope: project.Settings.SenderOnlyFindInScope, + SearchExpr: project.Settings.SenderSearchExpr, + }) svc.scope.SetRules(project.Settings.ScopeRules) @@ -255,14 +274,35 @@ func (svc *service) SetRequestLogFindFilter(ctx context.Context, filter reqlog.F filter.ProjectID = project.ID project.Settings.ReqLogOnlyFindInScope = filter.OnlyInScope - project.Settings.SearchExpr = filter.SearchExpr + project.Settings.ReqLogSearchExpr = filter.SearchExpr err = svc.repo.UpsertProject(ctx, project) if err != nil { return fmt.Errorf("proj: failed to update project: %w", err) } - svc.reqLogSvc.FindReqsFilter = filter + svc.reqLogSvc.SetFindReqsFilter(filter) + + return nil +} + +func (svc *service) SetSenderRequestFindFilter(ctx context.Context, filter sender.FindRequestsFilter) error { + project, err := svc.ActiveProject(ctx) + if err != nil { + return err + } + + filter.ProjectID = project.ID + + project.Settings.SenderOnlyFindInScope = filter.OnlyInScope + project.Settings.SenderSearchExpr = filter.SearchExpr + + err = svc.repo.UpsertProject(ctx, project) + if err != nil { + return fmt.Errorf("proj: failed to update project: %w", err) + } + + svc.senderSvc.SetFindReqsFilter(filter) return nil } diff --git a/pkg/reqlog/reqlog.go b/pkg/reqlog/reqlog.go index fa6f9a5..9876260 100644 --- a/pkg/reqlog/reqlog.go +++ b/pkg/reqlog/reqlog.go @@ -54,13 +54,26 @@ type ResponseLog struct { Body []byte } -type Service struct { - BypassOutOfScopeRequests bool - FindReqsFilter FindRequestsFilter - ActiveProjectID ulid.ULID +type Service interface { + FindRequests(ctx context.Context) ([]RequestLog, error) + FindRequestLogByID(ctx context.Context, id ulid.ULID) (RequestLog, error) + ClearRequests(ctx context.Context, projectID ulid.ULID) error + RequestModifier(next proxy.RequestModifyFunc) proxy.RequestModifyFunc + ResponseModifier(next proxy.ResponseModifyFunc) proxy.ResponseModifyFunc + SetActiveProjectID(id ulid.ULID) + ActiveProjectID() ulid.ULID + SetBypassOutOfScopeRequests(bool) + BypassOutOfScopeRequests() bool + SetFindReqsFilter(filter FindRequestsFilter) + FindReqsFilter() FindRequestsFilter +} - scope *scope.Scope - repo Repository +type service struct { + bypassOutOfScopeRequests bool + findReqsFilter FindRequestsFilter + activeProjectID ulid.ULID + scope *scope.Scope + repo Repository } type FindRequestsFilter struct { @@ -74,59 +87,35 @@ type Config struct { Repository Repository } -func NewService(cfg Config) *Service { - return &Service{ +func NewService(cfg Config) Service { + return &service{ repo: cfg.Repository, scope: cfg.Scope, } } -func (svc *Service) FindRequests(ctx context.Context) ([]RequestLog, error) { - return svc.repo.FindRequestLogs(ctx, svc.FindReqsFilter, svc.scope) +func (svc *service) FindRequests(ctx context.Context) ([]RequestLog, error) { + return svc.repo.FindRequestLogs(ctx, svc.findReqsFilter, svc.scope) } -func (svc *Service) FindRequestLogByID(ctx context.Context, id ulid.ULID) (RequestLog, error) { +func (svc *service) FindRequestLogByID(ctx context.Context, id ulid.ULID) (RequestLog, error) { return svc.repo.FindRequestLogByID(ctx, id) } -func (svc *Service) ClearRequests(ctx context.Context, projectID ulid.ULID) error { +func (svc *service) ClearRequests(ctx context.Context, projectID ulid.ULID) error { return svc.repo.ClearRequestLogs(ctx, projectID) } -func (svc *Service) storeResponse(ctx context.Context, reqLogID ulid.ULID, res *http.Response) error { - if res.Header.Get("Content-Encoding") == "gzip" { - gzipReader, err := gzip.NewReader(res.Body) - if err != nil { - return fmt.Errorf("could not create gzip reader: %w", err) - } - defer gzipReader.Close() - - buf := &bytes.Buffer{} - - if _, err := io.Copy(buf, gzipReader); err != nil { - return fmt.Errorf("could not read gzipped response body: %w", err) - } - - res.Body = io.NopCloser(buf) - } - - body, err := io.ReadAll(res.Body) +func (svc *service) storeResponse(ctx context.Context, reqLogID ulid.ULID, res *http.Response) error { + resLog, err := ParseHTTPResponse(res) if err != nil { - return fmt.Errorf("could not read body: %w", err) - } - - resLog := ResponseLog{ - Proto: res.Proto, - StatusCode: res.StatusCode, - Status: res.Status, - Header: res.Header, - Body: body, + return err } return svc.repo.StoreResponseLog(ctx, reqLogID, resLog) } -func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestModifyFunc { +func (svc *service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestModifyFunc { return func(req *http.Request) { next(req) @@ -149,7 +138,7 @@ func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestM } // Bypass logging if no project is active. - if svc.ActiveProjectID.Compare(ulid.ULID{}) == 0 { + if svc.activeProjectID.Compare(ulid.ULID{}) == 0 { ctx := context.WithValue(req.Context(), LogBypassedKey, true) *req = *req.WithContext(ctx) @@ -158,7 +147,7 @@ func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestM // Bypass logging if this setting is enabled and the incoming request // doesn't match any scope rules. - if svc.BypassOutOfScopeRequests && !svc.scope.Match(clone, body) { + if svc.bypassOutOfScopeRequests && !svc.scope.Match(clone, body) { ctx := context.WithValue(req.Context(), LogBypassedKey, true) *req = *req.WithContext(ctx) @@ -167,7 +156,7 @@ func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestM reqLog := RequestLog{ ID: ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy), - ProjectID: svc.ActiveProjectID, + ProjectID: svc.activeProjectID, Method: clone.Method, URL: clone.URL, Proto: clone.Proto, @@ -186,7 +175,7 @@ func (svc *Service) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestM } } -func (svc *Service) ResponseModifier(next proxy.ResponseModifyFunc) proxy.ResponseModifyFunc { +func (svc *service) ResponseModifier(next proxy.ResponseModifyFunc) proxy.ResponseModifyFunc { return func(res *http.Response) error { if err := next(res); err != nil { return err @@ -221,3 +210,58 @@ func (svc *Service) ResponseModifier(next proxy.ResponseModifyFunc) proxy.Respon return nil } } + +func (svc *service) SetActiveProjectID(id ulid.ULID) { + svc.activeProjectID = id +} + +func (svc *service) ActiveProjectID() ulid.ULID { + return svc.activeProjectID +} + +func (svc *service) SetFindReqsFilter(filter FindRequestsFilter) { + svc.findReqsFilter = filter +} + +func (svc *service) FindReqsFilter() FindRequestsFilter { + return svc.findReqsFilter +} + +func (svc *service) SetBypassOutOfScopeRequests(bypass bool) { + svc.bypassOutOfScopeRequests = bypass +} + +func (svc *service) BypassOutOfScopeRequests() bool { + return svc.bypassOutOfScopeRequests +} + +func ParseHTTPResponse(res *http.Response) (ResponseLog, error) { + if res.Header.Get("Content-Encoding") == "gzip" { + gzipReader, err := gzip.NewReader(res.Body) + if err != nil { + return ResponseLog{}, fmt.Errorf("reqlog: could not create gzip reader: %w", err) + } + defer gzipReader.Close() + + buf := &bytes.Buffer{} + + if _, err := io.Copy(buf, gzipReader); err != nil { + return ResponseLog{}, fmt.Errorf("reqlog: could not read gzipped response body: %w", err) + } + + res.Body = io.NopCloser(buf) + } + + body, err := io.ReadAll(res.Body) + if err != nil { + return ResponseLog{}, fmt.Errorf("reqlog: could not read body: %w", err) + } + + return ResponseLog{ + Proto: res.Proto, + StatusCode: res.StatusCode, + Status: res.Status, + Header: res.Header, + Body: body, + }, nil +} diff --git a/pkg/reqlog/reqlog_test.go b/pkg/reqlog/reqlog_test.go index 7a275e5..258b570 100644 --- a/pkg/reqlog/reqlog_test.go +++ b/pkg/reqlog/reqlog_test.go @@ -34,7 +34,7 @@ func TestRequestModifier(t *testing.T) { Repository: repoMock, Scope: &scope.Scope{}, }) - svc.ActiveProjectID = ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) + svc.SetActiveProjectID(ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy)) next := func(req *http.Request) { req.Body = io.NopCloser(strings.NewReader("modified body")) @@ -52,7 +52,7 @@ func TestRequestModifier(t *testing.T) { exp := reqlog.RequestLog{ ID: ulid.ULID{}, // Empty value - ProjectID: svc.ActiveProjectID, + ProjectID: svc.ActiveProjectID(), Method: req.Method, URL: req.URL, Proto: req.Proto, @@ -78,7 +78,7 @@ func TestResponseModifier(t *testing.T) { svc := reqlog.NewService(reqlog.Config{ Repository: repoMock, }) - svc.ActiveProjectID = ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) + svc.SetActiveProjectID(ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy)) next := func(res *http.Response) error { res.Body = io.NopCloser(strings.NewReader("modified body")) diff --git a/pkg/reqlog/search.go b/pkg/reqlog/search.go index 35f0e37..7ad4f1c 100644 --- a/pkg/reqlog/search.go +++ b/pkg/reqlog/search.go @@ -27,7 +27,7 @@ var reqLogSearchKeyFns = map[string]func(rl RequestLog) string{ "req.timestamp": func(rl RequestLog) string { return ulid.Time(rl.ID.Time()).String() }, } -var resLogSearchKeyFns = map[string]func(rl ResponseLog) string{ +var ResLogSearchKeyFns = map[string]func(rl ResponseLog) string{ "res.proto": func(rl ResponseLog) string { return rl.Proto }, "res.statusCode": func(rl ResponseLog) string { return strconv.Itoa(rl.StatusCode) }, "res.statusReason": func(rl ResponseLog) string { return rl.Status }, @@ -154,7 +154,7 @@ func (reqLog RequestLog) getMappedStringLiteral(s string) string { return "" } - fn, ok := resLogSearchKeyFns[s] + fn, ok := ResLogSearchKeyFns[s] if ok { return fn(*reqLog.Response) } @@ -174,7 +174,7 @@ func (reqLog RequestLog) matchStringLiteral(strLiteral search.StringLiteral) (bo } if reqLog.Response != nil { - for _, fn := range resLogSearchKeyFns { + for _, fn := range ResLogSearchKeyFns { if strings.Contains( strings.ToLower(fn(*reqLog.Response)), strings.ToLower(strLiteral.Value), diff --git a/pkg/sender/repo.go b/pkg/sender/repo.go new file mode 100644 index 0000000..f41a7c5 --- /dev/null +++ b/pkg/sender/repo.go @@ -0,0 +1,18 @@ +package sender + +import ( + "context" + + "github.com/oklog/ulid" + + "github.com/dstotijn/hetty/pkg/reqlog" + "github.com/dstotijn/hetty/pkg/scope" +) + +type Repository interface { + FindSenderRequestByID(ctx context.Context, id ulid.ULID) (Request, error) + FindSenderRequests(ctx context.Context, filter FindRequestsFilter, scope *scope.Scope) ([]Request, error) + StoreSenderRequest(ctx context.Context, req Request) error + StoreResponseLog(ctx context.Context, reqLogID ulid.ULID, resLog reqlog.ResponseLog) error + DeleteSenderRequests(ctx context.Context, projectID ulid.ULID) error +} diff --git a/pkg/sender/repo_mock_test.go b/pkg/sender/repo_mock_test.go new file mode 100644 index 0000000..96181fc --- /dev/null +++ b/pkg/sender/repo_mock_test.go @@ -0,0 +1,292 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package sender_test + +import ( + "context" + "github.com/dstotijn/hetty/pkg/reqlog" + "github.com/dstotijn/hetty/pkg/scope" + "github.com/dstotijn/hetty/pkg/sender" + "github.com/oklog/ulid" + "sync" +) + +// Ensure, that RepoMock does implement sender.Repository. +// If this is not the case, regenerate this file with moq. +var _ sender.Repository = &RepoMock{} + +// RepoMock is a mock implementation of sender.Repository. +// +// func TestSomethingThatUsesRepository(t *testing.T) { +// +// // make and configure a mocked sender.Repository +// mockedRepository := &RepoMock{ +// DeleteSenderRequestsFunc: func(ctx context.Context, projectID ulid.ULID) error { +// panic("mock out the DeleteSenderRequests method") +// }, +// FindSenderRequestByIDFunc: func(ctx context.Context, id ulid.ULID) (sender.Request, error) { +// panic("mock out the FindSenderRequestByID method") +// }, +// FindSenderRequestsFunc: func(ctx context.Context, filter sender.FindRequestsFilter, scopeMoqParam *scope.Scope) ([]sender.Request, error) { +// panic("mock out the FindSenderRequests method") +// }, +// StoreResponseLogFunc: func(ctx context.Context, reqLogID ulid.ULID, resLog reqlog.ResponseLog) error { +// panic("mock out the StoreResponseLog method") +// }, +// StoreSenderRequestFunc: func(ctx context.Context, req sender.Request) error { +// panic("mock out the StoreSenderRequest method") +// }, +// } +// +// // use mockedRepository in code that requires sender.Repository +// // and then make assertions. +// +// } +type RepoMock struct { + // DeleteSenderRequestsFunc mocks the DeleteSenderRequests method. + DeleteSenderRequestsFunc func(ctx context.Context, projectID ulid.ULID) error + + // FindSenderRequestByIDFunc mocks the FindSenderRequestByID method. + FindSenderRequestByIDFunc func(ctx context.Context, id ulid.ULID) (sender.Request, error) + + // FindSenderRequestsFunc mocks the FindSenderRequests method. + FindSenderRequestsFunc func(ctx context.Context, filter sender.FindRequestsFilter, scopeMoqParam *scope.Scope) ([]sender.Request, error) + + // StoreResponseLogFunc mocks the StoreResponseLog method. + StoreResponseLogFunc func(ctx context.Context, reqLogID ulid.ULID, resLog reqlog.ResponseLog) error + + // StoreSenderRequestFunc mocks the StoreSenderRequest method. + StoreSenderRequestFunc func(ctx context.Context, req sender.Request) error + + // calls tracks calls to the methods. + calls struct { + // DeleteSenderRequests holds details about calls to the DeleteSenderRequests method. + DeleteSenderRequests []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // ProjectID is the projectID argument value. + ProjectID ulid.ULID + } + // FindSenderRequestByID holds details about calls to the FindSenderRequestByID method. + FindSenderRequestByID []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // ID is the id argument value. + ID ulid.ULID + } + // FindSenderRequests holds details about calls to the FindSenderRequests method. + FindSenderRequests []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Filter is the filter argument value. + Filter sender.FindRequestsFilter + // ScopeMoqParam is the scopeMoqParam argument value. + ScopeMoqParam *scope.Scope + } + // StoreResponseLog holds details about calls to the StoreResponseLog method. + StoreResponseLog []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // ReqLogID is the reqLogID argument value. + ReqLogID ulid.ULID + // ResLog is the resLog argument value. + ResLog reqlog.ResponseLog + } + // StoreSenderRequest holds details about calls to the StoreSenderRequest method. + StoreSenderRequest []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Req is the req argument value. + Req sender.Request + } + } + lockDeleteSenderRequests sync.RWMutex + lockFindSenderRequestByID sync.RWMutex + lockFindSenderRequests sync.RWMutex + lockStoreResponseLog sync.RWMutex + lockStoreSenderRequest sync.RWMutex +} + +// DeleteSenderRequests calls DeleteSenderRequestsFunc. +func (mock *RepoMock) DeleteSenderRequests(ctx context.Context, projectID ulid.ULID) error { + if mock.DeleteSenderRequestsFunc == nil { + panic("RepoMock.DeleteSenderRequestsFunc: method is nil but Repository.DeleteSenderRequests was just called") + } + callInfo := struct { + Ctx context.Context + ProjectID ulid.ULID + }{ + Ctx: ctx, + ProjectID: projectID, + } + mock.lockDeleteSenderRequests.Lock() + mock.calls.DeleteSenderRequests = append(mock.calls.DeleteSenderRequests, callInfo) + mock.lockDeleteSenderRequests.Unlock() + return mock.DeleteSenderRequestsFunc(ctx, projectID) +} + +// DeleteSenderRequestsCalls gets all the calls that were made to DeleteSenderRequests. +// Check the length with: +// len(mockedRepository.DeleteSenderRequestsCalls()) +func (mock *RepoMock) DeleteSenderRequestsCalls() []struct { + Ctx context.Context + ProjectID ulid.ULID +} { + var calls []struct { + Ctx context.Context + ProjectID ulid.ULID + } + mock.lockDeleteSenderRequests.RLock() + calls = mock.calls.DeleteSenderRequests + mock.lockDeleteSenderRequests.RUnlock() + return calls +} + +// FindSenderRequestByID calls FindSenderRequestByIDFunc. +func (mock *RepoMock) FindSenderRequestByID(ctx context.Context, id ulid.ULID) (sender.Request, error) { + if mock.FindSenderRequestByIDFunc == nil { + panic("RepoMock.FindSenderRequestByIDFunc: method is nil but Repository.FindSenderRequestByID was just called") + } + callInfo := struct { + Ctx context.Context + ID ulid.ULID + }{ + Ctx: ctx, + ID: id, + } + mock.lockFindSenderRequestByID.Lock() + mock.calls.FindSenderRequestByID = append(mock.calls.FindSenderRequestByID, callInfo) + mock.lockFindSenderRequestByID.Unlock() + return mock.FindSenderRequestByIDFunc(ctx, id) +} + +// FindSenderRequestByIDCalls gets all the calls that were made to FindSenderRequestByID. +// Check the length with: +// len(mockedRepository.FindSenderRequestByIDCalls()) +func (mock *RepoMock) FindSenderRequestByIDCalls() []struct { + Ctx context.Context + ID ulid.ULID +} { + var calls []struct { + Ctx context.Context + ID ulid.ULID + } + mock.lockFindSenderRequestByID.RLock() + calls = mock.calls.FindSenderRequestByID + mock.lockFindSenderRequestByID.RUnlock() + return calls +} + +// FindSenderRequests calls FindSenderRequestsFunc. +func (mock *RepoMock) FindSenderRequests(ctx context.Context, filter sender.FindRequestsFilter, scopeMoqParam *scope.Scope) ([]sender.Request, error) { + if mock.FindSenderRequestsFunc == nil { + panic("RepoMock.FindSenderRequestsFunc: method is nil but Repository.FindSenderRequests was just called") + } + callInfo := struct { + Ctx context.Context + Filter sender.FindRequestsFilter + ScopeMoqParam *scope.Scope + }{ + Ctx: ctx, + Filter: filter, + ScopeMoqParam: scopeMoqParam, + } + mock.lockFindSenderRequests.Lock() + mock.calls.FindSenderRequests = append(mock.calls.FindSenderRequests, callInfo) + mock.lockFindSenderRequests.Unlock() + return mock.FindSenderRequestsFunc(ctx, filter, scopeMoqParam) +} + +// FindSenderRequestsCalls gets all the calls that were made to FindSenderRequests. +// Check the length with: +// len(mockedRepository.FindSenderRequestsCalls()) +func (mock *RepoMock) FindSenderRequestsCalls() []struct { + Ctx context.Context + Filter sender.FindRequestsFilter + ScopeMoqParam *scope.Scope +} { + var calls []struct { + Ctx context.Context + Filter sender.FindRequestsFilter + ScopeMoqParam *scope.Scope + } + mock.lockFindSenderRequests.RLock() + calls = mock.calls.FindSenderRequests + mock.lockFindSenderRequests.RUnlock() + return calls +} + +// StoreResponseLog calls StoreResponseLogFunc. +func (mock *RepoMock) StoreResponseLog(ctx context.Context, reqLogID ulid.ULID, resLog reqlog.ResponseLog) error { + if mock.StoreResponseLogFunc == nil { + panic("RepoMock.StoreResponseLogFunc: method is nil but Repository.StoreResponseLog was just called") + } + callInfo := struct { + Ctx context.Context + ReqLogID ulid.ULID + ResLog reqlog.ResponseLog + }{ + Ctx: ctx, + ReqLogID: reqLogID, + ResLog: resLog, + } + mock.lockStoreResponseLog.Lock() + mock.calls.StoreResponseLog = append(mock.calls.StoreResponseLog, callInfo) + mock.lockStoreResponseLog.Unlock() + return mock.StoreResponseLogFunc(ctx, reqLogID, resLog) +} + +// StoreResponseLogCalls gets all the calls that were made to StoreResponseLog. +// Check the length with: +// len(mockedRepository.StoreResponseLogCalls()) +func (mock *RepoMock) StoreResponseLogCalls() []struct { + Ctx context.Context + ReqLogID ulid.ULID + ResLog reqlog.ResponseLog +} { + var calls []struct { + Ctx context.Context + ReqLogID ulid.ULID + ResLog reqlog.ResponseLog + } + mock.lockStoreResponseLog.RLock() + calls = mock.calls.StoreResponseLog + mock.lockStoreResponseLog.RUnlock() + return calls +} + +// StoreSenderRequest calls StoreSenderRequestFunc. +func (mock *RepoMock) StoreSenderRequest(ctx context.Context, req sender.Request) error { + if mock.StoreSenderRequestFunc == nil { + panic("RepoMock.StoreSenderRequestFunc: method is nil but Repository.StoreSenderRequest was just called") + } + callInfo := struct { + Ctx context.Context + Req sender.Request + }{ + Ctx: ctx, + Req: req, + } + mock.lockStoreSenderRequest.Lock() + mock.calls.StoreSenderRequest = append(mock.calls.StoreSenderRequest, callInfo) + mock.lockStoreSenderRequest.Unlock() + return mock.StoreSenderRequestFunc(ctx, req) +} + +// StoreSenderRequestCalls gets all the calls that were made to StoreSenderRequest. +// Check the length with: +// len(mockedRepository.StoreSenderRequestCalls()) +func (mock *RepoMock) StoreSenderRequestCalls() []struct { + Ctx context.Context + Req sender.Request +} { + var calls []struct { + Ctx context.Context + Req sender.Request + } + mock.lockStoreSenderRequest.RLock() + calls = mock.calls.StoreSenderRequest + mock.lockStoreSenderRequest.RUnlock() + return calls +} diff --git a/pkg/sender/reqlog_mock_test.go b/pkg/sender/reqlog_mock_test.go new file mode 100644 index 0000000..6977de5 --- /dev/null +++ b/pkg/sender/reqlog_mock_test.go @@ -0,0 +1,498 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package sender_test + +import ( + "context" + "github.com/dstotijn/hetty/pkg/proxy" + "github.com/dstotijn/hetty/pkg/reqlog" + "github.com/oklog/ulid" + "sync" +) + +// Ensure, that ReqLogServiceMock does implement reqlog.Service. +// If this is not the case, regenerate this file with moq. +var _ reqlog.Service = &ReqLogServiceMock{} + +// ReqLogServiceMock is a mock implementation of reqlog.Service. +// +// func TestSomethingThatUsesService(t *testing.T) { +// +// // make and configure a mocked reqlog.Service +// mockedService := &ReqLogServiceMock{ +// ActiveProjectIDFunc: func() ulid.ULID { +// panic("mock out the ActiveProjectID method") +// }, +// BypassOutOfScopeRequestsFunc: func() bool { +// panic("mock out the BypassOutOfScopeRequests method") +// }, +// ClearRequestsFunc: func(ctx context.Context, projectID ulid.ULID) error { +// panic("mock out the ClearRequests method") +// }, +// FindReqsFilterFunc: func() reqlog.FindRequestsFilter { +// panic("mock out the FindReqsFilter method") +// }, +// FindRequestLogByIDFunc: func(ctx context.Context, id ulid.ULID) (reqlog.RequestLog, error) { +// panic("mock out the FindRequestLogByID method") +// }, +// FindRequestsFunc: func(ctx context.Context) ([]reqlog.RequestLog, error) { +// panic("mock out the FindRequests method") +// }, +// RequestModifierFunc: func(next proxy.RequestModifyFunc) proxy.RequestModifyFunc { +// panic("mock out the RequestModifier method") +// }, +// ResponseModifierFunc: func(next proxy.ResponseModifyFunc) proxy.ResponseModifyFunc { +// panic("mock out the ResponseModifier method") +// }, +// SetActiveProjectIDFunc: func(id ulid.ULID) { +// panic("mock out the SetActiveProjectID method") +// }, +// SetBypassOutOfScopeRequestsFunc: func(b bool) { +// panic("mock out the SetBypassOutOfScopeRequests method") +// }, +// SetFindReqsFilterFunc: func(filter reqlog.FindRequestsFilter) { +// panic("mock out the SetFindReqsFilter method") +// }, +// } +// +// // use mockedService in code that requires reqlog.Service +// // and then make assertions. +// +// } +type ReqLogServiceMock struct { + // ActiveProjectIDFunc mocks the ActiveProjectID method. + ActiveProjectIDFunc func() ulid.ULID + + // BypassOutOfScopeRequestsFunc mocks the BypassOutOfScopeRequests method. + BypassOutOfScopeRequestsFunc func() bool + + // ClearRequestsFunc mocks the ClearRequests method. + ClearRequestsFunc func(ctx context.Context, projectID ulid.ULID) error + + // FindReqsFilterFunc mocks the FindReqsFilter method. + FindReqsFilterFunc func() reqlog.FindRequestsFilter + + // FindRequestLogByIDFunc mocks the FindRequestLogByID method. + FindRequestLogByIDFunc func(ctx context.Context, id ulid.ULID) (reqlog.RequestLog, error) + + // FindRequestsFunc mocks the FindRequests method. + FindRequestsFunc func(ctx context.Context) ([]reqlog.RequestLog, error) + + // RequestModifierFunc mocks the RequestModifier method. + RequestModifierFunc func(next proxy.RequestModifyFunc) proxy.RequestModifyFunc + + // ResponseModifierFunc mocks the ResponseModifier method. + ResponseModifierFunc func(next proxy.ResponseModifyFunc) proxy.ResponseModifyFunc + + // SetActiveProjectIDFunc mocks the SetActiveProjectID method. + SetActiveProjectIDFunc func(id ulid.ULID) + + // SetBypassOutOfScopeRequestsFunc mocks the SetBypassOutOfScopeRequests method. + SetBypassOutOfScopeRequestsFunc func(b bool) + + // SetFindReqsFilterFunc mocks the SetFindReqsFilter method. + SetFindReqsFilterFunc func(filter reqlog.FindRequestsFilter) + + // calls tracks calls to the methods. + calls struct { + // ActiveProjectID holds details about calls to the ActiveProjectID method. + ActiveProjectID []struct { + } + // BypassOutOfScopeRequests holds details about calls to the BypassOutOfScopeRequests method. + BypassOutOfScopeRequests []struct { + } + // ClearRequests holds details about calls to the ClearRequests method. + ClearRequests []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // ProjectID is the projectID argument value. + ProjectID ulid.ULID + } + // FindReqsFilter holds details about calls to the FindReqsFilter method. + FindReqsFilter []struct { + } + // FindRequestLogByID holds details about calls to the FindRequestLogByID method. + FindRequestLogByID []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // ID is the id argument value. + ID ulid.ULID + } + // FindRequests holds details about calls to the FindRequests method. + FindRequests []struct { + // Ctx is the ctx argument value. + Ctx context.Context + } + // RequestModifier holds details about calls to the RequestModifier method. + RequestModifier []struct { + // Next is the next argument value. + Next proxy.RequestModifyFunc + } + // ResponseModifier holds details about calls to the ResponseModifier method. + ResponseModifier []struct { + // Next is the next argument value. + Next proxy.ResponseModifyFunc + } + // SetActiveProjectID holds details about calls to the SetActiveProjectID method. + SetActiveProjectID []struct { + // ID is the id argument value. + ID ulid.ULID + } + // SetBypassOutOfScopeRequests holds details about calls to the SetBypassOutOfScopeRequests method. + SetBypassOutOfScopeRequests []struct { + // B is the b argument value. + B bool + } + // SetFindReqsFilter holds details about calls to the SetFindReqsFilter method. + SetFindReqsFilter []struct { + // Filter is the filter argument value. + Filter reqlog.FindRequestsFilter + } + } + lockActiveProjectID sync.RWMutex + lockBypassOutOfScopeRequests sync.RWMutex + lockClearRequests sync.RWMutex + lockFindReqsFilter sync.RWMutex + lockFindRequestLogByID sync.RWMutex + lockFindRequests sync.RWMutex + lockRequestModifier sync.RWMutex + lockResponseModifier sync.RWMutex + lockSetActiveProjectID sync.RWMutex + lockSetBypassOutOfScopeRequests sync.RWMutex + lockSetFindReqsFilter sync.RWMutex +} + +// ActiveProjectID calls ActiveProjectIDFunc. +func (mock *ReqLogServiceMock) ActiveProjectID() ulid.ULID { + if mock.ActiveProjectIDFunc == nil { + panic("ReqLogServiceMock.ActiveProjectIDFunc: method is nil but Service.ActiveProjectID was just called") + } + callInfo := struct { + }{} + mock.lockActiveProjectID.Lock() + mock.calls.ActiveProjectID = append(mock.calls.ActiveProjectID, callInfo) + mock.lockActiveProjectID.Unlock() + return mock.ActiveProjectIDFunc() +} + +// ActiveProjectIDCalls gets all the calls that were made to ActiveProjectID. +// Check the length with: +// len(mockedService.ActiveProjectIDCalls()) +func (mock *ReqLogServiceMock) ActiveProjectIDCalls() []struct { +} { + var calls []struct { + } + mock.lockActiveProjectID.RLock() + calls = mock.calls.ActiveProjectID + mock.lockActiveProjectID.RUnlock() + return calls +} + +// BypassOutOfScopeRequests calls BypassOutOfScopeRequestsFunc. +func (mock *ReqLogServiceMock) BypassOutOfScopeRequests() bool { + if mock.BypassOutOfScopeRequestsFunc == nil { + panic("ReqLogServiceMock.BypassOutOfScopeRequestsFunc: method is nil but Service.BypassOutOfScopeRequests was just called") + } + callInfo := struct { + }{} + mock.lockBypassOutOfScopeRequests.Lock() + mock.calls.BypassOutOfScopeRequests = append(mock.calls.BypassOutOfScopeRequests, callInfo) + mock.lockBypassOutOfScopeRequests.Unlock() + return mock.BypassOutOfScopeRequestsFunc() +} + +// BypassOutOfScopeRequestsCalls gets all the calls that were made to BypassOutOfScopeRequests. +// Check the length with: +// len(mockedService.BypassOutOfScopeRequestsCalls()) +func (mock *ReqLogServiceMock) BypassOutOfScopeRequestsCalls() []struct { +} { + var calls []struct { + } + mock.lockBypassOutOfScopeRequests.RLock() + calls = mock.calls.BypassOutOfScopeRequests + mock.lockBypassOutOfScopeRequests.RUnlock() + return calls +} + +// ClearRequests calls ClearRequestsFunc. +func (mock *ReqLogServiceMock) ClearRequests(ctx context.Context, projectID ulid.ULID) error { + if mock.ClearRequestsFunc == nil { + panic("ReqLogServiceMock.ClearRequestsFunc: method is nil but Service.ClearRequests was just called") + } + callInfo := struct { + Ctx context.Context + ProjectID ulid.ULID + }{ + Ctx: ctx, + ProjectID: projectID, + } + mock.lockClearRequests.Lock() + mock.calls.ClearRequests = append(mock.calls.ClearRequests, callInfo) + mock.lockClearRequests.Unlock() + return mock.ClearRequestsFunc(ctx, projectID) +} + +// ClearRequestsCalls gets all the calls that were made to ClearRequests. +// Check the length with: +// len(mockedService.ClearRequestsCalls()) +func (mock *ReqLogServiceMock) ClearRequestsCalls() []struct { + Ctx context.Context + ProjectID ulid.ULID +} { + var calls []struct { + Ctx context.Context + ProjectID ulid.ULID + } + mock.lockClearRequests.RLock() + calls = mock.calls.ClearRequests + mock.lockClearRequests.RUnlock() + return calls +} + +// FindReqsFilter calls FindReqsFilterFunc. +func (mock *ReqLogServiceMock) FindReqsFilter() reqlog.FindRequestsFilter { + if mock.FindReqsFilterFunc == nil { + panic("ReqLogServiceMock.FindReqsFilterFunc: method is nil but Service.FindReqsFilter was just called") + } + callInfo := struct { + }{} + mock.lockFindReqsFilter.Lock() + mock.calls.FindReqsFilter = append(mock.calls.FindReqsFilter, callInfo) + mock.lockFindReqsFilter.Unlock() + return mock.FindReqsFilterFunc() +} + +// FindReqsFilterCalls gets all the calls that were made to FindReqsFilter. +// Check the length with: +// len(mockedService.FindReqsFilterCalls()) +func (mock *ReqLogServiceMock) FindReqsFilterCalls() []struct { +} { + var calls []struct { + } + mock.lockFindReqsFilter.RLock() + calls = mock.calls.FindReqsFilter + mock.lockFindReqsFilter.RUnlock() + return calls +} + +// FindRequestLogByID calls FindRequestLogByIDFunc. +func (mock *ReqLogServiceMock) FindRequestLogByID(ctx context.Context, id ulid.ULID) (reqlog.RequestLog, error) { + if mock.FindRequestLogByIDFunc == nil { + panic("ReqLogServiceMock.FindRequestLogByIDFunc: method is nil but Service.FindRequestLogByID was just called") + } + callInfo := struct { + Ctx context.Context + ID ulid.ULID + }{ + Ctx: ctx, + ID: id, + } + mock.lockFindRequestLogByID.Lock() + mock.calls.FindRequestLogByID = append(mock.calls.FindRequestLogByID, callInfo) + mock.lockFindRequestLogByID.Unlock() + return mock.FindRequestLogByIDFunc(ctx, id) +} + +// FindRequestLogByIDCalls gets all the calls that were made to FindRequestLogByID. +// Check the length with: +// len(mockedService.FindRequestLogByIDCalls()) +func (mock *ReqLogServiceMock) FindRequestLogByIDCalls() []struct { + Ctx context.Context + ID ulid.ULID +} { + var calls []struct { + Ctx context.Context + ID ulid.ULID + } + mock.lockFindRequestLogByID.RLock() + calls = mock.calls.FindRequestLogByID + mock.lockFindRequestLogByID.RUnlock() + return calls +} + +// FindRequests calls FindRequestsFunc. +func (mock *ReqLogServiceMock) FindRequests(ctx context.Context) ([]reqlog.RequestLog, error) { + if mock.FindRequestsFunc == nil { + panic("ReqLogServiceMock.FindRequestsFunc: method is nil but Service.FindRequests was just called") + } + callInfo := struct { + Ctx context.Context + }{ + Ctx: ctx, + } + mock.lockFindRequests.Lock() + mock.calls.FindRequests = append(mock.calls.FindRequests, callInfo) + mock.lockFindRequests.Unlock() + return mock.FindRequestsFunc(ctx) +} + +// FindRequestsCalls gets all the calls that were made to FindRequests. +// Check the length with: +// len(mockedService.FindRequestsCalls()) +func (mock *ReqLogServiceMock) FindRequestsCalls() []struct { + Ctx context.Context +} { + var calls []struct { + Ctx context.Context + } + mock.lockFindRequests.RLock() + calls = mock.calls.FindRequests + mock.lockFindRequests.RUnlock() + return calls +} + +// RequestModifier calls RequestModifierFunc. +func (mock *ReqLogServiceMock) RequestModifier(next proxy.RequestModifyFunc) proxy.RequestModifyFunc { + if mock.RequestModifierFunc == nil { + panic("ReqLogServiceMock.RequestModifierFunc: method is nil but Service.RequestModifier was just called") + } + callInfo := struct { + Next proxy.RequestModifyFunc + }{ + Next: next, + } + mock.lockRequestModifier.Lock() + mock.calls.RequestModifier = append(mock.calls.RequestModifier, callInfo) + mock.lockRequestModifier.Unlock() + return mock.RequestModifierFunc(next) +} + +// RequestModifierCalls gets all the calls that were made to RequestModifier. +// Check the length with: +// len(mockedService.RequestModifierCalls()) +func (mock *ReqLogServiceMock) RequestModifierCalls() []struct { + Next proxy.RequestModifyFunc +} { + var calls []struct { + Next proxy.RequestModifyFunc + } + mock.lockRequestModifier.RLock() + calls = mock.calls.RequestModifier + mock.lockRequestModifier.RUnlock() + return calls +} + +// ResponseModifier calls ResponseModifierFunc. +func (mock *ReqLogServiceMock) ResponseModifier(next proxy.ResponseModifyFunc) proxy.ResponseModifyFunc { + if mock.ResponseModifierFunc == nil { + panic("ReqLogServiceMock.ResponseModifierFunc: method is nil but Service.ResponseModifier was just called") + } + callInfo := struct { + Next proxy.ResponseModifyFunc + }{ + Next: next, + } + mock.lockResponseModifier.Lock() + mock.calls.ResponseModifier = append(mock.calls.ResponseModifier, callInfo) + mock.lockResponseModifier.Unlock() + return mock.ResponseModifierFunc(next) +} + +// ResponseModifierCalls gets all the calls that were made to ResponseModifier. +// Check the length with: +// len(mockedService.ResponseModifierCalls()) +func (mock *ReqLogServiceMock) ResponseModifierCalls() []struct { + Next proxy.ResponseModifyFunc +} { + var calls []struct { + Next proxy.ResponseModifyFunc + } + mock.lockResponseModifier.RLock() + calls = mock.calls.ResponseModifier + mock.lockResponseModifier.RUnlock() + return calls +} + +// SetActiveProjectID calls SetActiveProjectIDFunc. +func (mock *ReqLogServiceMock) SetActiveProjectID(id ulid.ULID) { + if mock.SetActiveProjectIDFunc == nil { + panic("ReqLogServiceMock.SetActiveProjectIDFunc: method is nil but Service.SetActiveProjectID was just called") + } + callInfo := struct { + ID ulid.ULID + }{ + ID: id, + } + mock.lockSetActiveProjectID.Lock() + mock.calls.SetActiveProjectID = append(mock.calls.SetActiveProjectID, callInfo) + mock.lockSetActiveProjectID.Unlock() + mock.SetActiveProjectIDFunc(id) +} + +// SetActiveProjectIDCalls gets all the calls that were made to SetActiveProjectID. +// Check the length with: +// len(mockedService.SetActiveProjectIDCalls()) +func (mock *ReqLogServiceMock) SetActiveProjectIDCalls() []struct { + ID ulid.ULID +} { + var calls []struct { + ID ulid.ULID + } + mock.lockSetActiveProjectID.RLock() + calls = mock.calls.SetActiveProjectID + mock.lockSetActiveProjectID.RUnlock() + return calls +} + +// SetBypassOutOfScopeRequests calls SetBypassOutOfScopeRequestsFunc. +func (mock *ReqLogServiceMock) SetBypassOutOfScopeRequests(b bool) { + if mock.SetBypassOutOfScopeRequestsFunc == nil { + panic("ReqLogServiceMock.SetBypassOutOfScopeRequestsFunc: method is nil but Service.SetBypassOutOfScopeRequests was just called") + } + callInfo := struct { + B bool + }{ + B: b, + } + mock.lockSetBypassOutOfScopeRequests.Lock() + mock.calls.SetBypassOutOfScopeRequests = append(mock.calls.SetBypassOutOfScopeRequests, callInfo) + mock.lockSetBypassOutOfScopeRequests.Unlock() + mock.SetBypassOutOfScopeRequestsFunc(b) +} + +// SetBypassOutOfScopeRequestsCalls gets all the calls that were made to SetBypassOutOfScopeRequests. +// Check the length with: +// len(mockedService.SetBypassOutOfScopeRequestsCalls()) +func (mock *ReqLogServiceMock) SetBypassOutOfScopeRequestsCalls() []struct { + B bool +} { + var calls []struct { + B bool + } + mock.lockSetBypassOutOfScopeRequests.RLock() + calls = mock.calls.SetBypassOutOfScopeRequests + mock.lockSetBypassOutOfScopeRequests.RUnlock() + return calls +} + +// SetFindReqsFilter calls SetFindReqsFilterFunc. +func (mock *ReqLogServiceMock) SetFindReqsFilter(filter reqlog.FindRequestsFilter) { + if mock.SetFindReqsFilterFunc == nil { + panic("ReqLogServiceMock.SetFindReqsFilterFunc: method is nil but Service.SetFindReqsFilter was just called") + } + callInfo := struct { + Filter reqlog.FindRequestsFilter + }{ + Filter: filter, + } + mock.lockSetFindReqsFilter.Lock() + mock.calls.SetFindReqsFilter = append(mock.calls.SetFindReqsFilter, callInfo) + mock.lockSetFindReqsFilter.Unlock() + mock.SetFindReqsFilterFunc(filter) +} + +// SetFindReqsFilterCalls gets all the calls that were made to SetFindReqsFilter. +// Check the length with: +// len(mockedService.SetFindReqsFilterCalls()) +func (mock *ReqLogServiceMock) SetFindReqsFilterCalls() []struct { + Filter reqlog.FindRequestsFilter +} { + var calls []struct { + Filter reqlog.FindRequestsFilter + } + mock.lockSetFindReqsFilter.RLock() + calls = mock.calls.SetFindReqsFilter + mock.lockSetFindReqsFilter.RUnlock() + return calls +} diff --git a/pkg/sender/search.go b/pkg/sender/search.go new file mode 100644 index 0000000..2fa1e29 --- /dev/null +++ b/pkg/sender/search.go @@ -0,0 +1,228 @@ +package sender + +import ( + "errors" + "fmt" + "regexp" + "strings" + + "github.com/oklog/ulid" + + "github.com/dstotijn/hetty/pkg/reqlog" + "github.com/dstotijn/hetty/pkg/scope" + "github.com/dstotijn/hetty/pkg/search" +) + +var senderReqSearchKeyFns = map[string]func(req Request) string{ + "req.id": func(req Request) string { return req.ID.String() }, + "req.proto": func(req Request) string { return req.Proto }, + "req.url": func(req Request) string { + if req.URL == nil { + return "" + } + return req.URL.String() + }, + "req.method": func(req Request) string { return req.Method }, + "req.body": func(req Request) string { return string(req.Body) }, + "req.timestamp": func(req Request) string { return ulid.Time(req.ID.Time()).String() }, +} + +// TODO: Request and response headers search key functions. + +// Matches returns true if the supplied search expression evaluates to true. +func (req Request) Matches(expr search.Expression) (bool, error) { + switch e := expr.(type) { + case search.PrefixExpression: + return req.matchPrefixExpr(e) + case search.InfixExpression: + return req.matchInfixExpr(e) + case search.StringLiteral: + return req.matchStringLiteral(e) + default: + return false, fmt.Errorf("expression type (%T) not supported", expr) + } +} + +func (req Request) matchPrefixExpr(expr search.PrefixExpression) (bool, error) { + switch expr.Operator { + case search.TokOpNot: + match, err := req.Matches(expr.Right) + if err != nil { + return false, err + } + + return !match, nil + default: + return false, errors.New("operator is not supported") + } +} + +func (req Request) matchInfixExpr(expr search.InfixExpression) (bool, error) { + switch expr.Operator { + case search.TokOpAnd: + left, err := req.Matches(expr.Left) + if err != nil { + return false, err + } + + right, err := req.Matches(expr.Right) + if err != nil { + return false, err + } + + return left && right, nil + case search.TokOpOr: + left, err := req.Matches(expr.Left) + if err != nil { + return false, err + } + + right, err := req.Matches(expr.Right) + if err != nil { + return false, err + } + + return left || right, nil + } + + left, ok := expr.Left.(search.StringLiteral) + if !ok { + return false, errors.New("left operand must be a string literal") + } + + leftVal := req.getMappedStringLiteral(left.Value) + + if expr.Operator == search.TokOpRe || expr.Operator == search.TokOpNotRe { + right, ok := expr.Right.(*regexp.Regexp) + if !ok { + return false, errors.New("right operand must be a regular expression") + } + + switch expr.Operator { + case search.TokOpRe: + return right.MatchString(leftVal), nil + case search.TokOpNotRe: + return !right.MatchString(leftVal), nil + } + } + + right, ok := expr.Right.(search.StringLiteral) + if !ok { + return false, errors.New("right operand must be a string literal") + } + + rightVal := req.getMappedStringLiteral(right.Value) + + switch expr.Operator { + case search.TokOpEq: + return leftVal == rightVal, nil + case search.TokOpNotEq: + return leftVal != rightVal, nil + case search.TokOpGt: + // TODO(?) attempt to parse as int. + return leftVal > rightVal, nil + case search.TokOpLt: + // TODO(?) attempt to parse as int. + return leftVal < rightVal, nil + case search.TokOpGtEq: + // TODO(?) attempt to parse as int. + return leftVal >= rightVal, nil + case search.TokOpLtEq: + // TODO(?) attempt to parse as int. + return leftVal <= rightVal, nil + default: + return false, errors.New("unsupported operator") + } +} + +func (req Request) getMappedStringLiteral(s string) string { + switch { + case strings.HasPrefix(s, "req."): + fn, ok := senderReqSearchKeyFns[s] + if ok { + return fn(req) + } + case strings.HasPrefix(s, "res."): + if req.Response == nil { + return "" + } + + fn, ok := reqlog.ResLogSearchKeyFns[s] + if ok { + return fn(*req.Response) + } + } + + return s +} + +func (req Request) matchStringLiteral(strLiteral search.StringLiteral) (bool, error) { + for _, fn := range senderReqSearchKeyFns { + if strings.Contains( + strings.ToLower(fn(req)), + strings.ToLower(strLiteral.Value), + ) { + return true, nil + } + } + + if req.Response != nil { + for _, fn := range reqlog.ResLogSearchKeyFns { + if strings.Contains( + strings.ToLower(fn(*req.Response)), + strings.ToLower(strLiteral.Value), + ) { + return true, nil + } + } + } + + return false, nil +} + +func (req Request) MatchScope(s *scope.Scope) bool { + for _, rule := range s.Rules() { + if rule.URL != nil && req.URL != nil { + if matches := rule.URL.MatchString(req.URL.String()); matches { + return true + } + } + + for key, values := range req.Header { + var keyMatches, valueMatches bool + + if rule.Header.Key != nil { + if matches := rule.Header.Key.MatchString(key); matches { + keyMatches = true + } + } + + if rule.Header.Value != nil { + for _, value := range values { + if matches := rule.Header.Value.MatchString(value); matches { + valueMatches = true + break + } + } + } + // When only key or value is set, match on whatever is set. + // When both are set, both must match. + switch { + case rule.Header.Key != nil && rule.Header.Value == nil && keyMatches: + return true + case rule.Header.Key == nil && rule.Header.Value != nil && valueMatches: + return true + case rule.Header.Key != nil && rule.Header.Value != nil && keyMatches && valueMatches: + return true + } + } + + if rule.Body != nil { + if matches := rule.Body.Match(req.Body); matches { + return true + } + } + } + + return false +} diff --git a/pkg/sender/search_test.go b/pkg/sender/search_test.go new file mode 100644 index 0000000..646186c --- /dev/null +++ b/pkg/sender/search_test.go @@ -0,0 +1,204 @@ +package sender_test + +import ( + "testing" + + "github.com/dstotijn/hetty/pkg/reqlog" + "github.com/dstotijn/hetty/pkg/search" + "github.com/dstotijn/hetty/pkg/sender" +) + +func TestRequestLogMatch(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + query string + senderReq sender.Request + expectedMatch bool + expectedError error + }{ + { + name: "infix expression, equal operator, match", + query: "req.body = foo", + senderReq: sender.Request{ + Body: []byte("foo"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, not equal operator, match", + query: "req.body != bar", + senderReq: sender.Request{ + Body: []byte("foo"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, greater than operator, match", + query: "req.body > a", + senderReq: sender.Request{ + Body: []byte("b"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, less than operator, match", + query: "req.body < b", + senderReq: sender.Request{ + Body: []byte("a"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, greater than or equal operator, match greater than", + query: "req.body >= a", + senderReq: sender.Request{ + Body: []byte("b"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, greater than or equal operator, match equal", + query: "req.body >= a", + senderReq: sender.Request{ + Body: []byte("a"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, less than or equal operator, match less than", + query: "req.body <= b", + senderReq: sender.Request{ + Body: []byte("a"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, less than or equal operator, match equal", + query: "req.body <= b", + senderReq: sender.Request{ + Body: []byte("b"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, regular expression operator, match", + query: `req.body =~ "^foo(.*)$"`, + senderReq: sender.Request{ + Body: []byte("foobar"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, negate regular expression operator, match", + query: `req.body !~ "^foo(.*)$"`, + senderReq: sender.Request{ + Body: []byte("xoobar"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, and operator, match", + query: "req.body = bar AND res.body = yolo", + senderReq: sender.Request{ + Body: []byte("bar"), + Response: &reqlog.ResponseLog{ + Body: []byte("yolo"), + }, + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "infix expression, or operator, match", + query: "req.body = bar OR res.body = yolo", + senderReq: sender.Request{ + Body: []byte("foo"), + Response: &reqlog.ResponseLog{ + Body: []byte("yolo"), + }, + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "prefix expression, not operator, match", + query: "NOT (req.body = bar)", + senderReq: sender.Request{ + Body: []byte("foo"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "string literal expression, match in request log", + query: "foo", + senderReq: sender.Request{ + Body: []byte("foo"), + }, + expectedMatch: true, + expectedError: nil, + }, + { + name: "string literal expression, no match", + query: "foo", + senderReq: sender.Request{ + Body: []byte("bar"), + }, + expectedMatch: false, + expectedError: nil, + }, + { + name: "string literal expression, match in response log", + query: "foo", + senderReq: sender.Request{ + Response: &reqlog.ResponseLog{ + Body: []byte("foo"), + }, + }, + expectedMatch: true, + expectedError: nil, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + searchExpr, err := search.ParseQuery(tt.query) + assertError(t, nil, err) + + got, err := tt.senderReq.Matches(searchExpr) + assertError(t, tt.expectedError, err) + + if tt.expectedMatch != got { + t.Errorf("expected match result: %v, got: %v", tt.expectedMatch, got) + } + }) + } +} + +func assertError(t *testing.T, exp, got error) { + t.Helper() + + switch { + case exp == nil && got != nil: + t.Fatalf("expected: nil, got: %v", got) + case exp != nil && got == nil: + t.Fatalf("expected: %v, got: nil", exp.Error()) + case exp != nil && got != nil && exp.Error() != got.Error(): + t.Fatalf("expected: %v, got: %v", exp.Error(), got.Error()) + } +} diff --git a/pkg/sender/sender.go b/pkg/sender/sender.go new file mode 100644 index 0000000..4909a00 --- /dev/null +++ b/pkg/sender/sender.go @@ -0,0 +1,251 @@ +package sender + +import ( + "bytes" + "context" + "errors" + "fmt" + "math/rand" + "net/http" + "net/url" + "time" + + "github.com/oklog/ulid" + + "github.com/dstotijn/hetty/pkg/reqlog" + "github.com/dstotijn/hetty/pkg/scope" + "github.com/dstotijn/hetty/pkg/search" +) + +//nolint:gosec +var ulidEntropy = rand.New(rand.NewSource(time.Now().UnixNano())) + +var defaultHTTPClient = &http.Client{ + Transport: &HTTPTransport{}, + Timeout: 30 * time.Second, +} + +var ( + ErrProjectIDMustBeSet = errors.New("sender: project ID must be set") + ErrRequestNotFound = errors.New("sender: request not found") +) + +type Service interface { + FindRequestByID(ctx context.Context, id ulid.ULID) (Request, error) + FindRequests(ctx context.Context) ([]Request, error) + CreateOrUpdateRequest(ctx context.Context, req Request) (Request, error) + CloneFromRequestLog(ctx context.Context, reqLogID ulid.ULID) (Request, error) + DeleteRequests(ctx context.Context, projectID ulid.ULID) error + SendRequest(ctx context.Context, id ulid.ULID) (Request, error) + SetActiveProjectID(ulid.ULID) + SetFindReqsFilter(filter FindRequestsFilter) + FindReqsFilter() FindRequestsFilter +} + +type service struct { + activeProjectID ulid.ULID + findReqsFilter FindRequestsFilter + scope *scope.Scope + repo Repository + reqLogSvc reqlog.Service + httpClient *http.Client +} + +type FindRequestsFilter struct { + ProjectID ulid.ULID + OnlyInScope bool + SearchExpr search.Expression +} + +type Config struct { + Scope *scope.Scope + Repository Repository + ReqLogService reqlog.Service + HTTPClient *http.Client +} + +type SendError struct { + err error +} + +func NewService(cfg Config) Service { + svc := &service{ + repo: cfg.Repository, + reqLogSvc: cfg.ReqLogService, + httpClient: defaultHTTPClient, + scope: cfg.Scope, + } + + if cfg.HTTPClient != nil { + svc.httpClient = cfg.HTTPClient + } + + return svc +} + +type Request struct { + ID ulid.ULID + ProjectID ulid.ULID + SourceRequestLogID ulid.ULID + + URL *url.URL + Method string + Proto string + Header http.Header + Body []byte + + Response *reqlog.ResponseLog +} + +func (svc *service) FindRequestByID(ctx context.Context, id ulid.ULID) (Request, error) { + req, err := svc.repo.FindSenderRequestByID(ctx, id) + if err != nil { + return Request{}, fmt.Errorf("sender: failed to find request: %w", err) + } + + return req, nil +} + +func (svc *service) FindRequests(ctx context.Context) ([]Request, error) { + return svc.repo.FindSenderRequests(ctx, svc.findReqsFilter, svc.scope) +} + +func (svc *service) CreateOrUpdateRequest(ctx context.Context, req Request) (Request, error) { + if svc.activeProjectID.Compare(ulid.ULID{}) == 0 { + return Request{}, ErrProjectIDMustBeSet + } + + if req.ID.Compare(ulid.ULID{}) == 0 { + req.ID = ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) + } + + req.ProjectID = svc.activeProjectID + + if req.Method == "" { + req.Method = http.MethodGet + } + + if req.Proto == "" { + req.Proto = HTTPProto2 + } + + if !isValidProto(req.Proto) { + return Request{}, fmt.Errorf("sender: unsupported HTTP protocol: %v", req.Proto) + } + + err := svc.repo.StoreSenderRequest(ctx, req) + if err != nil { + return Request{}, fmt.Errorf("sender: failed to store request: %w", err) + } + + return req, nil +} + +func (svc *service) CloneFromRequestLog(ctx context.Context, reqLogID ulid.ULID) (Request, error) { + if svc.activeProjectID.Compare(ulid.ULID{}) == 0 { + return Request{}, ErrProjectIDMustBeSet + } + + reqLog, err := svc.reqLogSvc.FindRequestLogByID(ctx, reqLogID) + if err != nil { + return Request{}, fmt.Errorf("sender: failed to find request log: %w", err) + } + + req := Request{ + ID: ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy), + ProjectID: svc.activeProjectID, + SourceRequestLogID: reqLogID, + Method: reqLog.Method, + URL: reqLog.URL, + Proto: HTTPProto2, // Attempt HTTP/2. + Header: reqLog.Header, + Body: reqLog.Body, + } + + err = svc.repo.StoreSenderRequest(ctx, req) + if err != nil { + return Request{}, fmt.Errorf("sender: failed to store request: %w", err) + } + + return req, nil +} + +func (svc *service) SetFindReqsFilter(filter FindRequestsFilter) { + svc.findReqsFilter = filter +} + +func (svc *service) FindReqsFilter() FindRequestsFilter { + return svc.findReqsFilter +} + +func (svc *service) SendRequest(ctx context.Context, id ulid.ULID) (Request, error) { + req, err := svc.repo.FindSenderRequestByID(ctx, id) + if err != nil { + return Request{}, fmt.Errorf("sender: failed to find request: %w", err) + } + + httpReq, err := parseHTTPRequest(ctx, req) + if err != nil { + return Request{}, fmt.Errorf("sender: failed to parse HTTP request: %w", err) + } + + resLog, err := svc.sendHTTPRequest(httpReq) + if err != nil { + return Request{}, fmt.Errorf("sender: could not send HTTP request: %w", err) + } + + err = svc.repo.StoreResponseLog(ctx, id, resLog) + if err != nil { + return Request{}, fmt.Errorf("sender: failed to store sender response log: %w", err) + } + + req.Response = &resLog + + return req, nil +} + +func parseHTTPRequest(ctx context.Context, req Request) (*http.Request, error) { + ctx = context.WithValue(ctx, protoCtxKey{}, req.Proto) + + httpReq, err := http.NewRequestWithContext(ctx, req.Method, req.URL.String(), bytes.NewReader(req.Body)) + if err != nil { + return nil, fmt.Errorf("failed to construct HTTP request: %w", err) + } + + if req.Header != nil { + httpReq.Header = req.Header + } + + return httpReq, nil +} + +func (svc *service) sendHTTPRequest(httpReq *http.Request) (reqlog.ResponseLog, error) { + res, err := svc.httpClient.Do(httpReq) + if err != nil { + return reqlog.ResponseLog{}, &SendError{err} + } + defer res.Body.Close() + + resLog, err := reqlog.ParseHTTPResponse(res) + if err != nil { + return reqlog.ResponseLog{}, fmt.Errorf("failed to parse http response: %w", err) + } + + return resLog, err +} + +func (svc *service) SetActiveProjectID(id ulid.ULID) { + svc.activeProjectID = id +} + +func (svc *service) DeleteRequests(ctx context.Context, projectID ulid.ULID) error { + return svc.repo.DeleteSenderRequests(ctx, projectID) +} + +func (e SendError) Error() string { + return fmt.Sprintf("failed to send HTTP request: %v", e.err) +} + +func (e SendError) Unwrap() error { + return e.err +} diff --git a/pkg/sender/sender_test.go b/pkg/sender/sender_test.go new file mode 100644 index 0000000..e9326a4 --- /dev/null +++ b/pkg/sender/sender_test.go @@ -0,0 +1,289 @@ +package sender_test + +//go:generate go run github.com/matryer/moq -out reqlog_mock_test.go -pkg sender_test ../reqlog Service:ReqLogServiceMock +//go:generate go run github.com/matryer/moq -out repo_mock_test.go -pkg sender_test . Repository:RepoMock + +import ( + "context" + "errors" + "fmt" + "math/rand" + "net/http" + "net/http/httptest" + "net/url" + "testing" + "time" + + "github.com/google/go-cmp/cmp" + "github.com/oklog/ulid" + + "github.com/dstotijn/hetty/pkg/reqlog" + "github.com/dstotijn/hetty/pkg/sender" +) + +//nolint:gosec +var ulidEntropy = rand.New(rand.NewSource(time.Now().UnixNano())) + +var exampleURL = func() *url.URL { + u, err := url.Parse("https://example.com/foobar") + if err != nil { + panic(err) + } + + return u +}() + +func TestStoreRequest(t *testing.T) { + t.Parallel() + + t.Run("without active project", func(t *testing.T) { + t.Parallel() + + svc := sender.NewService(sender.Config{}) + + _, err := svc.CreateOrUpdateRequest(context.Background(), sender.Request{ + URL: exampleURL, + Method: http.MethodPost, + Body: []byte("foobar"), + }) + if !errors.Is(err, sender.ErrProjectIDMustBeSet) { + t.Fatalf("expected `sender.ErrProjectIDMustBeSet`, got: %v", err) + } + }) + + t.Run("with active project", func(t *testing.T) { + t.Parallel() + + repoMock := &RepoMock{ + StoreSenderRequestFunc: func(ctx context.Context, req sender.Request) error { + return nil + }, + } + svc := sender.NewService(sender.Config{ + Repository: repoMock, + }) + + projectID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) + svc.SetActiveProjectID(projectID) + + exp := sender.Request{ + ProjectID: projectID, + URL: exampleURL, + Method: http.MethodPost, + Proto: "HTTP/1.1", + Header: http.Header{ + "X-Foo": []string{"bar"}, + }, + Body: []byte("foobar"), + } + + got, err := svc.CreateOrUpdateRequest(context.Background(), sender.Request{ + URL: exampleURL, + Method: http.MethodPost, + Proto: "HTTP/1.1", + Header: http.Header{ + "X-Foo": []string{"bar"}, + }, + Body: []byte("foobar"), + }) + if err != nil { + t.Fatalf("unexpected error storing request: %v", err) + } + + if got.ID.Compare(ulid.ULID{}) == 0 { + t.Fatal("expected request ID to be non-empty value") + } + + if len(repoMock.StoreSenderRequestCalls()) != 1 { + t.Fatal("expected `svc.repo.StoreSenderRequest()` to have been called 1 time") + } + + if diff := cmp.Diff(got, repoMock.StoreSenderRequestCalls()[0].Req); diff != "" { + t.Fatalf("repo call arg not equal (-exp, +got):\n%v", diff) + } + + // Reset ID to make comparison with expected easier. + got.ID = ulid.ULID{} + + if diff := cmp.Diff(exp, got); diff != "" { + t.Fatalf("request not equal (-exp, +got):\n%v", diff) + } + }) +} + +func TestCloneFromRequestLog(t *testing.T) { + t.Parallel() + + reqLogID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) + + t.Run("without active project", func(t *testing.T) { + t.Parallel() + + svc := sender.NewService(sender.Config{}) + + _, err := svc.CloneFromRequestLog(context.Background(), reqLogID) + if !errors.Is(err, sender.ErrProjectIDMustBeSet) { + t.Fatalf("expected `sender.ErrProjectIDMustBeSet`, got: %v", err) + } + }) + + t.Run("with active project", func(t *testing.T) { + t.Parallel() + + reqLog := reqlog.RequestLog{ + ID: reqLogID, + ProjectID: ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy), + URL: exampleURL, + Method: http.MethodPost, + Proto: "HTTP/1.1", + Header: http.Header{ + "X-Foo": []string{"bar"}, + }, + Body: []byte("foobar"), + } + + reqLogMock := &ReqLogServiceMock{ + FindRequestLogByIDFunc: func(ctx context.Context, id ulid.ULID) (reqlog.RequestLog, error) { + return reqLog, nil + }, + } + repoMock := &RepoMock{ + StoreSenderRequestFunc: func(ctx context.Context, req sender.Request) error { + return nil + }, + } + svc := sender.NewService(sender.Config{ + ReqLogService: reqLogMock, + Repository: repoMock, + }) + + projectID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) + svc.SetActiveProjectID(projectID) + + exp := sender.Request{ + SourceRequestLogID: reqLogID, + ProjectID: projectID, + URL: exampleURL, + Method: http.MethodPost, + Proto: sender.HTTPProto2, + Header: http.Header{ + "X-Foo": []string{"bar"}, + }, + Body: []byte("foobar"), + } + + got, err := svc.CloneFromRequestLog(context.Background(), reqLogID) + if err != nil { + t.Fatalf("unexpected error cloning from request log: %v", err) + } + + if len(reqLogMock.FindRequestLogByIDCalls()) != 1 { + t.Fatal("expected `svc.reqLogSvc.FindRequestLogByID()` to have been called 1 time") + } + + if got := reqLogMock.FindRequestLogByIDCalls()[0].ID; reqLogID.Compare(got) != 0 { + t.Fatalf("reqlog service call arg `id` not equal (expected: %q, got: %q)", reqLogID, got) + } + + if got.ID.Compare(ulid.ULID{}) == 0 { + t.Fatal("expected request ID to be non-empty value") + } + + if len(repoMock.StoreSenderRequestCalls()) != 1 { + t.Fatal("expected `svc.repo.StoreSenderRequest()` to have been called 1 time") + } + + if diff := cmp.Diff(got, repoMock.StoreSenderRequestCalls()[0].Req); diff != "" { + t.Fatalf("repo call arg not equal (-exp, +got):\n%v", diff) + } + + // Reset ID to make comparison with expected easier. + got.ID = ulid.ULID{} + + if diff := cmp.Diff(exp, got); diff != "" { + t.Fatalf("request not equal (-exp, +got):\n%v", diff) + } + }) +} + +func TestSendRequest(t *testing.T) { + t.Parallel() + + date := time.Now().Format(http.TimeFormat) + + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Foobar", "baz") + w.Header().Set("Date", date) + fmt.Fprint(w, "baz") + })) + defer ts.Close() + + tsURL, _ := url.Parse(ts.URL) + + reqID := ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy) + req := sender.Request{ + ID: reqID, + ProjectID: ulid.MustNew(ulid.Timestamp(time.Now()), ulidEntropy), + URL: tsURL, + Method: http.MethodPost, + Proto: "HTTP/1.1", + Header: http.Header{ + "X-Foo": []string{"bar"}, + }, + Body: []byte("foobar"), + } + + repoMock := &RepoMock{ + FindSenderRequestByIDFunc: func(ctx context.Context, id ulid.ULID) (sender.Request, error) { + return req, nil + }, + StoreResponseLogFunc: func(ctx context.Context, reqLogID ulid.ULID, resLog reqlog.ResponseLog) error { + return nil + }, + } + svc := sender.NewService(sender.Config{ + Repository: repoMock, + }) + + exp := reqlog.ResponseLog{ + Proto: "HTTP/1.1", + StatusCode: http.StatusOK, + Status: "200 OK", + Header: http.Header{ + "Content-Length": []string{"3"}, + "Content-Type": []string{"text/plain; charset=utf-8"}, + "Date": []string{date}, + "Foobar": []string{"baz"}, + }, + Body: []byte("baz"), + } + + got, err := svc.SendRequest(context.Background(), reqID) + if err != nil { + t.Fatalf("unexpected error sending request: %v", err) + } + + if len(repoMock.FindSenderRequestByIDCalls()) != 1 { + t.Fatal("expected `svc.repo.FindSenderRequestByID()` to have been called 1 time") + } + + if diff := cmp.Diff(reqID, repoMock.FindSenderRequestByIDCalls()[0].ID); diff != "" { + t.Fatalf("call arg `id` for `svc.repo.FindSenderRequestByID()` not equal (-exp, +got):\n%v", diff) + } + + if len(repoMock.StoreResponseLogCalls()) != 1 { + t.Fatal("expected `svc.repo.StoreResponseLog()` to have been called 1 time") + } + + if diff := cmp.Diff(reqID, repoMock.StoreResponseLogCalls()[0].ReqLogID); diff != "" { + t.Fatalf("call arg `reqLogID` for `svc.repo.StoreResponseLog()` not equal (-exp, +got):\n%v", diff) + } + + if diff := cmp.Diff(exp, repoMock.StoreResponseLogCalls()[0].ResLog); diff != "" { + t.Fatalf("call arg `resLog` for `svc.repo.StoreResponseLog()` not equal (-exp, +got):\n%v", diff) + } + + if diff := cmp.Diff(repoMock.StoreResponseLogCalls()[0].ResLog, *got.Response); diff != "" { + t.Fatalf("returned response log value and persisted value not equal (-exp, +got):\n%v", diff) + } +} diff --git a/pkg/sender/transport.go b/pkg/sender/transport.go new file mode 100644 index 0000000..9654c33 --- /dev/null +++ b/pkg/sender/transport.go @@ -0,0 +1,50 @@ +package sender + +import ( + "crypto/tls" + "net" + "net/http" + "time" +) + +type HTTPTransport struct{} + +type protoCtxKey struct{} + +const ( + HTTPProto1 = "HTTP/1.1" + HTTPProto2 = "HTTP/2.0" +) + +// h1OnlyTransport mimics `http.DefaultTransport`, but with HTTP/2 disabled. +var h1OnlyTransport = &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).DialContext, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + + // Disable HTTP/2. + TLSNextProto: map[string]func(string, *tls.Conn) http.RoundTripper{}, +} + +// RountTrip implements http.RoundTripper. Based on a context value on the +// HTTP request, it switches between using `http.DefaultTransport` (which attempts +// HTTP/2) and a HTTP/1.1 only transport that's based off `http.DefaultTransport`. +func (t *HTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) { + proto, ok := req.Context().Value(protoCtxKey{}).(string) + + if ok && proto == HTTPProto1 { + return h1OnlyTransport.RoundTrip(req) + } + + return http.DefaultTransport.RoundTrip(req) +} + +func isValidProto(proto string) bool { + return proto == HTTPProto1 || proto == HTTPProto2 +}