From 67365e54806ef43861f6b8f0d282d45ed7a075d2 Mon Sep 17 00:00:00 2001 From: akhilmhdh Date: Sun, 15 Jan 2023 00:13:25 +0530 Subject: [PATCH] migration(frontend): migrated frontend files except some components to ts --- .../{RouteGuard.js => RouteGuard.tsx} | 36 +-- frontend/components/basic/Error.tsx | 11 +- frontend/components/basic/InputField.tsx | 30 +- frontend/components/basic/Listbox.tsx | 35 ++- frontend/components/basic/Toggle.tsx | 29 +- .../basic/popups/BottomRightPopup.tsx | 36 ++- frontend/components/basic/table/Checkbox.js | 28 -- frontend/components/basic/table/Checkbox.tsx | 31 ++ frontend/components/billing/Plan.tsx | 32 +- .../integrations/CloudIntegration.tsx | 202 +++++++------ .../integrations/CloudIntegrationSection.tsx | 87 +++--- .../integrations/FrameworkIntegration.tsx | 43 +-- .../FrameworkIntegrationSection.tsx | 34 +-- .../integrations/IntegrationSection.tsx | 44 +-- frontend/components/navigation/NavHeader.tsx | 48 +-- .../signup/DonwloadBackupPDFStep.tsx | 51 ++-- frontend/components/signup/UserInfoStep.tsx | 142 ++++----- .../utilities/checks/PasswordCheck.ts | 5 +- .../{changePassword.js => changePassword.ts} | 35 ++- .../utilities/cryptography/crypto.ts | 19 +- .../utilities/telemetry/Telemetry.js | 42 --- .../utilities/telemetry/Telemetry.ts | 48 +++ frontend/{const.js => const.ts} | 0 frontend/package-lock.json | 14 +- frontend/package.json | 4 +- frontend/pages/404.tsx | 35 ++- .../pages/api/organization/GetOrgUsers.ts | 24 +- .../api/organization/getIncidentContacts.ts | 13 +- frontend/pages/dashboard.js | 33 --- frontend/pages/dashboard.tsx | 34 +++ frontend/pages/github.js | 37 --- frontend/pages/github.tsx | 41 +++ frontend/pages/heroku.js | 37 --- frontend/pages/heroku.tsx | 41 +++ frontend/pages/{index.js => index.tsx} | 0 frontend/pages/integrations/[id].js | 242 --------------- frontend/pages/integrations/[id].tsx | 263 +++++++++++++++++ frontend/pages/netlify.js | 41 --- frontend/pages/netlify.tsx | 46 +++ frontend/pages/noprojects.js | 35 --- frontend/pages/noprojects.tsx | 32 ++ frontend/pages/password-reset.tsx | 160 +++++----- frontend/pages/requestnewinvite.tsx | 32 +- frontend/pages/settings/billing/[id].js | 120 -------- frontend/pages/settings/billing/[id].tsx | 123 ++++++++ .../pages/settings/org/{[id].js => [id].tsx} | 277 +++++++++--------- .../settings/personal/{[id].js => [id].tsx} | 238 +++++++-------- frontend/pages/settings/project/[id].tsx | 7 +- .../{signupinvite.js => signupinvite.tsx} | 153 +++++----- frontend/pages/users/[id].tsx | 146 +++++---- frontend/pages/vercel.js | 40 --- frontend/pages/vercel.tsx | 46 +++ frontend/tsconfig.tsbuildinfo | 1 + 53 files changed, 1759 insertions(+), 1624 deletions(-) rename frontend/components/{RouteGuard.js => RouteGuard.tsx} (65%) delete mode 100644 frontend/components/basic/table/Checkbox.js create mode 100644 frontend/components/basic/table/Checkbox.tsx rename frontend/components/utilities/cryptography/{changePassword.js => changePassword.ts} (82%) delete mode 100644 frontend/components/utilities/telemetry/Telemetry.js create mode 100644 frontend/components/utilities/telemetry/Telemetry.ts rename frontend/{const.js => const.ts} (100%) delete mode 100644 frontend/pages/dashboard.js create mode 100644 frontend/pages/dashboard.tsx delete mode 100644 frontend/pages/github.js create mode 100644 frontend/pages/github.tsx delete mode 100644 frontend/pages/heroku.js create mode 100644 frontend/pages/heroku.tsx rename frontend/pages/{index.js => index.tsx} (100%) delete mode 100644 frontend/pages/integrations/[id].js create mode 100644 frontend/pages/integrations/[id].tsx delete mode 100644 frontend/pages/netlify.js create mode 100644 frontend/pages/netlify.tsx delete mode 100644 frontend/pages/noprojects.js create mode 100644 frontend/pages/noprojects.tsx delete mode 100644 frontend/pages/settings/billing/[id].js create mode 100644 frontend/pages/settings/billing/[id].tsx rename frontend/pages/settings/org/{[id].js => [id].tsx} (55%) rename frontend/pages/settings/personal/{[id].js => [id].tsx} (52%) rename frontend/pages/{signupinvite.js => signupinvite.tsx} (71%) delete mode 100644 frontend/pages/vercel.js create mode 100644 frontend/pages/vercel.tsx create mode 100644 frontend/tsconfig.tsbuildinfo diff --git a/frontend/components/RouteGuard.js b/frontend/components/RouteGuard.tsx similarity index 65% rename from frontend/components/RouteGuard.js rename to frontend/components/RouteGuard.tsx index f3693abec4..24c2e093ea 100644 --- a/frontend/components/RouteGuard.js +++ b/frontend/components/RouteGuard.tsx @@ -1,14 +1,17 @@ -import { useEffect, useState } from 'react'; -import Image from 'next/image'; -import { useRouter } from 'next/router'; +import { ReactNode, useEffect, useState } from "react"; +import { useRouter } from "next/router"; -import { publicPaths } from '~/const'; -import checkAuth from '~/pages/api/auth/CheckAuth'; +import { publicPaths } from "~/const"; +import checkAuth from "~/pages/api/auth/CheckAuth"; // #TODO: finish spinner only when the data loads fully // #TODO: Redirect somewhere if the page does not exist -export default function RouteGuard({ children }) { +type Prop = { + children: ReactNode; +}; + +export default function RouteGuard({ children }: Prop) { const router = useRouter(); const [authorized, setAuthorized] = useState(false); @@ -22,16 +25,16 @@ export default function RouteGuard({ children }) { // #TODO: add the loading page when not yet authorized. const hideContent = () => setAuthorized(false); // const onError = () => setAuthorized(true) - router.events.on('routeChangeStart', hideContent); + router.events.on("routeChangeStart", hideContent); // router.events.on("routeChangeError", onError); // on route change complete - run auth check - router.events.on('routeChangeComplete', authCheck); + router.events.on("routeChangeComplete", authCheck); // unsubscribe from events in useEffect return function return () => { - router.events.off('routeChangeStart', hideContent); - router.events.off('routeChangeComplete', authCheck); + router.events.off("routeChangeStart", hideContent); + router.events.off("routeChangeComplete", authCheck); // router.events.off("routeChangeError", onError); }; // eslint-disable-next-line react-hooks/exhaustive-deps @@ -39,11 +42,10 @@ export default function RouteGuard({ children }) { /** * redirect to login page if accessing a private page and not logged in - * @param {*} url - the url of the page we are trying to go to */ - async function authCheck(url) { + async function authCheck(url:string) { // Make sure that we don't redirect when the user is on the following pages. - const path = '/' + url.split('?')[0].split('/')[1]; + const path = "/" + url.split("?")[0].split("/")[1]; // Check if the user is authenticated const response = await checkAuth(); @@ -52,16 +54,16 @@ export default function RouteGuard({ children }) { if (!publicPaths.includes(path)) { try { if (response.status !== 200) { - router.push('/login'); - console.log('Unauthorized to access.'); + router.push("/login"); + console.log("Unauthorized to access."); setAuthorized(false); } else { setAuthorized(true); - console.log('Authorized to access.'); + console.log("Authorized to access."); } } catch (error) { console.log( - 'Error (probably the authCheck route is stuck again...):', + "Error (probably the authCheck route is stuck again...):", error ); } diff --git a/frontend/components/basic/Error.tsx b/frontend/components/basic/Error.tsx index b5f0b7a4c7..e4a3de366c 100644 --- a/frontend/components/basic/Error.tsx +++ b/frontend/components/basic/Error.tsx @@ -1,16 +1,15 @@ -import React from "react"; -import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; export default function Error({ text }: { text: string }): JSX.Element { return ( -
+
{text && ( -

{text}

+

{text}

)}
); diff --git a/frontend/components/basic/InputField.tsx b/frontend/components/basic/InputField.tsx index 2414109594..9d4a245ffc 100644 --- a/frontend/components/basic/InputField.tsx +++ b/frontend/components/basic/InputField.tsx @@ -1,4 +1,4 @@ -import { memo,useState } from 'react'; +import { memo, useState } from 'react'; import { faCircle, faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -28,12 +28,12 @@ const InputField = ( if (props.static === true) { return ( -
-

+

+

{props.label}

{props.text && ( -

{props.text}

+

{props.text}

)} props.onChangeHandler(e.target.value)} @@ -41,7 +41,7 @@ const InputField = ( placeholder={props.placeholder} value={props.value} required={props.isRequired} - className="bg-bunker-800 text-gray-400 border border-gray-600 rounded-md text-md p-2 w-full min-w-16 outline-none" + className='bg-bunker-800 text-gray-400 border border-gray-600 rounded-md text-md p-2 w-full min-w-16 outline-none' name={props.name} readOnly autoComplete={props.autoComplete} @@ -51,9 +51,9 @@ const InputField = ( ); } else { return ( -
-
-

{props.label}

+
+
+

{props.label}

{/* {props.label == "Password" && router.asPath != "/login" && (
{props.label?.includes('Password') && ( )} {props.blurred && ( -
-

+
+

{props.value .split('') .slice(0, 54) .map(() => ( ))} @@ -131,7 +131,7 @@ const InputField = ( )} */}
{props.error && ( -

+

{props.errorText}

)} diff --git a/frontend/components/basic/Listbox.tsx b/frontend/components/basic/Listbox.tsx index a65135dfad..8ce747376c 100644 --- a/frontend/components/basic/Listbox.tsx +++ b/frontend/components/basic/Listbox.tsx @@ -3,7 +3,7 @@ import { Fragment } from 'react'; import { faAngleDown, faCheck, - faPlus + faPlus, } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Listbox, Transition } from '@headlessui/react'; @@ -25,7 +25,6 @@ interface ListBoxProps { * @param {string[]} obj.data - all the options available * @param {string} obj.text - the text that shows us in front of the select option * @param {function} obj.buttonAction - if there is a button at the bottom of the list, this is the action that happens when you click the button - * @param {string} obj.width - button width * @returns */ export default function ListBox({ @@ -34,37 +33,37 @@ export default function ListBox({ data, text, buttonAction, - isFull + isFull, }: ListBoxProps): JSX.Element { return ( -
+
-
+
{text} - + {' '} {selected}
{data && ( -
- +
+
)} {data && ( - + {data.map((person, personIdx) => ( {selected ? ( - + ) : null} @@ -103,11 +102,11 @@ export default function ListBox({ {buttonAction && (
-
+
{textLine1}
-
{textLine2}
-
+
{textLine2}
+
{/*eslint-disable-next-line react/jsx-no-target-blank */} {buttonText} diff --git a/frontend/components/basic/table/Checkbox.js b/frontend/components/basic/table/Checkbox.js deleted file mode 100644 index 2ef6c2de83..0000000000 --- a/frontend/components/basic/table/Checkbox.js +++ /dev/null @@ -1,28 +0,0 @@ -import React from "react"; - -export const Checkbox = ({ addAllUsers, setAddAllUsers }) => { - return ( - <> -
- {addAllUsers == true ? ( - setAddAllUsers(!addAllUsers)} - /> - ) : ( -
setAddAllUsers(!addAllUsers)} - >
- )} - - -
- - ); -}; diff --git a/frontend/components/basic/table/Checkbox.tsx b/frontend/components/basic/table/Checkbox.tsx new file mode 100644 index 0000000000..56e0158c16 --- /dev/null +++ b/frontend/components/basic/table/Checkbox.tsx @@ -0,0 +1,31 @@ +type Props = { + addAllUsers: boolean; + setAddAllUsers: (arg: boolean) => void; +}; + +export const Checkbox = ({ addAllUsers, setAddAllUsers }: Props) => { + return ( + <> +
+ {addAllUsers == true ? ( + setAddAllUsers(!addAllUsers)} + /> + ) : ( +
setAddAllUsers(!addAllUsers)} + >
+ )} + + +
+ + ); +}; diff --git a/frontend/components/billing/Plan.tsx b/frontend/components/billing/Plan.tsx index 69b7baabaf..54d8515006 100644 --- a/frontend/components/billing/Plan.tsx +++ b/frontend/components/billing/Plan.tsx @@ -8,9 +8,9 @@ interface Props { plan: { name: string; price: string; - priceExplanation: string; + priceExplanation?: string; text: string; - subtext: string; + subtext?: string; buttonTextMain: string; buttonTextSecondary: string; current: boolean; @@ -27,33 +27,33 @@ export default function Plan({ plan }: Props) { } `} > -
-
+
+

{plan.name}

-
-

+

+

{plan.price}

-

+

{plan.priceExplanation}

-

+

{plan.text}

-

+

{plan.subtext}

-
+
{plan.current == false ? ( <> {plan.buttonTextMain == 'Schedule a Demo' ? ( - -
+ +
{plan.buttonTextMain}
@@ -68,7 +68,7 @@ export default function Plan({ plan }: Props) {
)} -
+
{plan.buttonTextSecondary}
@@ -93,7 +93,7 @@ export default function Plan({ plan }: Props) { : 'bg-chicago-700' }`} > -

CURRENT PLAN

+

CURRENT PLAN

)}
diff --git a/frontend/components/integrations/CloudIntegration.tsx b/frontend/components/integrations/CloudIntegration.tsx index dd1b13f47e..d63081d5a1 100644 --- a/frontend/components/integrations/CloudIntegration.tsx +++ b/frontend/components/integrations/CloudIntegration.tsx @@ -1,121 +1,117 @@ -import React from "react"; -import Image from "next/image"; -import { useRouter } from "next/router"; -import { - faCheck, - faX, - } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import Image from 'next/image'; +import { useRouter } from 'next/router'; +import { faCheck, faX } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import deleteIntegrationAuth from "../../pages/api/integrations/DeleteIntegrationAuth"; +import deleteIntegrationAuth from '../../pages/api/integrations/DeleteIntegrationAuth'; interface CloudIntegrationOption { - isAvailable: boolean; - name: string; - type: string; - clientId: string; - docsLink: string; - slug: string; + isAvailable: boolean; + name: string; + type: string; + clientId: string; + docsLink: string; + slug: string; } interface IntegrationAuth { - _id: string; - integration: string; + _id: string; + integration: string; } interface Props { - cloudIntegrationOption: CloudIntegrationOption; - setSelectedIntegrationOption: (cloudIntegration: CloudIntegrationOption) => void; - integrationOptionPress: (cloudIntegrationOption: CloudIntegrationOption) => void; - integrationAuths: IntegrationAuth[]; + cloudIntegrationOption: CloudIntegrationOption; + setSelectedIntegrationOption: ( + cloudIntegration: CloudIntegrationOption + ) => void; + integrationOptionPress: ( + cloudIntegrationOption: CloudIntegrationOption + ) => void; + integrationAuths: IntegrationAuth[]; } const CloudIntegration = ({ - cloudIntegrationOption, - setSelectedIntegrationOption, - integrationOptionPress, - integrationAuths + cloudIntegrationOption, + setSelectedIntegrationOption, + integrationOptionPress, + integrationAuths, }: Props) => { - const router = useRouter(); - return integrationAuths ? ( -
{ - if (!cloudIntegrationOption.isAvailable) return; - setSelectedIntegrationOption(cloudIntegrationOption); - integrationOptionPress(cloudIntegrationOption); - }} - key={cloudIntegrationOption.name} - > - integration logo - {cloudIntegrationOption.name.split(" ").length > 2 ? ( -
-
{cloudIntegrationOption.name.split(" ")[0]}
-
- {cloudIntegrationOption.name.split(" ")[1]}{" "} - {cloudIntegrationOption.name.split(" ")[2]} -
-
- ) : ( -
- {cloudIntegrationOption.name} -
- )} - {cloudIntegrationOption.isAvailable && - integrationAuths - .map((authorization) => authorization.integration) - .includes(cloudIntegrationOption.name.toLowerCase()) && ( -
-
{ - event.stopPropagation(); - deleteIntegrationAuth({ - integrationAuthId: integrationAuths - .filter( - (authorization) => - authorization.integration == - cloudIntegrationOption.name.toLowerCase() - ) - .map((authorization) => authorization._id)[0], - }); - - router.reload(); - }} - className="cursor-pointer w-max bg-red py-0.5 px-2 rounded-b-md text-xs flex flex-row items-center opacity-0 group-hover:opacity-100 duration-200" - > - - Revoke -
-
- - Authorized -
-
- )} - {!cloudIntegrationOption.isAvailable && ( -
-
- Coming Soon + const router = useRouter(); + return integrationAuths ? ( +
{ + if (!cloudIntegrationOption.isAvailable) return; + setSelectedIntegrationOption(cloudIntegrationOption); + integrationOptionPress(cloudIntegrationOption); + }} + key={cloudIntegrationOption.name} + > + integration logo + {cloudIntegrationOption.name.split(' ').length > 2 ? ( +
+
{cloudIntegrationOption.name.split(' ')[0]}
+
+ {cloudIntegrationOption.name.split(' ')[1]}{' '} + {cloudIntegrationOption.name.split(' ')[2]} +
+
+ ) : ( +
+ {cloudIntegrationOption.name} +
+ )} + {cloudIntegrationOption.isAvailable && + integrationAuths + .map((authorization) => authorization.integration) + .includes(cloudIntegrationOption.name.toLowerCase()) && ( +
+
{ + event.stopPropagation(); + deleteIntegrationAuth({ + integrationAuthId: integrationAuths + .filter( + (authorization) => + authorization.integration == + cloudIntegrationOption.name.toLowerCase() + ) + .map((authorization) => authorization._id)[0], + }); + + router.reload(); + }} + className='cursor-pointer w-max bg-red py-0.5 px-2 rounded-b-md text-xs flex flex-row items-center opacity-0 group-hover:opacity-100 duration-200' + > + + Revoke
+
+ + Authorized
+
)} + {!cloudIntegrationOption.isAvailable && ( +
+
+ Coming Soon +
- ) :
-} + )} +
+ ) : ( +
+ ); +}; -export default CloudIntegration; \ No newline at end of file +export default CloudIntegration; diff --git a/frontend/components/integrations/CloudIntegrationSection.tsx b/frontend/components/integrations/CloudIntegrationSection.tsx index d07022f7ac..4bc48cf1a8 100644 --- a/frontend/components/integrations/CloudIntegrationSection.tsx +++ b/frontend/components/integrations/CloudIntegrationSection.tsx @@ -1,53 +1,56 @@ -import React from "react"; -import { useTranslation } from "next-i18next"; +import { useTranslation } from 'next-i18next'; -import CloudIntegration from "./CloudIntegration"; +import CloudIntegration from './CloudIntegration'; interface CloudIntegrationOption { - isAvailable: boolean; - name: string; - type: string; - clientId: string; - docsLink: string; - slug: string; + isAvailable: boolean; + name: string; + type: string; + clientId: string; + docsLink: string; + slug: string; } interface Props { - cloudIntegrationOptions: CloudIntegrationOption[]; - setSelectedIntegrationOption: () => void; - integrationOptionPress: () => void; - integrationAuths: any; + cloudIntegrationOptions: CloudIntegrationOption[]; + setSelectedIntegrationOption: () => void; + integrationOptionPress: () => void; + integrationAuths: any; } -const CloudIntegrationSection = ({ - cloudIntegrationOptions, - setSelectedIntegrationOption, - integrationOptionPress, - integrationAuths +const CloudIntegrationSection = ({ + cloudIntegrationOptions, + setSelectedIntegrationOption, + integrationOptionPress, + integrationAuths, }: Props) => { - const { t } = useTranslation(); + const { t } = useTranslation(); - return ( - <> -
-

{t("integrations:cloud-integrations")}

-

- {t("integrations:click-to-start")} -

-
-
- {cloudIntegrationOptions.map((cloudIntegrationOption) => ( - - ))} -
- - ); -} + return ( + <> +
+

+ {t('integrations:cloud-integrations')} +

+

+ {t('integrations:click-to-start')} +

+
+
+ {cloudIntegrationOptions.map((cloudIntegrationOption) => ( + + ))} +
+ + ); +}; -export default CloudIntegrationSection; \ No newline at end of file +export default CloudIntegrationSection; diff --git a/frontend/components/integrations/FrameworkIntegration.tsx b/frontend/components/integrations/FrameworkIntegration.tsx index 432dbad513..c5d922c496 100644 --- a/frontend/components/integrations/FrameworkIntegration.tsx +++ b/frontend/components/integrations/FrameworkIntegration.tsx @@ -1,5 +1,4 @@ -import React from "react"; -import Image from "next/image"; +import Image from 'next/image'; interface Framework { name: string; @@ -8,29 +7,33 @@ interface Framework { docsLink: string; } -const FrameworkIntegration = ({ - framework -}: { - framework: Framework; -}) => { +const FrameworkIntegration = ({ framework }: { framework: Framework }) => { return ( - + + ); -} +}; export default FrameworkIntegration; diff --git a/frontend/components/integrations/FrameworkIntegrationSection.tsx b/frontend/components/integrations/FrameworkIntegrationSection.tsx index 163931cf27..31bac00434 100644 --- a/frontend/components/integrations/FrameworkIntegrationSection.tsx +++ b/frontend/components/integrations/FrameworkIntegrationSection.tsx @@ -1,18 +1,17 @@ -import React from "react"; -import { useTranslation } from "next-i18next"; +import { useTranslation } from 'next-i18next'; -import FrameworkIntegration from "./FrameworkIntegration"; +import FrameworkIntegration from './FrameworkIntegration'; interface Framework { - name: string; - image: string; - link: string; - slug: string; - docsLink: string; + name: string; + image: string; + link: string; + slug: string; + docsLink: string; } interface Props { - frameworks: [Framework] + frameworks: [Framework]; } const FrameworkIntegrationSection = ({ frameworks }: Props) => { @@ -20,15 +19,17 @@ const FrameworkIntegrationSection = ({ frameworks }: Props) => { return ( <> -
-

{t("integrations:framework-integrations")}

-

- {t("integrations:click-to-setup")} +

+

+ {t('integrations:framework-integrations')} +

+

+ {t('integrations:click-to-setup')}

-
+
{frameworks.map((framework) => ( - @@ -36,7 +37,6 @@ const FrameworkIntegrationSection = ({ frameworks }: Props) => {
); -} +}; export default FrameworkIntegrationSection; - diff --git a/frontend/components/integrations/IntegrationSection.tsx b/frontend/components/integrations/IntegrationSection.tsx index 633a747afb..026b543ce7 100644 --- a/frontend/components/integrations/IntegrationSection.tsx +++ b/frontend/components/integrations/IntegrationSection.tsx @@ -1,8 +1,6 @@ -import React from "react"; +import guidGenerator from '~/utilities/randomId'; -import guidGenerator from "~/utilities/randomId"; - -import Integration from "./Integration"; +import Integration from './Integration'; interface Props { integrations: any; @@ -23,23 +21,25 @@ const ProjectIntegrationSection = ({ integrations, environments = [], }: Props) => { - return integrations.length > 0 ? ( -
-
-

Current Integrations

-

- Manage your integrations of Infisical with third-party services. -

-
- {integrations.map((integration: IntegrationType) => ( - - ))} + return integrations.length > 0 ? ( +
+
+

Current Integrations

+

+ Manage your integrations of Infisical with third-party services. +

- ) :
-} + {integrations.map((integration: IntegrationType) => ( + + ))} +
+ ) : ( +
+ ); +}; -export default ProjectIntegrationSection; \ No newline at end of file +export default ProjectIntegrationSection; diff --git a/frontend/components/navigation/NavHeader.tsx b/frontend/components/navigation/NavHeader.tsx index 6e9fabe39f..8c1721be34 100644 --- a/frontend/components/navigation/NavHeader.tsx +++ b/frontend/components/navigation/NavHeader.tsx @@ -1,32 +1,36 @@ -import { useEffect, useState } from "react"; -import { useRouter } from "next/router"; -import { - faAngleRight, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useEffect, useState } from 'react'; +import { useRouter } from 'next/router'; +import { faAngleRight } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import getOrganization from "~/pages/api/organization/GetOrg"; -import getProjectInfo from "~/pages/api/workspace/getProjectInfo"; +import getOrganization from '~/pages/api/organization/GetOrg'; +import getProjectInfo from '~/pages/api/workspace/getProjectInfo'; /** * This is the component at the top of almost every page. * It shows how to navigate to a certain page. * It future these links should also be clickable and hoverable - * @param obj + * @param obj * @param obj.pageName - Name of the page * @param obj.isProjectRelated - whether this page is related to project or now (determine if it's 2 or 3 navigation steps) - * @returns + * @returns */ -export default function NavHeader({ pageName, isProjectRelated } : { pageName: string; isProjectRelated: boolean; }): JSX.Element { - const [orgName, setOrgName] = useState(""); - const [workspaceName, setWorkspaceName] = useState(""); +export default function NavHeader({ + pageName, + isProjectRelated, +}: { + pageName: string; + isProjectRelated?: boolean; +}): JSX.Element { + const [orgName, setOrgName] = useState(''); + const [workspaceName, setWorkspaceName] = useState(''); const router = useRouter(); useEffect(() => { (async () => { - const orgId = localStorage.getItem("orgData.id") + const orgId = localStorage.getItem('orgData.id'); const org = await getOrganization({ - orgId: orgId ? orgId : "", + orgId: orgId ? orgId : '', }); setOrgName(org.name); @@ -39,27 +43,27 @@ export default function NavHeader({ pageName, isProjectRelated } : { pageName: s }, []); return ( -
-
+
+
{orgName?.charAt(0)}
-
{orgName}
+
{orgName}
{isProjectRelated && ( <> -
+
{workspaceName}
)} -
{pageName}
+
{pageName}
); } diff --git a/frontend/components/signup/DonwloadBackupPDFStep.tsx b/frontend/components/signup/DonwloadBackupPDFStep.tsx index 786c49fd22..97905e450f 100644 --- a/frontend/components/signup/DonwloadBackupPDFStep.tsx +++ b/frontend/components/signup/DonwloadBackupPDFStep.tsx @@ -1,47 +1,50 @@ -import React from "react"; -import { useTranslation } from "next-i18next"; -import { faWarning } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - -import Button from "../basic/buttons/Button"; -import issueBackupKey from "../utilities/cryptography/issueBackupKey"; +import { useTranslation } from 'next-i18next'; +import { faWarning } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import Button from '../basic/buttons/Button'; +import issueBackupKey from '../utilities/cryptography/issueBackupKey'; interface DownloadBackupPDFStepProps { incrementStep: () => void; - email: string; + email: string; password: string; name: string; } /** * This is the step of the signup flow where the user downloads the backup pdf - * @param {object} obj + * @param {object} obj * @param {function} obj.incrementStep - function that moves the user on to the next stage of signup * @param {string} obj.email - user's email * @param {string} obj.password - user's password - * @param {string} obj.name - user's name - * @returns + * @param {string} obj.name - user's name + * @returns */ -export default function DonwloadBackupPDFStep({ incrementStep, email, password, name }: DownloadBackupPDFStepProps): JSX.Element { +export default function DonwloadBackupPDFStep({ + incrementStep, + email, + password, + name, +}: DownloadBackupPDFStepProps): JSX.Element { const { t } = useTranslation(); return ( -
-

- {t("signup:step4-message")} +

+

+ {t('signup:step4-message')}

-
-
{t("signup:step4-description1")}
-
{t("signup:step4-description2")}
+
+
{t('signup:step4-description1')}
+
{t('signup:step4-description2')}
-
- - {t("signup:step4-description3")} +
+ + {t('signup:step4-description3')}
-
+
diff --git a/frontend/components/signup/UserInfoStep.tsx b/frontend/components/signup/UserInfoStep.tsx index 2732f8649a..d1f4524878 100644 --- a/frontend/components/signup/UserInfoStep.tsx +++ b/frontend/components/signup/UserInfoStep.tsx @@ -1,20 +1,20 @@ -import React, { useState } from "react"; -import { useRouter } from "next/router"; -import { useTranslation } from "next-i18next"; -import { faCheck, faX } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import React, { useState } from 'react'; +import { useRouter } from 'next/router'; +import { useTranslation } from 'next-i18next'; +import { faCheck, faX } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import completeAccountInformationSignup from "~/pages/api/auth/CompleteAccountInformationSignup"; +import completeAccountInformationSignup from '~/pages/api/auth/CompleteAccountInformationSignup'; -import Button from "../basic/buttons/Button"; -import InputField from "../basic/InputField"; -import attemptLogin from "../utilities/attemptLogin"; -import passwordCheck from "../utilities/checks/PasswordCheck"; -import Aes256Gcm from "../utilities/cryptography/aes-256-gcm"; +import Button from '../basic/buttons/Button'; +import InputField from '../basic/InputField'; +import attemptLogin from '../utilities/attemptLogin'; +import passwordCheck from '../utilities/checks/PasswordCheck'; +import Aes256Gcm from '../utilities/cryptography/aes-256-gcm'; -const nacl = require("tweetnacl"); -const jsrp = require("jsrp"); -nacl.util = require("tweetnacl-util"); +const nacl = require('tweetnacl'); +const jsrp = require('jsrp'); +nacl.util = require('tweetnacl-util'); const client = new jsrp.client(); interface UserInfoStepProps { @@ -42,16 +42,16 @@ interface UserInfoStepProps { * @param {string} obj.lastName - user's lastName * @param {string} obj.setLastName - function managing the state of user's last name */ -export default function UserInfoStep({ - verificationToken, - incrementStep, +export default function UserInfoStep({ + verificationToken, + incrementStep, email, password, - setPassword, - firstName, + setPassword, + firstName, setFirstName, lastName, - setLastName + setLastName, }: UserInfoStepProps): JSX.Element { const [firstNameError, setFirstNameError] = useState(false); const [lastNameError, setLastNameError] = useState(false); @@ -63,7 +63,7 @@ export default function UserInfoStep({ const { t } = useTranslation(); const router = useRouter(); - // Verifies if the information that the users entered (name, workspace) + // Verifies if the information that the users entered (name, workspace) // is there, and if the password matches the criteria. const signupErrorCheck = async () => { setIsLoading(true); @@ -85,7 +85,7 @@ export default function UserInfoStep({ setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - currentErrorCheck: errorCheck, + errorCheck, }); if (!errorCheck) { @@ -102,11 +102,11 @@ export default function UserInfoStep({ .slice(0, 32) .padStart( 32 + (password.slice(0, 32).length - new Blob([password]).size), - "0" + '0' ), }) as { ciphertext: string; iv: string; tag: string }; - localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY); + localStorage.setItem('PRIVATE_KEY', PRIVATE_KEY); client.init( { @@ -134,10 +134,10 @@ export default function UserInfoStep({ if (response.status === 200) { // response = await response.json(); - localStorage.setItem("publicKey", PUBLIC_KEY); - localStorage.setItem("encryptedPrivateKey", ciphertext); - localStorage.setItem("iv", iv); - localStorage.setItem("tag", tag); + localStorage.setItem('publicKey', PUBLIC_KEY); + localStorage.setItem('encryptedPrivateKey', ciphertext); + localStorage.setItem('iv', iv); + localStorage.setItem('tag', tag); try { await attemptLogin( @@ -163,45 +163,45 @@ export default function UserInfoStep({ }; return ( -
-

- {t("signup:step3-message")} +

+

+ {t('signup:step3-message')}

-
+
-
+
-
+
{ setPassword(password); passwordCheck({ @@ -209,98 +209,98 @@ export default function UserInfoStep({ setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - currentErrorCheck: false, + errorCheck: false, }); }} - type="password" + type='password' value={password} isRequired error={ passwordErrorLength && passwordErrorNumber && passwordErrorLowerCase } - autoComplete="new-password" - id="new-password" + autoComplete='new-password' + id='new-password' /> {passwordErrorLength || passwordErrorLowerCase || passwordErrorNumber ? ( -
+
- {t("section-password:validate-base")} + {t('section-password:validate-base')}
-
+
{passwordErrorLength ? ( ) : ( )}
- {t("section-password:validate-length")} + {t('section-password:validate-length')}
-
+
{passwordErrorLowerCase ? ( ) : ( )}
- {t("section-password:validate-case")} + {t('section-password:validate-case')}
-
+
{passwordErrorNumber ? ( ) : ( )}
- {t("section-password:validate-number")} + {t('section-password:validate-number')}
) : ( -
+
)}
-
+
- ) + ); } diff --git a/frontend/components/utilities/checks/PasswordCheck.ts b/frontend/components/utilities/checks/PasswordCheck.ts index 10240b7476..b511304fbc 100644 --- a/frontend/components/utilities/checks/PasswordCheck.ts +++ b/frontend/components/utilities/checks/PasswordCheck.ts @@ -1,6 +1,6 @@ interface PasswordCheckProps { password: string; - currentErrorCheck: boolean; + errorCheck: boolean; setPasswordErrorLength: (value: boolean) => void; setPasswordErrorNumber: (value: boolean) => void; setPasswordErrorLowerCase: (value: boolean) => void; @@ -14,9 +14,8 @@ const passwordCheck = ({ setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - currentErrorCheck, + errorCheck, }: PasswordCheckProps) => { - let errorCheck = currentErrorCheck; if (!password || password.length < 14) { setPasswordErrorLength(true); errorCheck = true; diff --git a/frontend/components/utilities/cryptography/changePassword.js b/frontend/components/utilities/cryptography/changePassword.ts similarity index 82% rename from frontend/components/utilities/cryptography/changePassword.js rename to frontend/components/utilities/cryptography/changePassword.ts index c173b3cdfb..0a8f6a35de 100644 --- a/frontend/components/utilities/cryptography/changePassword.js +++ b/frontend/components/utilities/cryptography/changePassword.ts @@ -1,11 +1,10 @@ +import jsrp from 'jsrp'; + import changePassword2 from '~/pages/api/auth/ChangePassword2'; import SRP1 from '~/pages/api/auth/SRP1'; import Aes256Gcm from './aes-256-gcm'; -const nacl = require('tweetnacl'); -nacl.util = require('tweetnacl-util'); -const jsrp = require('jsrp'); const clientOldPassword = new jsrp.client(); const clientNewPassword = new jsrp.client(); @@ -19,13 +18,13 @@ const clientNewPassword = new jsrp.client(); * @returns */ const changePassword = async ( - email, - currentPassword, - newPassword, - setCurrentPasswordError, - setPasswordChanged, - setCurrentPassword, - setNewPassword + email: string, + currentPassword: string, + newPassword: string, + setCurrentPasswordError: (arg: boolean) => void, + setPasswordChanged: (arg: boolean) => void, + setCurrentPassword: (arg: string) => void, + setNewPassword: (arg: string) => void ) => { try { setPasswordChanged(false); @@ -34,7 +33,7 @@ const changePassword = async ( clientOldPassword.init( { username: email, - password: currentPassword + password: currentPassword, }, async () => { const clientPublicKey = clientOldPassword.getPublicKey(); @@ -42,7 +41,7 @@ const changePassword = async ( let serverPublicKey, salt; try { const res = await SRP1({ - clientPublicKey: clientPublicKey + clientPublicKey: clientPublicKey, }); serverPublicKey = res.serverPublicKey; salt = res.salt; @@ -58,13 +57,13 @@ const changePassword = async ( clientNewPassword.init( { username: email, - password: newPassword + password: newPassword, }, async () => { clientNewPassword.createVerifier(async (err, result) => { // The Blob part here is needed to account for symbols that count as 2+ bytes (e.g., é, å, ø) const { ciphertext, iv, tag } = Aes256Gcm.encrypt({ - text: localStorage.getItem('PRIVATE_KEY'), + text: localStorage.getItem('PRIVATE_KEY') as string, secret: newPassword .slice(0, 32) .padStart( @@ -72,7 +71,7 @@ const changePassword = async ( (newPassword.slice(0, 32).length - new Blob([newPassword]).size), '0' - ) + ), }); if (ciphertext) { @@ -88,11 +87,11 @@ const changePassword = async ( tag, salt: result.salt, verifier: result.verifier, - clientProof + clientProof, }); - if (res.status == 400) { + if (res && res.status == 400) { setCurrentPasswordError(true); - } else if (res.status == 200) { + } else if (res && res.status == 200) { setPasswordChanged(true); setCurrentPassword(''); setNewPassword(''); diff --git a/frontend/components/utilities/cryptography/crypto.ts b/frontend/components/utilities/cryptography/crypto.ts index 409b447fc5..f314c67a2a 100644 --- a/frontend/components/utilities/cryptography/crypto.ts +++ b/frontend/components/utilities/cryptography/crypto.ts @@ -22,8 +22,11 @@ type encryptAsymmetricProps = { const encryptAssymmetric = ({ plaintext, publicKey, - privateKey -}: encryptAsymmetricProps): object => { + privateKey, +}: encryptAsymmetricProps): { + ciphertext: string; + nonce: string; +} => { const nonce = nacl.randomBytes(24); const ciphertext = nacl.box( nacl.util.decodeUTF8(plaintext), @@ -34,7 +37,7 @@ const encryptAssymmetric = ({ return { ciphertext: nacl.util.encodeBase64(ciphertext), - nonce: nacl.util.encodeBase64(nonce) + nonce: nacl.util.encodeBase64(nonce), }; }; @@ -58,7 +61,7 @@ const decryptAssymmetric = ({ ciphertext, nonce, publicKey, - privateKey + privateKey, }: decryptAsymmetricProps): string => { const plaintext = nacl.box.open( nacl.util.decodeBase64(ciphertext), @@ -83,7 +86,7 @@ type encryptSymmetricProps = { */ const encryptSymmetric = ({ plaintext, - key + key, }: encryptSymmetricProps): object => { let ciphertext, iv, tag; try { @@ -100,7 +103,7 @@ const encryptSymmetric = ({ return { ciphertext, iv, - tag + tag, }; }; @@ -125,7 +128,7 @@ const decryptSymmetric = ({ ciphertext, iv, tag, - key + key, }: decryptSymmetricProps): string => { let plaintext; try { @@ -142,5 +145,5 @@ export { decryptAssymmetric, decryptSymmetric, encryptAssymmetric, - encryptSymmetric + encryptSymmetric, }; diff --git a/frontend/components/utilities/telemetry/Telemetry.js b/frontend/components/utilities/telemetry/Telemetry.js deleted file mode 100644 index 8a0f9cc735..0000000000 --- a/frontend/components/utilities/telemetry/Telemetry.js +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable */ -import { initPostHog } from "~/components/analytics/posthog"; -import { ENV } from "~/components/utilities/config"; - -class Capturer { - constructor() { - this.api = initPostHog(); - } - - capture(item) { - if (ENV == "production" && TELEMETRY_CAPTURING_ENABLED) { - try { - this.api.capture(item); - } catch (error) { - console.error("PostHog", error); - } - } - } - - identify(id) { - if (ENV == "production" && TELEMETRY_CAPTURING_ENABLED) { - try { - this.api.identify(id); - } catch (error) { - console.error("PostHog", error); - } - } - } - -} - -export default class Telemetry { - constructor() { - if (!Telemetry.instance) { - Telemetry.instance = new Capturer(); - } - } - - getInstance() { - return Telemetry.instance; - } -} diff --git a/frontend/components/utilities/telemetry/Telemetry.ts b/frontend/components/utilities/telemetry/Telemetry.ts new file mode 100644 index 0000000000..e7e367fbd7 --- /dev/null +++ b/frontend/components/utilities/telemetry/Telemetry.ts @@ -0,0 +1,48 @@ +/* eslint-disable */ +import { PostHog } from 'posthog-js'; +import { initPostHog } from '~/components/analytics/posthog'; +import { ENV } from '~/components/utilities/config'; + +declare let TELEMETRY_CAPTURING_ENABLED: any; + +class Capturer { + api: PostHog; + + constructor() { + this.api = initPostHog()!; + } + + capture(item: string) { + if (ENV == 'production' && TELEMETRY_CAPTURING_ENABLED) { + try { + this.api.capture(item); + } catch (error) { + console.error('PostHog', error); + } + } + } + + identify(id: string) { + if (ENV == 'production' && TELEMETRY_CAPTURING_ENABLED) { + try { + this.api.identify(id); + } catch (error) { + console.error('PostHog', error); + } + } + } +} + +export default class Telemetry { + static instance: Capturer; + + constructor() { + if (!Telemetry.instance) { + Telemetry.instance = new Capturer(); + } + } + + getInstance() { + return Telemetry.instance; + } +} diff --git a/frontend/const.js b/frontend/const.ts similarity index 100% rename from frontend/const.js rename to frontend/const.ts diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9d04d355ed..1a58b7c2d2 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -4,7 +4,6 @@ "requires": true, "packages": { "": { - "name": "frontend", "dependencies": { "@emotion/css": "^11.10.0", "@emotion/server": "^11.10.0", @@ -55,6 +54,7 @@ }, "devDependencies": { "@tailwindcss/typography": "^0.5.4", + "@types/jsrp": "^0.2.4", "@types/node": "18.11.9", "@types/react": "^18.0.26", "@typescript-eslint/eslint-plugin": "^5.45.0", @@ -1105,6 +1105,12 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/jsrp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@types/jsrp/-/jsrp-0.2.4.tgz", + "integrity": "sha512-9RerZiVclCJNQrAaUH71s7tQpIlvyrM+1oWYwaRW+9xYYG0p2rnqSZMS0j+W+bL1tkBRUQUyXiSEUTnbv8HQjA==", + "dev": true + }, "node_modules/@types/mdast": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", @@ -8675,6 +8681,12 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "@types/jsrp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@types/jsrp/-/jsrp-0.2.4.tgz", + "integrity": "sha512-9RerZiVclCJNQrAaUH71s7tQpIlvyrM+1oWYwaRW+9xYYG0p2rnqSZMS0j+W+bL1tkBRUQUyXiSEUTnbv8HQjA==", + "dev": true + }, "@types/mdast": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", diff --git a/frontend/package.json b/frontend/package.json index f5ea22a3e6..579aaa0963 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,8 @@ "build": "next build", "start": "next start", "start:docker": "next build && next start", - "lint": "next lint" + "lint": "next lint", + "type-check": "tsc --project tsconfig.json" }, "dependencies": { "@emotion/css": "^11.10.0", @@ -58,6 +59,7 @@ }, "devDependencies": { "@tailwindcss/typography": "^0.5.4", + "@types/jsrp": "^0.2.4", "@types/node": "18.11.9", "@types/react": "^18.0.26", "@typescript-eslint/eslint-plugin": "^5.45.0", diff --git a/frontend/pages/404.tsx b/frontend/pages/404.tsx index 3c2ce3f507..ac96cd68be 100644 --- a/frontend/pages/404.tsx +++ b/frontend/pages/404.tsx @@ -1,26 +1,37 @@ -import React from "react"; -import Head from "next/head"; -import Image from "next/image"; -import Link from "next/link"; +import Head from 'next/head'; +import Image from 'next/image'; +import Link from 'next/link'; export default function Custom404() { return ( -
+
Infisical | Page Not Found - + -
-

Oops, something went wrong

-

Think this is a mistake? Email team@infisical.com and we`ll fix it!

- +
+

Oops, something went wrong

+

+ Think this is a mistake? Email{' '} + + team@infisical.com + {' '} + and we`ll fix it!{' '} +

+ Go to Dashboard infisical dragon - page not found
diff --git a/frontend/pages/api/organization/GetOrgUsers.ts b/frontend/pages/api/organization/GetOrgUsers.ts index f1aaa7209f..e5c5ba7622 100644 --- a/frontend/pages/api/organization/GetOrgUsers.ts +++ b/frontend/pages/api/organization/GetOrgUsers.ts @@ -1,17 +1,35 @@ import SecurityClient from '~/utilities/SecurityClient'; +export interface IMembershipOrg { + _id: string; + user: { + email: string; + firstName: string; + lastName: string; + _id: string; + publicKey: string; + }; + inviteEmail: string; + organization: string; + role: 'owner' | 'admin' | 'member'; + status: 'invited' | 'accepted'; +} /** * This route lets us get all the users in an org. * @param {object} obj * @param {string} obj.orgId - organization Id * @returns */ -const getOrganizationUsers = ({ orgId }: { orgId: string }) => { +const getOrganizationUsers = ({ + orgId, +}: { + orgId: string; +}): Promise => { return SecurityClient.fetchCall('/api/v1/organization/' + orgId + '/users', { method: 'GET', headers: { - 'Content-Type': 'application/json' - } + 'Content-Type': 'application/json', + }, }).then(async (res) => { if (res?.status == 200) { return (await res.json()).users; diff --git a/frontend/pages/api/organization/getIncidentContacts.ts b/frontend/pages/api/organization/getIncidentContacts.ts index bb9c3613a7..01ea81350b 100644 --- a/frontend/pages/api/organization/getIncidentContacts.ts +++ b/frontend/pages/api/organization/getIncidentContacts.ts @@ -1,18 +1,25 @@ import SecurityClient from '~/utilities/SecurityClient'; +export interface IIncidentContactOrg { + _id: string; + email: string; + organization: string; +} /** * This routes gets all the incident contacts of a certain organization * @param {*} workspaceId * @returns */ -const getIncidentContacts = (organizationId: string) => { +const getIncidentContacts = ( + organizationId: string +): Promise => { return SecurityClient.fetchCall( '/api/v1/organization/' + organizationId + '/incidentContactOrg', { method: 'GET', headers: { - 'Content-Type': 'application/json' - } + 'Content-Type': 'application/json', + }, } ).then(async (res) => { if (res && res.status == 200) { diff --git a/frontend/pages/dashboard.js b/frontend/pages/dashboard.js deleted file mode 100644 index e183347aa5..0000000000 --- a/frontend/pages/dashboard.js +++ /dev/null @@ -1,33 +0,0 @@ -import { useEffect } from "react"; -import Head from "next/head"; -import { useRouter } from "next/router"; - -import getWorkspaces from "./api/workspace/getWorkspaces"; - -export default function DashboardRedirect() { - const router = useRouter(); - - /** - * Here we forward to the default workspace if a user opens this url - */ - // eslint-disable-next-line react-hooks/exhaustive-deps - useEffect(async () => { - let userWorkspace; - try { - if (localStorage.getItem("projectData.id")) { - router.push("/dashboard/" + localStorage.getItem("projectData.id")); - } else { - const userWorkspaces = await getWorkspaces(); - userWorkspace = userWorkspaces[0]._id; - router.push("/dashboard/" + userWorkspace); - } - } catch (error) { - console.log("Error - Not logged in yet"); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return
; -} - -DashboardRedirect.requireAuth = true; diff --git a/frontend/pages/dashboard.tsx b/frontend/pages/dashboard.tsx new file mode 100644 index 0000000000..8b3ba26945 --- /dev/null +++ b/frontend/pages/dashboard.tsx @@ -0,0 +1,34 @@ +import { useEffect } from 'react'; +import { useRouter } from 'next/router'; + +import getWorkspaces from './api/workspace/getWorkspaces'; + +export default function DashboardRedirect() { + const router = useRouter(); + + /** + * Here we forward to the default workspace if a user opens this url + */ + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(() => { + (async () => { + let userWorkspace; + try { + if (localStorage.getItem('projectData.id')) { + router.push('/dashboard/' + localStorage.getItem('projectData.id')); + } else { + const userWorkspaces = await getWorkspaces(); + userWorkspace = userWorkspaces[0]._id; + router.push('/dashboard/' + userWorkspace); + } + } catch (error) { + console.log('Error - Not logged in yet'); + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return
; +} + +DashboardRedirect.requireAuth = true; diff --git a/frontend/pages/github.js b/frontend/pages/github.js deleted file mode 100644 index af2b2b0874..0000000000 --- a/frontend/pages/github.js +++ /dev/null @@ -1,37 +0,0 @@ -import React, { useEffect } from "react"; -import Head from "next/head"; -import { useRouter } from "next/router"; -const queryString = require("query-string"); -import AuthorizeIntegration from "./api/integrations/authorizeIntegration"; - -export default function Github() { - const router = useRouter(); - const parsedUrl = queryString.parse(router.asPath.split("?")[1]); - const code = parsedUrl.code; - const state = parsedUrl.state; - - /** - * Here we forward to the default workspace if a user opens this url - */ - // eslint-disable-next-line react-hooks/exhaustive-deps - useEffect(async () => { - try { - if (state === localStorage.getItem('latestCSRFToken')) { - localStorage.removeItem('latestCSRFToken'); - await AuthorizeIntegration({ - workspaceId: localStorage.getItem('projectData.id'), - code, - integration: "github", - }); - router.push("/integrations/" + localStorage.getItem("projectData.id")); - } - } catch (error) { - console.error('Github integration error: ', error); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return
; -} - -Github.requireAuth = true; diff --git a/frontend/pages/github.tsx b/frontend/pages/github.tsx new file mode 100644 index 0000000000..03173b7658 --- /dev/null +++ b/frontend/pages/github.tsx @@ -0,0 +1,41 @@ +import { useEffect } from 'react'; +import { useRouter } from 'next/router'; +import queryString from 'query-string'; + +import AuthorizeIntegration from './api/integrations/authorizeIntegration'; + +export default function Github() { + const router = useRouter(); + const parsedUrl = queryString.parse(router.asPath.split('?')[1]); + const code = parsedUrl.code; + const state = parsedUrl.state; + + /** + * Here we forward to the default workspace if a user opens this url + */ + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(() => { + (async () => { + try { + if (state === localStorage.getItem('latestCSRFToken')) { + localStorage.removeItem('latestCSRFToken'); + await AuthorizeIntegration({ + workspaceId: localStorage.getItem('projectData.id') as string, + code: code as string, + integration: 'github', + }); + router.push( + '/integrations/' + localStorage.getItem('projectData.id') + ); + } + } catch (error) { + console.error('Github integration error: ', error); + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return
; +} + +Github.requireAuth = true; diff --git a/frontend/pages/heroku.js b/frontend/pages/heroku.js deleted file mode 100644 index 3302c0dac0..0000000000 --- a/frontend/pages/heroku.js +++ /dev/null @@ -1,37 +0,0 @@ -import { useEffect } from "react"; -import Head from "next/head"; -import { useRouter } from "next/router"; -const queryString = require("query-string"); -import AuthorizeIntegration from "./api/integrations/authorizeIntegration"; - -export default function Heroku() { - const router = useRouter(); - const parsedUrl = queryString.parse(router.asPath.split("?")[1]); - const code = parsedUrl.code; - const state = parsedUrl.state; - - /** - * Here we forward to the default workspace if a user opens this url - */ - // eslint-disable-next-line react-hooks/exhaustive-deps - useEffect(async () => { - try { - if (state === localStorage.getItem('latestCSRFToken')) { - localStorage.removeItem('latestCSRFToken'); - await AuthorizeIntegration({ - workspaceId: localStorage.getItem('projectData.id'), - code, - integration: "heroku", - }); - router.push("/integrations/" + localStorage.getItem("projectData.id")); - } - } catch (error) { - console.error('Heroku integration error: ', error); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return
; -} - -Heroku.requireAuth = true; diff --git a/frontend/pages/heroku.tsx b/frontend/pages/heroku.tsx new file mode 100644 index 0000000000..0f64bd81b8 --- /dev/null +++ b/frontend/pages/heroku.tsx @@ -0,0 +1,41 @@ +import { useEffect } from 'react'; +import { useRouter } from 'next/router'; +import queryString from 'query-string'; + +import AuthorizeIntegration from './api/integrations/authorizeIntegration'; + +export default function Heroku() { + const router = useRouter(); + const parsedUrl = queryString.parse(router.asPath.split('?')[1]); + const code = parsedUrl.code; + const state = parsedUrl.state; + + /** + * Here we forward to the default workspace if a user opens this url + */ + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(() => { + (async () => { + try { + if (state === localStorage.getItem('latestCSRFToken')) { + localStorage.removeItem('latestCSRFToken'); + await AuthorizeIntegration({ + workspaceId: localStorage.getItem('projectData.id') as string, + code: code as string, + integration: 'heroku', + }); + router.push( + '/integrations/' + localStorage.getItem('projectData.id') + ); + } + } catch (error) { + console.error('Heroku integration error: ', error); + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return
; +} + +Heroku.requireAuth = true; diff --git a/frontend/pages/index.js b/frontend/pages/index.tsx similarity index 100% rename from frontend/pages/index.js rename to frontend/pages/index.tsx diff --git a/frontend/pages/integrations/[id].js b/frontend/pages/integrations/[id].js deleted file mode 100644 index 8a11bc3c44..0000000000 --- a/frontend/pages/integrations/[id].js +++ /dev/null @@ -1,242 +0,0 @@ -import { useEffect, useState } from "react"; -import Head from "next/head"; -import Image from "next/image"; -import { useRouter } from "next/router"; -import { useTranslation } from "next-i18next"; -import { - faArrowRight, - faCheck, - faRotate, - faX, -} from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; - -import ActivateBotDialog from "~/components/basic/dialog/ActivateBotDialog"; -import CloudIntegrationSection from "~/components/integrations/CloudIntegrationSection"; -import FrameworkIntegrationSection from "~/components/integrations/FrameworkIntegrationSection"; -import IntegrationSection from "~/components/integrations/IntegrationSection"; -import NavHeader from "~/components/navigation/NavHeader"; -import { getTranslatedServerSideProps } from "~/utilities/withTranslateProps"; - -import frameworkIntegrationOptions from "../../public/json/frameworkIntegrations.json"; -import getBot from "../api/bot/getBot"; -import setBotActiveStatus from "../api/bot/setBotActiveStatus"; -import getIntegrationOptions from "../api/integrations/GetIntegrationOptions"; -import getWorkspaceAuthorizations from "../api/integrations/getWorkspaceAuthorizations"; -import getWorkspaceIntegrations from "../api/integrations/getWorkspaceIntegrations"; -import getAWorkspace from "../api/workspace/getAWorkspace"; -import getLatestFileKey from "../api/workspace/getLatestFileKey"; -const { - decryptAssymmetric, - encryptAssymmetric -} = require('../../components/utilities/cryptography/crypto'); -const crypto = require("crypto"); - -export default function Integrations() { - const [cloudIntegrationOptions, setCloudIntegrationOptions] = useState([]); - const [integrationAuths, setIntegrationAuths] = useState([]); - const [environments,setEnvironments] = useState([]) - const [integrations, setIntegrations] = useState([]); - const [bot, setBot] = useState(null); - const [isActivateBotDialogOpen, setIsActivateBotDialogOpen] = useState(false); - // const [isIntegrationAccessTokenDialogOpen, setIntegrationAccessTokenDialogOpen] = useState(true); - const [selectedIntegrationOption, setSelectedIntegrationOption] = useState(null); - - const router = useRouter(); - const workspaceId = router.query.id; - - const { t } = useTranslation(); - - useEffect(async () => { - try { - const workspace = await getAWorkspace(workspaceId); - setEnvironments(workspace.environments); - - // get cloud integration options - setCloudIntegrationOptions( - await getIntegrationOptions() - ); - - // get project integration authorizations - setIntegrationAuths( - await getWorkspaceAuthorizations({ - workspaceId - }) - ); - - // get project integrations - setIntegrations( - await getWorkspaceIntegrations({ - workspaceId, - }) - ); - - // get project bot - setBot(await getBot({ workspaceId })); - - } catch (err) { - console.log(err); - } - }, []); - - /** - * Activate bot for project by performing the following steps: - * 1. Get the (encrypted) project key - * 2. Decrypt project key with user's private key - * 3. Encrypt project key with bot's public key - * 4. Send encrypted project key to backend and set bot status to active - */ - const handleBotActivate = async () => { - let botKey; - try { - - if (bot) { - // case: there is a bot - const key = await getLatestFileKey({ workspaceId }); - const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY'); - - const WORKSPACE_KEY = decryptAssymmetric({ - ciphertext: key.latestKey.encryptedKey, - nonce: key.latestKey.nonce, - publicKey: key.latestKey.sender.publicKey, - privateKey: PRIVATE_KEY - }); - - const { ciphertext, nonce } = encryptAssymmetric({ - plaintext: WORKSPACE_KEY, - publicKey: bot.publicKey, - privateKey: PRIVATE_KEY - }); - - botKey = { - encryptedKey: ciphertext, - nonce - } - - setBot((await setBotActiveStatus({ - botId: bot._id, - isActive: bot.isActive ? false : true, - botKey - })).bot); - } - } catch (err) { - console.error(err); - } - } - - /** - * Start integration for a given integration option [integrationOption] - * @param {Object} obj - * @param {Object} obj.integrationOption - an integration option - * @param {String} obj.name - * @param {String} obj.type - * @param {String} obj.docsLink - * @returns - */ - const handleIntegrationOption = async ({ integrationOption }) => { - try { - // generate CSRF token for OAuth2 code-token exchange integrations - const state = crypto.randomBytes(16).toString("hex"); - localStorage.setItem('latestCSRFToken', state); - - switch (integrationOption.name) { - case 'Heroku': - window.location = `https://id.heroku.com/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=write-protected&state=${state}`; - break; - case 'Vercel': - window.location = `https://vercel.com/integrations/${integrationOption.clientSlug}/new?state=${state}`; - break; - case 'Netlify': - window.location = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&state=${state}&redirect_uri=${window.location.origin}/netlify`; - break; - case 'GitHub': - window.location = `https://github.com/login/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=repo&redirect_uri=${window.location.origin}/github&state=${state}`; - break; - // case 'Fly.io': - // console.log('fly.io'); - // setIntegrationAccessTokenDialogOpen(true); - // break; - } - } catch (err) { - console.log(err); - } - } - - /** - * Open dialog to activate bot if bot is not active. - * Otherwise, start integration [integrationOption] - * @param {Object} integrationOption - an integration option - * @param {String} integrationOption.name - * @param {String} integrationOption.type - * @param {String} integrationOption.docsLink - * @returns - */ - const integrationOptionPress = (integrationOption) => { - try { - if (bot.isActive) { - // case: bot is active -> proceed with integration - handleIntegrationOption({ integrationOption }); - return; - } - - // case: bot is not active -> open modal to activate bot - setIsActivateBotDialogOpen(true); - } catch (err) { - console.error(err); - } - } - - return ( -
- - - {t("common:head-title", { title: t("integrations:title") })} - - - - - - -
- - setIsActivateBotDialogOpen(false)} - selectedIntegrationOption={selectedIntegrationOption} - handleBotActivate={handleBotActivate} - handleIntegrationOption={handleIntegrationOption} - /> - {/* setIntegrationAccessTokenDialogOpen(false)} - selectedIntegrationOption={selectedIntegrationOption} - handleBotActivate={handleBotActivate} - handleIntegrationOption={handleIntegrationOption} - /> */} - - {(cloudIntegrationOptions.length > 0 && bot) ? ( - - ) : ( -
- )} - -
-
- ); -} - -Integrations.requireAuth = true; - -export const getServerSideProps = getTranslatedServerSideProps([ - "integrations", -]); diff --git a/frontend/pages/integrations/[id].tsx b/frontend/pages/integrations/[id].tsx new file mode 100644 index 0000000000..ff30402ee6 --- /dev/null +++ b/frontend/pages/integrations/[id].tsx @@ -0,0 +1,263 @@ +import crypto from 'crypto'; + +import { useEffect, useState } from 'react'; +import Head from 'next/head'; +import { useRouter } from 'next/router'; +import { useTranslation } from 'next-i18next'; + +import ActivateBotDialog from '~/components/basic/dialog/ActivateBotDialog'; +import CloudIntegrationSection from '~/components/integrations/CloudIntegrationSection'; +import FrameworkIntegrationSection from '~/components/integrations/FrameworkIntegrationSection'; +import IntegrationSection from '~/components/integrations/IntegrationSection'; +import NavHeader from '~/components/navigation/NavHeader'; +import { getTranslatedServerSideProps } from '~/utilities/withTranslateProps'; + +import { + decryptAssymmetric, + encryptAssymmetric, +} from '../../components/utilities/cryptography/crypto'; +import frameworkIntegrationOptions from '../../public/json/frameworkIntegrations.json'; +import getBot from '../api/bot/getBot'; +import setBotActiveStatus from '../api/bot/setBotActiveStatus'; +import getIntegrationOptions from '../api/integrations/GetIntegrationOptions'; +import getWorkspaceAuthorizations from '../api/integrations/getWorkspaceAuthorizations'; +import getWorkspaceIntegrations from '../api/integrations/getWorkspaceIntegrations'; +import getAWorkspace from '../api/workspace/getAWorkspace'; +import getLatestFileKey from '../api/workspace/getLatestFileKey'; + +export default function Integrations() { + const [cloudIntegrationOptions, setCloudIntegrationOptions] = useState([]); + const [integrationAuths, setIntegrationAuths] = useState([]); + const [environments, setEnvironments] = useState< + { + name: string; + slug: string; + }[] + >([]); + const [integrations, setIntegrations] = useState([]); + // TODO: These will have its type when migratiing towards react-query + const [bot, setBot] = useState(null); + const [isActivateBotDialogOpen, setIsActivateBotDialogOpen] = useState(false); + // const [isIntegrationAccessTokenDialogOpen, setIntegrationAccessTokenDialogOpen] = useState(true); + const [selectedIntegrationOption, setSelectedIntegrationOption] = + useState(null); + + const router = useRouter(); + const workspaceId = router.query.id as string; + + const { t } = useTranslation(); + + useEffect(() => { + (async () => { + try { + const workspace = await getAWorkspace(workspaceId); + setEnvironments(workspace.environments); + + // get cloud integration options + setCloudIntegrationOptions(await getIntegrationOptions()); + + // get project integration authorizations + setIntegrationAuths( + await getWorkspaceAuthorizations({ + workspaceId, + }) + ); + + // get project integrations + setIntegrations( + await getWorkspaceIntegrations({ + workspaceId, + }) + ); + + // get project bot + setBot(await getBot({ workspaceId })); + } catch (err) { + console.log(err); + } + })(); + }, []); + + /** + * Activate bot for project by performing the following steps: + * 1. Get the (encrypted) project key + * 2. Decrypt project key with user's private key + * 3. Encrypt project key with bot's public key + * 4. Send encrypted project key to backend and set bot status to active + */ + const handleBotActivate = async () => { + let botKey; + try { + if (bot) { + // case: there is a bot + const key = await getLatestFileKey({ workspaceId }); + const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY'); + + if (!PRIVATE_KEY) { + throw new Error('Private Key missing'); + } + + const WORKSPACE_KEY = decryptAssymmetric({ + ciphertext: key.latestKey.encryptedKey, + nonce: key.latestKey.nonce, + publicKey: key.latestKey.sender.publicKey, + privateKey: PRIVATE_KEY, + }); + + const { ciphertext, nonce } = encryptAssymmetric({ + plaintext: WORKSPACE_KEY, + publicKey: bot.publicKey, + privateKey: PRIVATE_KEY, + }); + + botKey = { + encryptedKey: ciphertext, + nonce, + }; + + setBot( + ( + await setBotActiveStatus({ + botId: bot._id, + isActive: bot.isActive ? false : true, + botKey, + }) + ).bot + ); + } + } catch (err) { + console.error(err); + } + }; + + /** + * Start integration for a given integration option [integrationOption] + * @param {Object} obj + * @param {Object} obj.integrationOption - an integration option + * @param {String} obj.name + * @param {String} obj.type + * @param {String} obj.docsLink + * @returns + */ + const handleIntegrationOption = async ({ + integrationOption, + }: { + integrationOption: any; + }) => { + try { + // generate CSRF token for OAuth2 code-token exchange integrations + const state = crypto.randomBytes(16).toString('hex'); + localStorage.setItem('latestCSRFToken', state); + + switch (integrationOption.name) { + case 'Heroku': + window.location.assign( + `https://id.heroku.com/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=write-protected&state=${state}` + ); + break; + case 'Vercel': + window.location.assign( + `https://vercel.com/integrations/${integrationOption.clientSlug}/new?state=${state}` + ); + break; + case 'Netlify': + window.location.assign( + `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&state=${state}&redirect_uri=${window.location.origin}/netlify` + ); + break; + case 'GitHub': + window.location.assign( + `https://github.com/login/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=repo&redirect_uri=${window.location.origin}/github&state=${state}` + ); + break; + // case 'Fly.io': + // console.log('fly.io'); + // setIntegrationAccessTokenDialogOpen(true); + // break; + } + } catch (err) { + console.log(err); + } + }; + + /** + * Open dialog to activate bot if bot is not active. + * Otherwise, start integration [integrationOption] + * @param {Object} integrationOption - an integration option + * @param {String} integrationOption.name + * @param {String} integrationOption.type + * @param {String} integrationOption.docsLink + * @returns + */ + const integrationOptionPress = (integrationOption: any) => { + try { + if (bot.isActive) { + // case: bot is active -> proceed with integration + handleIntegrationOption({ integrationOption }); + return; + } + + // case: bot is not active -> open modal to activate bot + setIsActivateBotDialogOpen(true); + } catch (err) { + console.error(err); + } + }; + + return ( +
+ + + {t('common:head-title', { title: t('integrations:title') })} + + + + + + +
+ + setIsActivateBotDialogOpen(false)} + selectedIntegrationOption={selectedIntegrationOption} + handleBotActivate={handleBotActivate} + handleIntegrationOption={handleIntegrationOption} + /> + {/* setIntegrationAccessTokenDialogOpen(false)} + selectedIntegrationOption={selectedIntegrationOption} + handleBotActivate={handleBotActivate} + handleIntegrationOption={handleIntegrationOption} + /> */} + + {cloudIntegrationOptions.length > 0 && bot ? ( + + ) : ( +
+ )} + +
+
+ ); +} + +Integrations.requireAuth = true; + +export const getServerSideProps = getTranslatedServerSideProps([ + 'integrations', +]); diff --git a/frontend/pages/netlify.js b/frontend/pages/netlify.js deleted file mode 100644 index fc58042d5d..0000000000 --- a/frontend/pages/netlify.js +++ /dev/null @@ -1,41 +0,0 @@ -import { useEffect } from "react"; -import Head from "next/head"; -import { useRouter } from "next/router"; -const queryString = require("query-string"); -import AuthorizeIntegration from "./api/integrations/authorizeIntegration"; - -export default function Netlify() { - const router = useRouter(); - const parsedUrl = queryString.parse(router.asPath.split("?")[1]); - const code = parsedUrl.code; - const state = parsedUrl.state; - // modify comment here - - /** - * Here we forward to the default workspace if a user opens this url - */ - // eslint-disable-next-line react-hooks/exhaustive-deps - useEffect(async () => { - try { - if (state === localStorage.getItem('latestCSRFToken')) { - localStorage.removeItem('latestCSRFToken'); - - await AuthorizeIntegration({ - workspaceId: localStorage.getItem('projectData.id'), - code, - integration: "netlify" - }); - - router.push("/integrations/" + localStorage.getItem("projectData.id")); - } - } catch (err) { - console.error('Netlify integration error: ', err); - } - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return
; -} - -Netlify.requireAuth = true; diff --git a/frontend/pages/netlify.tsx b/frontend/pages/netlify.tsx new file mode 100644 index 0000000000..ef92c19b6e --- /dev/null +++ b/frontend/pages/netlify.tsx @@ -0,0 +1,46 @@ +import { useEffect } from 'react'; +import { useRouter } from 'next/router'; +import queryString from 'query-string'; + +import AuthorizeIntegration from './api/integrations/authorizeIntegration'; + +export default function Netlify() { + const router = useRouter(); + const parsedUrl = queryString.parse(router.asPath.split('?')[1]); + const code = parsedUrl.code; + const state = parsedUrl.state; + // modify comment here + + /** + * Here we forward to the default workspace if a user opens this url + */ + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(() => { + (async () => { + try { + if (!code) throw new Error('Code not found'); + + if (state === localStorage.getItem('latestCSRFToken')) { + localStorage.removeItem('latestCSRFToken'); + + await AuthorizeIntegration({ + workspaceId: localStorage.getItem('projectData.id') as string, + code: code as string, + integration: 'netlify', + }); + + router.push( + '/integrations/' + localStorage.getItem('projectData.id') + ); + } + } catch (err) { + console.error('Netlify integration error: ', err); + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return
; +} + +Netlify.requireAuth = true; diff --git a/frontend/pages/noprojects.js b/frontend/pages/noprojects.js deleted file mode 100644 index 93cf89043a..0000000000 --- a/frontend/pages/noprojects.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from "react"; -import Image from "next/image"; - -import { getTranslatedServerSideProps } from "~/utilities/withTranslateProps"; - -export default function NoProjects() { - return ( -
-
- google logo -
-
-
- You are not part of any projects in this organization yet. When you do, - they will appear here. -
-
- Create a new project, or ask other organization members to give you - neccessary permissions. -
-
-
- ); -} - -NoProjects.requireAuth = true; - -export const getServerSideProps = getTranslatedServerSideProps(["noprojects"]); diff --git a/frontend/pages/noprojects.tsx b/frontend/pages/noprojects.tsx new file mode 100644 index 0000000000..addcaadafd --- /dev/null +++ b/frontend/pages/noprojects.tsx @@ -0,0 +1,32 @@ +import Image from 'next/image'; + +import { getTranslatedServerSideProps } from '~/utilities/withTranslateProps'; + +export default function NoProjects() { + return ( +
+
+ google logo +
+
+
+ You are not part of any projects in this organization yet. When you + do, they will appear here. +
+
+ Create a new project, or ask other organization members to give you + neccessary permissions. +
+
+
+ ); +} + +NoProjects.requireAuth = true; + +export const getServerSideProps = getTranslatedServerSideProps(['noprojects']); diff --git a/frontend/pages/password-reset.tsx b/frontend/pages/password-reset.tsx index c02067d35c..dfb5e01abd 100644 --- a/frontend/pages/password-reset.tsx +++ b/frontend/pages/password-reset.tsx @@ -1,40 +1,39 @@ -import { useState } from "react"; -import Image from "next/image"; -import { useRouter } from "next/router"; -import { faCheck, faX } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useState } from 'react'; +import Image from 'next/image'; +import { useRouter } from 'next/router'; +import { faCheck, faX } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import jsrp from 'jsrp'; +import queryString from 'query-string'; -import Button from "~/components/basic/buttons/Button"; -import InputField from "~/components/basic/InputField"; -import passwordCheck from "~/components/utilities/checks/PasswordCheck"; -import Aes256Gcm from "~/components/utilities/cryptography/aes-256-gcm"; -import { getTranslatedStaticProps } from "~/components/utilities/withTranslateProps"; +import Button from '~/components/basic/buttons/Button'; +import InputField from '~/components/basic/InputField'; +import passwordCheck from '~/components/utilities/checks/PasswordCheck'; +import Aes256Gcm from '~/components/utilities/cryptography/aes-256-gcm'; +import { getTranslatedStaticProps } from '~/components/utilities/withTranslateProps'; -import EmailVerifyOnPasswordReset from "./api/auth/EmailVerifyOnPasswordReset"; -import getBackupEncryptedPrivateKey from "./api/auth/getBackupEncryptedPrivateKey"; -import resetPasswordOnAccountRecovery from "./api/auth/resetPasswordOnAccountRecovery"; +import EmailVerifyOnPasswordReset from './api/auth/EmailVerifyOnPasswordReset'; +import getBackupEncryptedPrivateKey from './api/auth/getBackupEncryptedPrivateKey'; +import resetPasswordOnAccountRecovery from './api/auth/resetPasswordOnAccountRecovery'; -const queryString = require("query-string"); -const nacl = require("tweetnacl"); -const jsrp = require("jsrp"); -nacl.util = require("tweetnacl-util"); const client = new jsrp.client(); export default function PasswordReset() { - const router = useRouter(); - const parsedUrl = queryString.parse(router.asPath.split("?")[1]); - const token = parsedUrl.token; - const email = parsedUrl.to?.replace(" ", "+").trim(); - const [verificationToken, setVerificationToken] = useState(""); + const [verificationToken, setVerificationToken] = useState(''); const [step, setStep] = useState(1); - const [backupKey, setBackupKey] = useState(""); - const [privateKey, setPrivateKey] = useState(""); - const [newPassword, setNewPassword] = useState(""); + const [backupKey, setBackupKey] = useState(''); + const [privateKey, setPrivateKey] = useState(''); + const [newPassword, setNewPassword] = useState(''); const [backupKeyError, setBackupKeyError] = useState(false); const [passwordErrorLength, setPasswordErrorLength] = useState(false); const [passwordErrorNumber, setPasswordErrorNumber] = useState(false); const [passwordErrorLowerCase, setPasswordErrorLowerCase] = useState(false); + const router = useRouter(); + const parsedUrl = queryString.parse(router.asPath.split('?')[1]); + const token = parsedUrl.token as string; + const email = (parsedUrl.to as string)?.replace(' ', '+').trim(); + // Unencrypt the private key with a backup key const getEncryptedKeyHandler = async () => { try { @@ -55,13 +54,12 @@ export default function PasswordReset() { // If everything is correct, reset the password const resetPasswordHandler = async () => { - let errorCheck = false; - errorCheck = passwordCheck({ + const errorCheck = passwordCheck({ password: newPassword, setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - currentErrorCheck: errorCheck, + errorCheck: false, }); if (!errorCheck) { @@ -73,7 +71,7 @@ export default function PasswordReset() { .padStart( 32 + (newPassword.slice(0, 32).length - new Blob([newPassword]).size), - "0" + '0' ), }) as { ciphertext: string; iv: string; tag: string }; @@ -96,7 +94,7 @@ export default function PasswordReset() { // if everything works, go the main dashboard page. if (response?.status === 200) { - router.push("/login"); + router.push('/login'); } } ); @@ -107,19 +105,19 @@ export default function PasswordReset() { // Click a button to confirm email const stepConfirmEmail = ( -
-

+

+

Confirm your email

verify email -
+
@@ -141,34 +139,34 @@ export default function PasswordReset() { // Input backup key const stepInputBackupKey = ( -
-

+

+

Enter your backup key

-
-

+

+

You can find it in your emrgency kit. You had to download the enrgency kit during signup.

-
+
-
-
+
+
@@ -177,18 +175,18 @@ export default function PasswordReset() { // Enter new password const stepEnterNewPassword = ( -
-

+

+

Enter new password

-
-

+

+

Make sure you save it somewhere save.

-
+
{ setNewPassword(password); passwordCheck({ @@ -196,70 +194,70 @@ export default function PasswordReset() { setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - currentErrorCheck: false, + errorCheck: false, }); }} - type="password" + type='password' value={newPassword} isRequired error={ passwordErrorLength && passwordErrorLowerCase && passwordErrorNumber } - autoComplete="new-password" - id="new-password" + autoComplete='new-password' + id='new-password' />
{passwordErrorLength || passwordErrorLowerCase || passwordErrorNumber ? ( -
+
Password should contain at least:
-
+
{passwordErrorLength ? ( - + ) : ( )}
14 characters
-
+
{passwordErrorLowerCase ? ( - + ) : ( )}
1 lowercase character
-
+
{passwordErrorNumber ? ( - + ) : ( )}
1 number @@ -267,14 +265,14 @@ export default function PasswordReset() {
) : ( -
+
)} -
-
+
+
@@ -282,7 +280,7 @@ export default function PasswordReset() { ); return ( -
+
{step === 1 && stepConfirmEmail} {step === 2 && stepInputBackupKey} {step === 3 && stepEnterNewPassword} diff --git a/frontend/pages/requestnewinvite.tsx b/frontend/pages/requestnewinvite.tsx index 0f1358267d..c8a5118803 100644 --- a/frontend/pages/requestnewinvite.tsx +++ b/frontend/pages/requestnewinvite.tsx @@ -1,31 +1,35 @@ -import React from "react"; -import Head from "next/head"; -import Image from "next/image"; +import Head from 'next/head'; +import Image from 'next/image'; /** - * This is the page that shows up when a user's invitation + * This is the page that shows up when a user's invitation * to join a project/organization on Infisical has expired */ export default function RequestNewInvite() { return ( -
+
Request a New Invite - + -
-

Oops, your invite has expired.

-

Ask your admin for a new one.

-

- Note: If it still {"doesn't work"}, please reach out to us at +

+

+ Oops, your invite has expired. +

+

Ask your admin for a new one.

+

+ + Note: + {' '} + If it still {"doesn't work"}, please reach out to us at support@infisical.com

-
+
google logo
diff --git a/frontend/pages/settings/billing/[id].js b/frontend/pages/settings/billing/[id].js deleted file mode 100644 index c3e26a3b4d..0000000000 --- a/frontend/pages/settings/billing/[id].js +++ /dev/null @@ -1,120 +0,0 @@ -import { useEffect, useState } from "react"; -import Head from "next/head"; -import { useTranslation } from "next-i18next"; - -import Plan from "~/components/billing/Plan"; -import NavHeader from "~/components/navigation/NavHeader"; -import { STRIPE_PRODUCT_PRO, STRIPE_PRODUCT_STARTER } from "~/utilities/config"; -import { getTranslatedServerSideProps } from "~/utilities/withTranslateProps"; - -import getOrganizationSubscriptions from "../../api/organization/GetOrgSubscription"; -import getOrganizationUsers from "../../api/organization/GetOrgUsers"; - -export default function SettingsBilling() { - let [currentPlan, setCurrentPlan] = useState(""); - let [numUsers, setNumUsers] = useState(""); - - const { t } = useTranslation(); - - const plans = [ - { - key: 1, - name: t("billing:starter.name"), - price: t("billing:free"), - priceExplanation: t("billing:starter.price-explanation"), - text: t("billing:starter.text"), - subtext: t("billing:starter.subtext"), - buttonTextMain: t("billing:downgrade"), - buttonTextSecondary: t("billing:learn-more"), - current: currentPlan == STRIPE_PRODUCT_STARTER, - }, - { - key: 2, - name: t("billing:professional.name"), - price: "$9", - priceExplanation: t("billing:professional.price-explanation"), - subtext: t("billing:professional.subtext"), - text: t("billing:professional.text"), - buttonTextMain: t("billing:upgrade"), - buttonTextSecondary: t("billing:learn-more"), - current: currentPlan == STRIPE_PRODUCT_PRO, - }, - { - key: 3, - name: t("billing:enterprise.name"), - price: t("billing:custom-pricing"), - text: t("billing:enterprise.text"), - buttonTextMain: t("billing:schedule-demo"), - buttonTextSecondary: t("billing:learn-more"), - current: false, - }, - ]; - - useEffect(async () => { - const subscriptions = await getOrganizationSubscriptions({ - orgId: localStorage.getItem("orgData.id"), - }); - - setCurrentPlan(subscriptions.data[0].plan.id); - const orgUsers = await getOrganizationUsers({ - orgId: localStorage.getItem("orgData.id"), - }); - setNumUsers(orgUsers.length); - }, []); - - return ( -
- - {t("common:head-title", { title: t("billing:title") })} - - -
-
- -
-
-

- {t("billing:title")} -

-

- {t("billing:description")} -

-
-
-
-

{t("billing:subscription")}

-
- {plans.map((plan) => ( - - ))} -
-

- {t("billing:current-usage")} -

-
-
-

{numUsers}

-

- {numUsers > 1 - ? "Organization members" - : "Organization member"} -

-
- {/*
-

1

-

Organization projects

-
*/} -
-
-
-
-
- ); -} - -SettingsBilling.requireAuth = true; - -export const getServerSideProps = getTranslatedServerSideProps([ - "settings", - "billing", -]); diff --git a/frontend/pages/settings/billing/[id].tsx b/frontend/pages/settings/billing/[id].tsx new file mode 100644 index 0000000000..9837b8d761 --- /dev/null +++ b/frontend/pages/settings/billing/[id].tsx @@ -0,0 +1,123 @@ +import { useEffect, useState } from 'react'; +import Head from 'next/head'; +import { useTranslation } from 'next-i18next'; + +import Plan from '~/components/billing/Plan'; +import NavHeader from '~/components/navigation/NavHeader'; +import { STRIPE_PRODUCT_PRO, STRIPE_PRODUCT_STARTER } from '~/utilities/config'; +import { getTranslatedServerSideProps } from '~/utilities/withTranslateProps'; + +import getOrganizationSubscriptions from '../../api/organization/GetOrgSubscription'; +import getOrganizationUsers from '../../api/organization/GetOrgUsers'; + +export default function SettingsBilling() { + const [currentPlan, setCurrentPlan] = useState(''); + const [numUsers, setNumUsers] = useState(0); + + const { t } = useTranslation(); + + const plans = [ + { + key: 1, + name: t('billing:starter.name')!, + price: t('billing:free')!, + priceExplanation: t('billing:starter.price-explanation')!, + text: t('billing:starter.text')!, + subtext: t('billing:starter.subtext')!, + buttonTextMain: t('billing:downgrade')!, + buttonTextSecondary: t('billing:learn-more')!, + current: currentPlan == STRIPE_PRODUCT_STARTER, + }, + { + key: 2, + name: t('billing:professional.name')!, + price: '$9', + priceExplanation: t('billing:professional.price-explanation')!, + subtext: t('billing:professional.subtext')!, + text: t('billing:professional.text')!, + buttonTextMain: t('billing:upgrade')!, + buttonTextSecondary: t('billing:learn-more')!, + current: currentPlan == STRIPE_PRODUCT_PRO, + }, + { + key: 3, + name: t('billing:enterprise.name')!, + price: t('billing:custom-pricing')!, + text: t('billing:enterprise.text')!, + buttonTextMain: t('billing:schedule-demo')!, + buttonTextSecondary: t('billing:learn-more')!, + current: false, + }, + ]; + + useEffect(() => { + (async () => { + const orgId = localStorage.getItem('orgData.id') as string; + const subscriptions = await getOrganizationSubscriptions({ + orgId, + }); + + setCurrentPlan(subscriptions.data[0].plan.id); + const orgUsers = await getOrganizationUsers({ + orgId, + }); + setNumUsers(orgUsers.length); + })(); + }, []); + + return ( +
+ + {t('common:head-title', { title: t('billing:title') })} + + +
+
+ +
+
+

+ {t('billing:title')} +

+

+ {t('billing:description')} +

+
+
+
+

{t('billing:subscription')}

+
+ {plans.map((plan) => ( + + ))} +
+

+ {t('billing:current-usage')} +

+
+
+

{numUsers}

+

+ {numUsers > 1 + ? 'Organization members' + : 'Organization member'} +

+
+ {/*
+

1

+

Organization projects

+
*/} +
+
+
+
+
+ ); +} + +SettingsBilling.requireAuth = true; + +export const getServerSideProps = getTranslatedServerSideProps([ + 'settings', + 'billing', +]); diff --git a/frontend/pages/settings/org/[id].js b/frontend/pages/settings/org/[id].tsx similarity index 55% rename from frontend/pages/settings/org/[id].js rename to frontend/pages/settings/org/[id].tsx index cec025780e..1370afa69e 100644 --- a/frontend/pages/settings/org/[id].js +++ b/frontend/pages/settings/org/[id].tsx @@ -1,23 +1,23 @@ -import { useEffect, useState } from "react"; -import Head from "next/head"; -import { useRouter } from "next/router"; -import { useTranslation } from "next-i18next"; +import { useEffect, useState } from 'react'; +import Head from 'next/head'; +import { useRouter } from 'next/router'; +import { useTranslation } from 'next-i18next'; import { faMagnifyingGlass, faPlus, - faX + faX, } from '@fortawesome/free-solid-svg-icons'; import { faCheck } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import Button from "~/components/basic/buttons/Button"; -import AddIncidentContactDialog from "~/components/basic/dialog/AddIncidentContactDialog"; -import AddUserDialog from "~/components/basic/dialog/AddUserDialog"; -import InputField from "~/components/basic/InputField"; -import UserTable from "~/components/basic/table/UserTable"; -import NavHeader from "~/components/navigation/NavHeader"; -import guidGenerator from "~/utilities/randomId"; -import { getTranslatedServerSideProps } from "~/utilities/withTranslateProps"; +import Button from '~/components/basic/buttons/Button'; +import AddIncidentContactDialog from '~/components/basic/dialog/AddIncidentContactDialog'; +import AddUserDialog from '~/components/basic/dialog/AddUserDialog'; +import InputField from '~/components/basic/InputField'; +import UserTable from '~/components/basic/table/UserTable'; +import NavHeader from '~/components/navigation/NavHeader'; +import guidGenerator from '~/utilities/randomId'; +import { getTranslatedServerSideProps } from '~/utilities/withTranslateProps'; import addUserToOrg from '../../api/organization/addUserToOrg'; import deleteIncidentContact from '../../api/organization/deleteIncidentContact'; @@ -37,74 +37,76 @@ export default function SettingsOrg() { const [emailUser, setEmailUser] = useState(''); const [workspaceToBeDeletedName, setWorkspaceToBeDeletedName] = useState(''); const [searchUsers, setSearchUsers] = useState(''); - const [workspaceId, setWorkspaceId] = useState(''); const [isAddIncidentContactOpen, setIsAddIncidentContactOpen] = useState(false); const [isAddUserOpen, setIsAddUserOpen] = useState( router.asPath.split('?')[1] == 'invite' ); - const [incidentContacts, setIncidentContacts] = useState([]); + const [incidentContacts, setIncidentContacts] = useState([]); const [searchIncidentContact, setSearchIncidentContact] = useState(''); - const [userList, setUserList] = useState(); + const [userList, setUserList] = useState([]); const [personalEmail, setPersonalEmail] = useState(''); - let workspaceIdTemp; const [email, setEmail] = useState(''); const [currentPlan, setCurrentPlan] = useState(''); + const workspaceId = router.query.id as string; + const { t } = useTranslation(); - useEffect(async () => { - let org = await getOrganization({ - orgId: localStorage.getItem('orgData.id') - }); - let orgData = org; - setOrgName(orgData.name); - let incidentContactsData = await getIncidentContacts( - localStorage.getItem('orgData.id') - ); + useEffect(() => { + (async () => { + const orgId = localStorage.getItem('orgData.id') as string; + const org = await getOrganization({ + orgId, + }); - setIncidentContacts(incidentContactsData?.map((contact) => contact.email)); + setOrgName(org.name); + const incidentContactsData = await getIncidentContacts( + localStorage.getItem('orgData.id') as string + ); - const user = await getUser(); - setPersonalEmail(user.email); + setIncidentContacts( + incidentContactsData?.map((contact) => contact.email) + ); - workspaceIdTemp = router.query.id; - let orgUsers = await getOrganizationUsers({ - orgId: localStorage.getItem('orgData.id') - }); - setUserList( - orgUsers.map((user) => ({ - key: guidGenerator(), - firstName: user.user?.firstName, - lastName: user.user?.lastName, - email: user.user?.email == null ? user.inviteEmail : user.user?.email, - role: user?.role, - status: user?.status, - userId: user.user?._id, - membershipId: user._id, - publicKey: user.user?.publicKey - })) - ); - const subscriptions = await getOrganizationSubscriptions({ - orgId: localStorage.getItem('orgData.id') - }); - setCurrentPlan(subscriptions.data[0].plan.product); + const user = await getUser(); + setPersonalEmail(user.email); + + const orgUsers = await getOrganizationUsers({ + orgId, + }); + + setUserList( + orgUsers.map((user) => ({ + key: guidGenerator(), + firstName: user.user?.firstName, + lastName: user.user?.lastName, + email: user.user?.email == null ? user.inviteEmail : user.user?.email, + role: user?.role, + status: user?.status, + userId: user.user?._id, + membershipId: user._id, + publicKey: user.user?.publicKey, + })) + ); + + const subscriptions = await getOrganizationSubscriptions({ + orgId, + }); + setCurrentPlan(subscriptions.data[0].plan.product); + })(); }, []); - const modifyOrgName = (newName) => { + const modifyOrgName = (newName: string) => { setButtonReady(true); setOrgName(newName); }; - const submitChanges = (newOrgName) => { - renameOrg(localStorage.getItem('orgData.id'), newOrgName); + const submitChanges = (newOrgName: string) => { + renameOrg(localStorage.getItem('orgData.id') as string, newOrgName); setButtonReady(false); }; - useEffect(async () => { - setWorkspaceId(router.query.id); - }, []); - function closeAddUserModal() { setIsAddUserOpen(false); } @@ -121,18 +123,21 @@ export default function SettingsOrg() { setIsAddIncidentContactOpen(true); } - async function submitAddUserModal(email) { - await addUserToOrg(email, localStorage.getItem('orgData.id')); + async function submitAddUserModal(email: string) { + await addUserToOrg(email, localStorage.getItem('orgData.id') as string); setEmail(''); setIsAddUserOpen(false); router.reload(); } - const deleteIncidentContactFully = (incidentContact) => { + const deleteIncidentContactFully = (incidentContact: string) => { setIncidentContacts( incidentContacts.filter((contact) => contact != incidentContact) ); - deleteIncidentContact(localStorage.getItem('orgData.id'), incidentContact); + deleteIncidentContact( + localStorage.getItem('orgData.id') as string, + incidentContact + ); }; /** @@ -142,32 +147,31 @@ export default function SettingsOrg() { * It then deletes the workspace and forwards the user to another aviable workspace. */ const executeDeletingWorkspace = async () => { - let userWorkspaces = await getWorkspaces(); + const userWorkspaces = await getWorkspaces(); if (userWorkspaces.length > 1) { if ( - userWorkspaces.filter( - (workspace) => workspace._id == router.query.id - )[0].name == workspaceToBeDeletedName + userWorkspaces.filter((workspace) => workspace._id == workspaceId)[0] + .name == workspaceToBeDeletedName ) { - await deleteWorkspace(router.query.id); - let userWorkspaces = await getWorkspaces(); + await deleteWorkspace(workspaceId); + const userWorkspaces = await getWorkspaces(); router.push('/dashboard/' + userWorkspaces[0]._id); } } }; return ( -
+
- {t("common:head-title", { title: t("settings-org:title") })} + {t('common:head-title', { title: t('settings-org:title') })} - + -
-
- +
+
+ -
-
-

- {t("settings-org:title")} +

+
+

+ {t('settings-org:title')}

-

- {t("settings-org:description")} +

+ {t('settings-org:description')}

-
-
-
-
-
-

- {t("common:display-name")} +

+
+
+
+
+

+ {t('common:display-name')}

-
+
-
-

- {t("section-members:org-members")} +

+

+ {t('section-members:org-members')}

-

- {t("section-members:org-members-description")} +

+ {t('section-members:org-members-description')}

{/* */} -
-
+
+
setSearchUsers(e.target.value)} - placeholder={t("section-members:search-members")} + placeholder={t('section-members:search-members') as string} />
-
+
{userList && ( -
+
)}
-
-
-
-

- {t("section-incident:incident-contacts")} +

+
+
+

+ {t('section-incident:incident-contacts')}

-

- {t("section-incident:incident-contacts-description")} +

+ {t('section-incident:incident-contacts-description')}

-
+
-
+
setSearchIncidentContact(e.target.value)} - placeholder={t("common:search")} + placeholder={t('common:search') as string} />
{incidentContacts?.filter((email) => @@ -317,25 +322,25 @@ export default function SettingsOrg() { .map((contact) => (
-

{contact}

-
+

{contact}

+
)) ) : ( -
-

- {t("section-incident:no-incident-contacts")} +

+

+ {t('section-incident:no-incident-contacts')}

)} @@ -386,8 +391,8 @@ export default function SettingsOrg() { SettingsOrg.requireAuth = true; export const getServerSideProps = getTranslatedServerSideProps([ - "settings", - "settings-org", - "section-incident", - "section-members", + 'settings', + 'settings-org', + 'section-incident', + 'section-members', ]); diff --git a/frontend/pages/settings/personal/[id].js b/frontend/pages/settings/personal/[id].tsx similarity index 52% rename from frontend/pages/settings/personal/[id].js rename to frontend/pages/settings/personal/[id].tsx index a592bf45be..bae7a54a24 100644 --- a/frontend/pages/settings/personal/[id].js +++ b/frontend/pages/settings/personal/[id].tsx @@ -1,77 +1,78 @@ -import { useEffect, useState } from "react"; -import Head from "next/head"; -import { useRouter } from "next/router"; -import { useTranslation } from "next-i18next"; -import { faCheck, faX } from "@fortawesome/free-solid-svg-icons"; -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { useEffect, useState } from 'react'; +import Head from 'next/head'; +import { useRouter } from 'next/router'; +import { useTranslation } from 'next-i18next'; +import { faCheck, faX } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import Button from "~/components/basic/buttons/Button"; -import InputField from "~/components/basic/InputField"; -import ListBox from "~/components/basic/Listbox"; -import NavHeader from "~/components/navigation/NavHeader"; -import changePassword from "~/components/utilities/cryptography/changePassword"; -import issueBackupKey from "~/components/utilities/cryptography/issueBackupKey"; -import passwordCheck from "~/utilities/checks/PasswordCheck"; -import { getTranslatedServerSideProps } from "~/utilities/withTranslateProps"; +import Button from '~/components/basic/buttons/Button'; +import InputField from '~/components/basic/InputField'; +import ListBox from '~/components/basic/Listbox'; +import NavHeader from '~/components/navigation/NavHeader'; +import changePassword from '~/components/utilities/cryptography/changePassword'; +import issueBackupKey from '~/components/utilities/cryptography/issueBackupKey'; +import passwordCheck from '~/utilities/checks/PasswordCheck'; +import { getTranslatedServerSideProps } from '~/utilities/withTranslateProps'; -import getUser from "../../api/user/getUser"; +import getUser from '../../api/user/getUser'; export default function PersonalSettings() { - const [personalEmail, setPersonalEmail] = useState(""); - const [personalName, setPersonalName] = useState(""); + const [personalEmail, setPersonalEmail] = useState(''); + const [personalName, setPersonalName] = useState(''); const [passwordErrorLength, setPasswordErrorLength] = useState(false); const [passwordErrorNumber, setPasswordErrorNumber] = useState(false); const [passwordErrorLowerCase, setPasswordErrorLowerCase] = useState(false); const [currentPasswordError, setCurrentPasswordError] = useState(false); - const [currentPassword, setCurrentPassword] = useState(""); - const [newPassword, setNewPassword] = useState(""); - const [backupPassword, setBackupPassword] = useState(""); + const [currentPassword, setCurrentPassword] = useState(''); + const [newPassword, setNewPassword] = useState(''); + const [backupPassword, setBackupPassword] = useState(''); const [passwordChanged, setPasswordChanged] = useState(false); const [backupKeyIssued, setBackupKeyIssued] = useState(false); const [backupKeyError, setBackupKeyError] = useState(false); const { t } = useTranslation(); const router = useRouter(); - const lang = router.locale ?? "en"; + const lang = router.locale ?? 'en'; - const setLanguage = async (to) => { + const setLanguage = async (to: string) => { router.push(router.asPath, router.asPath, { locale: to }); - localStorage.setItem("lang", to); + localStorage.setItem('lang', to); }; - useEffect(async () => { - let user = await getUser(); - setPersonalEmail(user.email); - setPersonalName(user.firstName + " " + user.lastName); + useEffect(() => { + getUser().then((user) => { + setPersonalEmail(user.email); + setPersonalName(user.firstName + ' ' + user.lastName); + }); }, []); return ( -
+
- {t("common:head-title", { title: t("settings-personal:title") })} + {t('common:head-title', { title: t('settings-personal:title') })} - + -
-
+
+
-
-
-

- {t("settings-personal:title")} +

+
+

+ {t('settings-personal:title')}

-

- {t("settings-personal:description")} +

+ {t('settings-personal:description')}

-
-
-
+
+
+
{/*

@@ -118,46 +119,45 @@ export default function PersonalSettings() {

*/}
-
-

- {t("settings-personal:change-language")} +

+

+ {t('settings-personal:change-language')}

-
+
-
-
-
-

- {t("section-password:change")} +

+
+
+

+ {t('section-password:change')}

-
+
{ setCurrentPassword(password); }} - type="password" + type='password' value={currentPassword} isRequired error={currentPasswordError} - errorText={t("section-password:current-wrong")} - autoComplete="current-password" - id="current-password" + errorText={t('section-password:current-wrong') as string} + autoComplete='current-password' + id='current-password' /> -
+
{ setNewPassword(password); passwordCheck({ @@ -165,10 +165,10 @@ export default function PersonalSettings() { setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - currentErrorCheck: false, + errorCheck: false, }); }} - type="password" + type='password' value={newPassword} isRequired error={ @@ -176,86 +176,86 @@ export default function PersonalSettings() { passwordErrorLowerCase && passwordErrorNumber } - autoComplete="new-password" - id="new-password" + autoComplete='new-password' + id='new-password' />
{passwordErrorLength || passwordErrorLowerCase || passwordErrorNumber ? ( -
+
- {t("section-password:validate-base")} + {t('section-password:validate-base')}
-
+
{passwordErrorLength ? ( ) : ( )}
- {t("section-password:validate-length")} + {t('section-password:validate-length')}
-
+
{passwordErrorLowerCase ? ( ) : ( )}
- {t("section-password:validate-case")} + {t('section-password:validate-case')}
-
+
{passwordErrorNumber ? ( ) : ( )}
- {t("section-password:validate-number")} + {t('section-password:validate-number')}
) : ( -
+
)} -
+
-
-
-
-

- {t("settings-personal:emergency.name")} +

+
+
+

+ {t('settings-personal:emergency.name')}

-

- {t("settings-personal:emergency.text1")} +

+ {t('settings-personal:emergency.text1')}

-

- {t("settings-personal:emergency.text2")} +

+ {t('settings-personal:emergency.text2')}

-
+
-
+
@@ -357,7 +359,7 @@ export default function PersonalSettings() { PersonalSettings.requireAuth = true; export const getServerSideProps = getTranslatedServerSideProps([ - "settings", - "settings-personal", - "section-password", + 'settings', + 'settings-personal', + 'section-password', ]); diff --git a/frontend/pages/settings/project/[id].tsx b/frontend/pages/settings/project/[id].tsx index 5b9e3f5de9..382ce6d43a 100644 --- a/frontend/pages/settings/project/[id].tsx +++ b/frontend/pages/settings/project/[id].tsx @@ -101,9 +101,8 @@ export default function SettingsBasic() { if (userWorkspaces.length > 1) { if ( - userWorkspaces.filter( - (workspace) => workspace._id === workspaceId - )[0].name == workspaceToBeDeletedName + userWorkspaces.filter((workspace) => workspace._id === workspaceId)[0] + .name == workspaceToBeDeletedName ) { await deleteWorkspace(workspaceId); const userWorkspaces = await getWorkspaces(); @@ -323,7 +322,7 @@ export default function SettingsBasic() {

{ setIsLoading(true); - var errorCheck = false; + let errorCheck = false; if (!firstName) { setFirstNameError(true); errorCheck = true; @@ -63,7 +64,7 @@ export default function SignupInvite() { setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - errorCheck + errorCheck, }); if (!errorCheck) { @@ -71,8 +72,8 @@ export default function SignupInvite() { const pair = nacl.box.keyPair(); const secretKeyUint8Array = pair.secretKey; const publicKeyUint8Array = pair.publicKey; - const PRIVATE_KEY = nacl.util.encodeBase64(secretKeyUint8Array); - const PUBLIC_KEY = nacl.util.encodeBase64(publicKeyUint8Array); + const PRIVATE_KEY = encodeBase64(secretKeyUint8Array); + const PUBLIC_KEY = encodeBase64(publicKeyUint8Array); const { ciphertext, iv, tag } = Aes256Gcm.encrypt({ text: PRIVATE_KEY, @@ -81,7 +82,7 @@ export default function SignupInvite() { .padStart( 32 + (password.slice(0, 32).length - new Blob([password]).size), '0' - ) + ), }); localStorage.setItem('PRIVATE_KEY', PRIVATE_KEY); @@ -89,7 +90,7 @@ export default function SignupInvite() { client.init( { username: email, - password: password + password: password, }, async () => { client.createVerifier(async (err, result) => { @@ -103,11 +104,11 @@ export default function SignupInvite() { tag, salt: result.salt, verifier: result.verifier, - token: verificationToken + token: verificationToken, }); // if everything works, go the main dashboard page. - if (!errorCheck && response.status == '200') { + if (!errorCheck && response.status == 200) { response = await response.json(); localStorage.setItem('publicKey', PUBLIC_KEY); @@ -140,42 +141,42 @@ export default function SignupInvite() { // Step 4 of the sign up process (download the emergency kit pdf) const stepConfirmEmail = ( -
-

+

+

Confirm your email

verify email -
+
@@ -183,37 +184,37 @@ export default function SignupInvite() { // Because this is the invite signup - we directly go to the last step of signup (email is already verified) const main = ( -
-

+

+

Almost there!

-
+
-
+
-
+
{ setPassword(password); passwordCheck({ @@ -221,35 +222,35 @@ export default function SignupInvite() { setPasswordErrorLength, setPasswordErrorNumber, setPasswordErrorLowerCase, - currentErrorCheck: false + errorCheck: false, }); }} - type="password" + type='password' value={password} isRequired error={ passwordErrorLength && passwordErrorNumber && passwordErrorLowerCase } - autoComplete="new-password" - id="new-password" + autoComplete='new-password' + id='new-password' /> {passwordErrorLength || passwordErrorLowerCase || passwordErrorNumber ? ( -
+
Password should contain at least:
-
+
{passwordErrorLength ? ( ) : ( )}
-
+
{passwordErrorLowerCase ? ( ) : ( )}
-
+
{passwordErrorNumber ? ( ) : ( )}
) : ( -
+
)}
-
+
@@ -320,38 +321,38 @@ export default function SignupInvite() { // Step 4 of the sign up process (download the emergency kit pdf) const step4 = ( -
-

+

+

Save your Emergency Kit

-
+
If you get locked out of your account, your Emergency Kit is the only way to sign in.
-
+
We recommend you download it and keep it somewhere safe.
-
- +
+ It contains your Secret Key which we cannot access or recover for you if you lose it.
-
+
-
+
) : ( -
-
+
+
loading animation
); @@ -233,7 +251,7 @@ export default function Users() { Users.requireAuth = true; export const getServerSideProps = getTranslatedServerSideProps([ - "settings", - "settings-members", - "section-members", + 'settings', + 'settings-members', + 'section-members', ]); diff --git a/frontend/pages/vercel.js b/frontend/pages/vercel.js deleted file mode 100644 index 7b15769b1b..0000000000 --- a/frontend/pages/vercel.js +++ /dev/null @@ -1,40 +0,0 @@ -import { useEffect } from "react"; -import Head from "next/head"; -import { useRouter } from "next/router"; -const queryString = require("query-string"); -import AuthorizeIntegration from "./api/integrations/authorizeIntegration"; - -export default function Vercel() { - const router = useRouter(); - const parsedUrl = queryString.parse(router.asPath.split("?")[1]); - const code = parsedUrl.code; - const state = parsedUrl.state - - /** - * Here we forward to the default workspace if a user opens this url - */ - // eslint-disable-next-line react-hooks/exhaustive-deps - useEffect(async () => { - try { - if (state === localStorage.getItem('latestCSRFToken')) { - localStorage.removeItem('latestCSRFToken'); - - await AuthorizeIntegration({ - workspaceId: localStorage.getItem('projectData.id'), - code, - integration: "vercel" - }); - - router.push("/integrations/" + localStorage.getItem("projectData.id")); - } - } catch (err) { - console.error('Vercel integration error: ', err); - } - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return
; -} - -Vercel.requireAuth = true; diff --git a/frontend/pages/vercel.tsx b/frontend/pages/vercel.tsx new file mode 100644 index 0000000000..a6fa3c80d5 --- /dev/null +++ b/frontend/pages/vercel.tsx @@ -0,0 +1,46 @@ +import { useEffect } from 'react'; +import { useRouter } from 'next/router'; +import queryString from 'query-string'; + +import AuthorizeIntegration from './api/integrations/authorizeIntegration'; + +export default function Vercel() { + const router = useRouter(); + const parsedUrl = queryString.parse(router.asPath.split('?')[1]); + const code = parsedUrl.code; + const state = parsedUrl.state; + + /** + * Here we forward to the default workspace if a user opens this url + */ + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(() => { + (async () => { + try { + // type check + if (!code) throw new Error('Code not found'); + + if (state === localStorage.getItem('latestCSRFToken')) { + localStorage.removeItem('latestCSRFToken'); + + await AuthorizeIntegration({ + workspaceId: localStorage.getItem('projectData.id') as string, + code: code as string, + integration: 'vercel', + }); + + router.push( + '/integrations/' + localStorage.getItem('projectData.id') + ); + } + } catch (err) { + console.error('Vercel integration error: ', err); + } + })(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return
; +} + +Vercel.requireAuth = true; diff --git a/frontend/tsconfig.tsbuildinfo b/frontend/tsconfig.tsbuildinfo new file mode 100644 index 0000000000..0dd714d7ac --- /dev/null +++ b/frontend/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"program":{"fileNames":["./node_modules/typescript/lib/lib.es5.d.ts","./node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/typescript/lib/lib.es2021.d.ts","./node_modules/typescript/lib/lib.es2022.d.ts","./node_modules/typescript/lib/lib.esnext.d.ts","./node_modules/typescript/lib/lib.dom.d.ts","./node_modules/typescript/lib/lib.dom.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/typescript/lib/lib.es2021.promise.d.ts","./node_modules/typescript/lib/lib.es2021.string.d.ts","./node_modules/typescript/lib/lib.es2021.weakref.d.ts","./node_modules/typescript/lib/lib.es2021.intl.d.ts","./node_modules/typescript/lib/lib.es2022.array.d.ts","./node_modules/typescript/lib/lib.es2022.error.d.ts","./node_modules/typescript/lib/lib.es2022.intl.d.ts","./node_modules/typescript/lib/lib.es2022.object.d.ts","./node_modules/typescript/lib/lib.es2022.sharedmemory.d.ts","./node_modules/typescript/lib/lib.es2022.string.d.ts","./node_modules/typescript/lib/lib.esnext.intl.d.ts","./node_modules/next/dist/styled-jsx/types/css.d.ts","./node_modules/@types/react/global.d.ts","./node_modules/csstype/index.d.ts","./node_modules/@types/prop-types/index.d.ts","./node_modules/@types/scheduler/tracing.d.ts","./node_modules/@types/react/index.d.ts","./node_modules/next/dist/styled-jsx/types/index.d.ts","./node_modules/next/dist/styled-jsx/types/macro.d.ts","./node_modules/next/dist/styled-jsx/types/style.d.ts","./node_modules/next/dist/styled-jsx/types/global.d.ts","./node_modules/next/dist/shared/lib/amp.d.ts","./node_modules/next/amp.d.ts","./node_modules/@types/node/assert.d.ts","./node_modules/@types/node/assert/strict.d.ts","./node_modules/@types/node/globals.d.ts","./node_modules/@types/node/async_hooks.d.ts","./node_modules/@types/node/buffer.d.ts","./node_modules/@types/node/child_process.d.ts","./node_modules/@types/node/cluster.d.ts","./node_modules/@types/node/console.d.ts","./node_modules/@types/node/constants.d.ts","./node_modules/@types/node/crypto.d.ts","./node_modules/@types/node/dgram.d.ts","./node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/@types/node/dns.d.ts","./node_modules/@types/node/dns/promises.d.ts","./node_modules/@types/node/domain.d.ts","./node_modules/@types/node/dom-events.d.ts","./node_modules/@types/node/events.d.ts","./node_modules/@types/node/fs.d.ts","./node_modules/@types/node/fs/promises.d.ts","./node_modules/@types/node/http.d.ts","./node_modules/@types/node/http2.d.ts","./node_modules/@types/node/https.d.ts","./node_modules/@types/node/inspector.d.ts","./node_modules/@types/node/module.d.ts","./node_modules/@types/node/net.d.ts","./node_modules/@types/node/os.d.ts","./node_modules/@types/node/path.d.ts","./node_modules/@types/node/perf_hooks.d.ts","./node_modules/@types/node/process.d.ts","./node_modules/@types/node/punycode.d.ts","./node_modules/@types/node/querystring.d.ts","./node_modules/@types/node/readline.d.ts","./node_modules/@types/node/readline/promises.d.ts","./node_modules/@types/node/repl.d.ts","./node_modules/@types/node/stream.d.ts","./node_modules/@types/node/stream/promises.d.ts","./node_modules/@types/node/stream/consumers.d.ts","./node_modules/@types/node/stream/web.d.ts","./node_modules/@types/node/string_decoder.d.ts","./node_modules/@types/node/test.d.ts","./node_modules/@types/node/timers.d.ts","./node_modules/@types/node/timers/promises.d.ts","./node_modules/@types/node/tls.d.ts","./node_modules/@types/node/trace_events.d.ts","./node_modules/@types/node/tty.d.ts","./node_modules/@types/node/url.d.ts","./node_modules/@types/node/util.d.ts","./node_modules/@types/node/v8.d.ts","./node_modules/@types/node/vm.d.ts","./node_modules/@types/node/wasi.d.ts","./node_modules/@types/node/worker_threads.d.ts","./node_modules/@types/node/zlib.d.ts","./node_modules/@types/node/globals.global.d.ts","./node_modules/@types/node/index.d.ts","./node_modules/next/dist/server/get-page-files.d.ts","./node_modules/next/dist/compiled/webpack/webpack.d.ts","./node_modules/next/dist/server/config.d.ts","./node_modules/next/dist/lib/load-custom-routes.d.ts","./node_modules/next/dist/shared/lib/image-config.d.ts","./node_modules/next/dist/build/webpack/plugins/subresource-integrity-plugin.d.ts","./node_modules/next/dist/server/config-shared.d.ts","./node_modules/next/dist/server/base-http/index.d.ts","./node_modules/next/dist/server/api-utils/index.d.ts","./node_modules/next/dist/shared/lib/router/utils/route-regex.d.ts","./node_modules/next/dist/shared/lib/router/utils/route-matcher.d.ts","./node_modules/next/dist/server/body-streams.d.ts","./node_modules/next/dist/server/request-meta.d.ts","./node_modules/next/dist/server/router.d.ts","./node_modules/next/dist/build/analysis/get-page-static-info.d.ts","./node_modules/next/dist/build/webpack/loaders/get-module-build-info.d.ts","./node_modules/next/dist/build/webpack/plugins/middleware-plugin.d.ts","./node_modules/next/dist/server/render-result.d.ts","./node_modules/next/dist/server/web/next-url.d.ts","./node_modules/next/dist/server/web/spec-extension/cookies.d.ts","./node_modules/next/dist/server/web/spec-extension/request.d.ts","./node_modules/next/dist/server/web/spec-extension/fetch-event.d.ts","./node_modules/next/dist/server/web/spec-extension/response.d.ts","./node_modules/next/dist/server/web/types.d.ts","./node_modules/next/dist/build/index.d.ts","./node_modules/next/dist/build/webpack/plugins/pages-manifest-plugin.d.ts","./node_modules/next/dist/server/send-payload/revalidate-headers.d.ts","./node_modules/next/dist/server/send-payload/index.d.ts","./node_modules/next/dist/server/base-http/node.d.ts","./node_modules/next/dist/server/font-utils.d.ts","./node_modules/next/dist/server/load-components.d.ts","./node_modules/next/dist/server/render.d.ts","./node_modules/next/dist/shared/lib/router/utils/parse-url.d.ts","./node_modules/next/dist/shared/lib/router/utils/middleware-route-matcher.d.ts","./node_modules/next/dist/server/response-cache/types.d.ts","./node_modules/next/dist/server/response-cache/index.d.ts","./node_modules/next/dist/server/base-server.d.ts","./node_modules/next/dist/server/image-optimizer.d.ts","./node_modules/next/dist/server/next-server.d.ts","./node_modules/next/dist/server/dev/static-paths-worker.d.ts","./node_modules/next/dist/server/dev/next-dev-server.d.ts","./node_modules/next/dist/server/next.d.ts","./node_modules/next/types/index.d.ts","./node_modules/next/dist/shared/lib/html-context.d.ts","./node_modules/@next/env/types/index.d.ts","./node_modules/next/dist/shared/lib/mitt.d.ts","./node_modules/next/dist/client/with-router.d.ts","./node_modules/next/dist/client/router.d.ts","./node_modules/next/dist/client/route-loader.d.ts","./node_modules/next/dist/client/page-loader.d.ts","./node_modules/next/dist/shared/lib/router/router.d.ts","./node_modules/next/dist/shared/lib/constants.d.ts","./node_modules/next/dist/shared/lib/utils.d.ts","./node_modules/next/dist/pages/_app.d.ts","./node_modules/next/app.d.ts","./node_modules/next/dist/shared/lib/runtime-config.d.ts","./node_modules/next/config.d.ts","./node_modules/next/dist/pages/_document.d.ts","./node_modules/next/document.d.ts","./node_modules/next/dist/shared/lib/dynamic.d.ts","./node_modules/next/dynamic.d.ts","./node_modules/next/dist/pages/_error.d.ts","./node_modules/next/error.d.ts","./node_modules/next/dist/shared/lib/head.d.ts","./node_modules/next/head.d.ts","./node_modules/next/dist/client/image.d.ts","./node_modules/next/image.d.ts","./node_modules/next/dist/client/link.d.ts","./node_modules/next/link.d.ts","./node_modules/next/router.d.ts","./node_modules/next/dist/client/script.d.ts","./node_modules/next/script.d.ts","./node_modules/next/dist/server/web/spec-extension/user-agent.d.ts","./node_modules/next/dist/compiled/@edge-runtime/primitives/url.d.ts","./node_modules/next/server.d.ts","./node_modules/next/types/global.d.ts","./node_modules/next/index.d.ts","./node_modules/next/image-types/global.d.ts","./next-env.d.ts","./const.ts","./node_modules/@sentry/types/types/attachment.d.ts","./node_modules/@sentry/types/types/severity.d.ts","./node_modules/@sentry/types/types/breadcrumb.d.ts","./node_modules/@sentry/types/types/datacategory.d.ts","./node_modules/@sentry/types/types/clientreport.d.ts","./node_modules/@sentry/types/types/dsn.d.ts","./node_modules/@sentry/types/types/context.d.ts","./node_modules/@sentry/types/types/debugmeta.d.ts","./node_modules/@sentry/types/types/mechanism.d.ts","./node_modules/@sentry/types/types/stackframe.d.ts","./node_modules/@sentry/types/types/stacktrace.d.ts","./node_modules/@sentry/types/types/exception.d.ts","./node_modules/@sentry/types/types/extra.d.ts","./node_modules/@sentry/types/types/measurement.d.ts","./node_modules/@sentry/types/types/request.d.ts","./node_modules/@sentry/types/types/misc.d.ts","./node_modules/@sentry/types/types/eventprocessor.d.ts","./node_modules/@sentry/types/types/user.d.ts","./node_modules/@sentry/types/types/session.d.ts","./node_modules/@sentry/types/types/package.d.ts","./node_modules/@sentry/types/types/sdkinfo.d.ts","./node_modules/@sentry/types/types/envelope.d.ts","./node_modules/@sentry/types/types/polymorphics.d.ts","./node_modules/@sentry/types/types/transaction.d.ts","./node_modules/@sentry/types/types/span.d.ts","./node_modules/@sentry/types/types/scope.d.ts","./node_modules/@sentry/types/types/event.d.ts","./node_modules/@sentry/types/types/hub.d.ts","./node_modules/@sentry/types/types/integration.d.ts","./node_modules/@sentry/types/types/sdkmetadata.d.ts","./node_modules/@sentry/types/types/textencoder.d.ts","./node_modules/@sentry/types/types/transport.d.ts","./node_modules/@sentry/types/types/options.d.ts","./node_modules/@sentry/types/types/client.d.ts","./node_modules/@sentry/types/types/error.d.ts","./node_modules/@sentry/types/types/globals.d.ts","./node_modules/@sentry/types/types/runtime.d.ts","./node_modules/@sentry/types/types/tracing.d.ts","./node_modules/@sentry/types/types/thread.d.ts","./node_modules/@sentry/types/types/wrappedfunction.d.ts","./node_modules/@sentry/types/types/index.d.ts","./node_modules/posthog-js/dist/module.d.ts","./components/utilities/config/index.ts","./components/analytics/posthog.ts","./pages/api/auth/token.ts","./components/utilities/securityclient.ts","./public/data/frequentinterfaces.ts","./components/utilities/cryptography/aes-256-gcm.ts","./pages/api/auth/login1.ts","./pages/api/auth/login2.ts","./pages/api/files/addsecrets.ts","./pages/api/organization/getorgs.ts","./pages/api/organization/getorguserprojects.ts","./pages/api/user/getuser.ts","./pages/api/workspace/uploadkeys.ts","./components/utilities/cryptography/crypto.ts","./pages/api/workspace/getlatestfilekey.ts","./components/utilities/secrets/encryptsecrets.ts","./components/utilities/telemetry/telemetry.ts","./components/utilities/savetokentolocalstorage.ts","./components/utilities/attemptlogin.ts","./node_modules/jspdf/types/index.d.ts","./components/utilities/generatebackuppdf.ts","./components/utilities/parsedotenv.ts","./components/utilities/randomid.ts","./node_modules/i18next/index.d.ts","./node_modules/react-i18next/transwithoutcontext.d.ts","./node_modules/react-i18next/initreacti18next.d.ts","./node_modules/react-i18next/index.d.ts","./node_modules/@types/hoist-non-react-statics/index.d.ts","./node_modules/next-i18next/dist/types/appwithtranslation.d.ts","./node_modules/next-i18next/dist/types/index.d.ts","./node_modules/next-i18next/dist/types/types.d.ts","./node_modules/next-i18next/dist/types/serversidetranslations.d.ts","./node_modules/next-i18next/serversidetranslations.d.ts","./components/utilities/withtranslateprops.ts","./pages/api/organization/getorgusers.ts","./pages/api/useractions/checkuseraction.ts","./components/utilities/checks/onboardingcheck.ts","./components/utilities/checks/passwordcheck.ts","./components/utilities/checks/templocalstorage.ts","./node_modules/@types/jsrp/index.d.ts","./pages/api/auth/changepassword2.ts","./pages/api/auth/srp1.ts","./components/utilities/cryptography/changepassword.ts","./pages/api/auth/issuebackupprivatekey.ts","./components/utilities/cryptography/issuebackupkey.ts","./components/utilities/secrets/checkoverrides.ts","./public/data/frequentconstants.ts","./components/utilities/secrets/downloaddotenv.ts","./components/utilities/secrets/downloadyaml.ts","./pages/api/files/getsecrets.ts","./components/utilities/secrets/getsecretsforproject.ts","./ee/api/secrets/getactiondata.ts","./ee/api/secrets/getprojectlogs.ts","./ee/api/secrets/getprojectsercetshanpshots.ts","./ee/api/secrets/getprojectsercetsnapshotscount.ts","./ee/api/secrets/getsecretsnapshotdata.ts","./ee/api/secrets/getsecretversions.ts","./ee/api/secrets/performsecretrollback.ts","./ee/utilities/findtextdifferences.ts","./ee/utilities/timesince.ts","./hooks/usepopup.tsx","./hooks/index.ts","./pages/api/auth/checkauth.ts","./pages/api/auth/checkemailverificationcode.ts","./pages/api/auth/completeaccountinformationsignup.ts","./pages/api/auth/completeaccountinformationsignupinvite.ts","./pages/api/auth/emailverifyonpasswordreset.ts","./pages/api/auth/logout.ts","./pages/api/auth/sendemailonpasswordreset.ts","./pages/api/auth/sendverificationemail.ts","./pages/api/auth/verifysignupinvite.ts","./pages/api/auth/getbackupencryptedprivatekey.ts","./pages/api/auth/publickeyinfisical.ts","./pages/api/auth/resetpasswordonaccountrecovery.ts","./pages/api/bot/getbot.ts","./pages/api/bot/setbotactivestatus.ts","./pages/api/environments/createenvironment.ts","./pages/api/environments/deleteenvironment.ts","./pages/api/environments/updateenvironment.ts","./pages/api/files/deletesecrets.ts","./pages/api/files/updatesecrets.ts","./pages/api/files/uploadsecrets.ts","./pages/api/integrations/changeherokuconfigvars.ts","./pages/api/integrations/deleteintegration.ts","./pages/api/integrations/deleteintegrationauth.ts","./pages/api/integrations/getintegrationapps.ts","./pages/api/integrations/getintegrationoptions.ts","./pages/api/integrations/startintegration.ts","./pages/api/integrations/authorizeintegration.ts","./pages/api/integrations/getworkspaceauthorizations.ts","./pages/api/integrations/getworkspaceintegrations.ts","./pages/api/integrations/updateintegration.ts","./pages/api/organization/getorg.ts","./pages/api/organization/getorgprojects.ts","./pages/api/organization/getorgsubscription.ts","./pages/api/organization/striperedirect.ts","./pages/api/organization/addincidentcontact.ts","./pages/api/organization/addusertoorg.ts","./pages/api/organization/deleteincidentcontact.ts","./pages/api/organization/deleteuserfromorganization.ts","./pages/api/organization/getincidentcontacts.ts","./pages/api/organization/renameorg.ts","./pages/api/servicetoken/addservicetoken.ts","./pages/api/servicetoken/deleteservicetoken.ts","./pages/api/servicetoken/getservicetokens.ts","./pages/api/useractions/registeruseraction.ts","./pages/api/workspace/addusertoworkspace.ts","./pages/api/workspace/changeuserroleinworkspace.ts","./pages/api/workspace/createworkspace.ts","./pages/api/workspace/deleteuserfromworkspace.ts","./pages/api/workspace/deleteworkspace.ts","./pages/api/workspace/getaworkspace.ts","./pages/api/workspace/getprojectinfo.ts","./pages/api/workspace/getworkspacekeys.ts","./pages/api/workspace/getworkspaceusers.ts","./pages/api/workspace/getworkspaces.ts","./pages/api/workspace/renameworkspace.ts","./components/routeguard.tsx","./node_modules/@fortawesome/fontawesome-common-types/index.d.ts","./node_modules/@fortawesome/free-solid-svg-icons/index.d.ts","./node_modules/@fortawesome/fontawesome-svg-core/index.d.ts","./node_modules/@fortawesome/react-fontawesome/index.d.ts","./components/basic/error.tsx","./node_modules/@headlessui/react/dist/types.d.ts","./node_modules/@headlessui/react/dist/utils/render.d.ts","./node_modules/@headlessui/react/dist/components/combobox/combobox.d.ts","./node_modules/@headlessui/react/dist/components/dialog/dialog.d.ts","./node_modules/@headlessui/react/dist/components/disclosure/disclosure.d.ts","./node_modules/@headlessui/react/dist/components/focus-trap/focus-trap.d.ts","./node_modules/@headlessui/react/dist/components/listbox/listbox.d.ts","./node_modules/@headlessui/react/dist/components/menu/menu.d.ts","./node_modules/@headlessui/react/dist/components/popover/popover.d.ts","./node_modules/@headlessui/react/dist/components/portal/portal.d.ts","./node_modules/@headlessui/react/dist/components/radio-group/radio-group.d.ts","./node_modules/@headlessui/react/dist/components/switch/switch.d.ts","./node_modules/@headlessui/react/dist/components/tabs/tabs.d.ts","./node_modules/@headlessui/react/dist/components/transitions/transition.d.ts","./node_modules/@headlessui/react/dist/index.d.ts","./components/basic/eventfilter.tsx","./components/basic/inputfield.tsx","./node_modules/@fortawesome/free-brands-svg-icons/index.d.ts","./node_modules/@fortawesome/free-regular-svg-icons/index.d.ts","./components/navigation/navbardashboard.tsx","./components/basic/buttons/button.tsx","./components/basic/table/checkbox.tsx","./components/basic/dialog/addworkspacedialog.js","./components/basic/listbox.tsx","./components/basic/layout.tsx","./components/basic/toggle.tsx","./components/basic/dialog/addupdateenvironmentdialog.tsx","./components/basic/dialog/deleteactionmodal.tsx","./components/basic/dialog/deleteenvvar.tsx","./components/basic/popups/bottomrightpopup.tsx","./components/basic/table/environmentstable.tsx","./components/context/notifications/notification.tsx","./components/context/notifications/notifications.tsx","./components/context/notifications/notificationprovider.tsx","./components/basic/table/servicetokentable.tsx","./components/billing/plan.tsx","./components/dashboard/commentfield.tsx","./components/dashboard/dashboardinputfield.tsx","./components/dashboard/deleteactionbutton.tsx","./components/dashboard/downloadsecretsmenu.tsx","./node_modules/yaml/dist/parse/line-counter.d.ts","./node_modules/yaml/dist/errors.d.ts","./node_modules/yaml/dist/doc/applyreviver.d.ts","./node_modules/yaml/dist/log.d.ts","./node_modules/yaml/dist/nodes/tojs.d.ts","./node_modules/yaml/dist/nodes/scalar.d.ts","./node_modules/yaml/dist/nodes/collection.d.ts","./node_modules/yaml/dist/nodes/yamlmap.d.ts","./node_modules/yaml/dist/nodes/yamlseq.d.ts","./node_modules/yaml/dist/schema/types.d.ts","./node_modules/yaml/dist/schema/schema.d.ts","./node_modules/yaml/dist/doc/createnode.d.ts","./node_modules/yaml/dist/nodes/addpairtojsmap.d.ts","./node_modules/yaml/dist/nodes/pair.d.ts","./node_modules/yaml/dist/schema/tags.d.ts","./node_modules/yaml/dist/options.d.ts","./node_modules/yaml/dist/stringify/stringify.d.ts","./node_modules/yaml/dist/nodes/node.d.ts","./node_modules/yaml/dist/parse/cst-scalar.d.ts","./node_modules/yaml/dist/parse/cst-stringify.d.ts","./node_modules/yaml/dist/parse/cst-visit.d.ts","./node_modules/yaml/dist/parse/cst.d.ts","./node_modules/yaml/dist/nodes/alias.d.ts","./node_modules/yaml/dist/doc/document.d.ts","./node_modules/yaml/dist/doc/directives.d.ts","./node_modules/yaml/dist/compose/composer.d.ts","./node_modules/yaml/dist/parse/lexer.d.ts","./node_modules/yaml/dist/parse/parser.d.ts","./node_modules/yaml/dist/public-api.d.ts","./node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts","./node_modules/yaml/dist/schema/yaml-1.1/set.d.ts","./node_modules/yaml/dist/visit.d.ts","./node_modules/yaml/dist/index.d.ts","./components/dashboard/dropzone.tsx","./components/dashboard/generatesecretmenu.tsx","./components/dashboard/keypair.tsx","./ee/components/secretversionlist.tsx","./components/dashboard/sidebar.tsx","./components/integrations/cloudintegration.tsx","./components/integrations/cloudintegrationsection.tsx","./components/integrations/frameworkintegration.tsx","./components/integrations/frameworkintegrationsection.tsx","./components/integrations/integration.tsx","./components/integrations/integrationsection.tsx","./components/navigation/navheader.tsx","./node_modules/react-code-input/src/reactcodeinput.d.ts","./components/signup/codeinputstep.tsx","./components/signup/donwloadbackuppdfstep.tsx","./components/signup/enteremailstep.tsx","./components/signup/teaminvitestep.tsx","./components/signup/userinfostep.tsx","./ee/components/activitysidebar.tsx","./ee/components/activitytable.tsx","./ee/components/pitrecoverysidebar.tsx","./pages/404.tsx","./pages/dashboard.tsx","./pages/email-not-verified.tsx","./node_modules/query-string/index.d.ts","./pages/github.tsx","./pages/heroku.tsx","./pages/index.tsx","./pages/login.tsx","./pages/netlify.tsx","./pages/noprojects.tsx","./pages/password-reset.tsx","./pages/requestnewinvite.tsx","./pages/signup.tsx","./node_modules/tweetnacl/nacl.d.ts","./node_modules/tweetnacl-util/nacl-util.d.ts","./pages/signupinvite.tsx","./pages/vercel.tsx","./pages/verify-email.tsx","./pages/activity/[id].tsx","./pages/dashboard/[id].tsx","./pages/home/[id].tsx","./components/basic/dialog/activatebotdialog.js","./public/json/frameworkintegrations.json","./pages/integrations/[id].tsx","./pages/settings/billing/[id].tsx","./components/basic/dialog/addincidentcontactdialog.js","./components/basic/dialog/adduserdialog.js","./components/basic/table/usertable.js","./pages/settings/org/[id].tsx","./pages/settings/personal/[id].tsx","./components/basic/dialog/addservicetokendialog.js","./pages/settings/project/[id].tsx","./components/basic/dialog/addprojectmemberdialog.js","./pages/users/[id].tsx","./node_modules/@types/ms/index.d.ts","./node_modules/@types/debug/index.d.ts","./node_modules/@types/unist/index.d.ts","./node_modules/@types/hast/index.d.ts","./node_modules/@types/json-schema/index.d.ts","./node_modules/@types/json5/index.d.ts","./node_modules/@types/mdast/index.d.ts","./node_modules/@types/mdurl/encode.d.ts","./node_modules/@types/mdurl/decode.d.ts","./node_modules/@types/mdurl/parse.d.ts","./node_modules/@types/mdurl/format.d.ts","./node_modules/@types/mdurl/index.d.ts","./node_modules/@types/parse-json/index.d.ts","./node_modules/@types/raf/index.d.ts","./node_modules/redux/index.d.ts","./node_modules/@types/react-redux/index.d.ts","./node_modules/@types/scheduler/index.d.ts","./node_modules/@types/semver/classes/semver.d.ts","./node_modules/@types/semver/functions/parse.d.ts","./node_modules/@types/semver/functions/valid.d.ts","./node_modules/@types/semver/functions/clean.d.ts","./node_modules/@types/semver/functions/inc.d.ts","./node_modules/@types/semver/functions/diff.d.ts","./node_modules/@types/semver/functions/major.d.ts","./node_modules/@types/semver/functions/minor.d.ts","./node_modules/@types/semver/functions/patch.d.ts","./node_modules/@types/semver/functions/prerelease.d.ts","./node_modules/@types/semver/functions/compare.d.ts","./node_modules/@types/semver/functions/rcompare.d.ts","./node_modules/@types/semver/functions/compare-loose.d.ts","./node_modules/@types/semver/functions/compare-build.d.ts","./node_modules/@types/semver/functions/sort.d.ts","./node_modules/@types/semver/functions/rsort.d.ts","./node_modules/@types/semver/functions/gt.d.ts","./node_modules/@types/semver/functions/lt.d.ts","./node_modules/@types/semver/functions/eq.d.ts","./node_modules/@types/semver/functions/neq.d.ts","./node_modules/@types/semver/functions/gte.d.ts","./node_modules/@types/semver/functions/lte.d.ts","./node_modules/@types/semver/functions/cmp.d.ts","./node_modules/@types/semver/functions/coerce.d.ts","./node_modules/@types/semver/classes/comparator.d.ts","./node_modules/@types/semver/classes/range.d.ts","./node_modules/@types/semver/functions/satisfies.d.ts","./node_modules/@types/semver/ranges/max-satisfying.d.ts","./node_modules/@types/semver/ranges/min-satisfying.d.ts","./node_modules/@types/semver/ranges/to-comparators.d.ts","./node_modules/@types/semver/ranges/min-version.d.ts","./node_modules/@types/semver/ranges/valid.d.ts","./node_modules/@types/semver/ranges/outside.d.ts","./node_modules/@types/semver/ranges/gtr.d.ts","./node_modules/@types/semver/ranges/ltr.d.ts","./node_modules/@types/semver/ranges/intersects.d.ts","./node_modules/@types/semver/ranges/simplify.d.ts","./node_modules/@types/semver/ranges/subset.d.ts","./node_modules/@types/semver/internals/identifiers.d.ts","./node_modules/@types/semver/index.d.ts","./node_modules/@types/use-sync-external-store/index.d.ts","./node_modules/@types/uuid/index.d.ts","./components/basic/table/checkbox.js"],"fileInfos":[{"version":"8730f4bf322026ff5229336391a18bcaa1f94d4f82416c8b2f3954e2ccaae2ba","affectsGlobalScope":true},"dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6","7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467","8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9","5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06","4b421cbfb3a38a27c279dec1e9112c3d1da296f77a1a85ddadf7e7a425d45d18","1fc5ab7a764205c68fa10d381b08417795fc73111d6dd16b5b1ed36badb743d9","746d62152361558ea6d6115cf0da4dd10ede041d14882ede3568bce5dc4b4f1f","d11a03592451da2d1065e09e61f4e2a9bf68f780f4f6623c18b57816a9679d17","aea179452def8a6152f98f63b191b84e7cbd69b0e248c91e61fb2e52328abe8c",{"version":"3aafcb693fe5b5c3bd277bd4c3a617b53db474fe498fc5df067c5603b1eebde7","affectsGlobalScope":true},{"version":"f3d4da15233e593eacb3965cde7960f3fddf5878528d882bcedd5cbaba0193c7","affectsGlobalScope":true},{"version":"adb996790133eb33b33aadb9c09f15c2c575e71fb57a62de8bf74dbf59ec7dfb","affectsGlobalScope":true},{"version":"8cc8c5a3bac513368b0157f3d8b31cfdcfe78b56d3724f30f80ed9715e404af8","affectsGlobalScope":true},{"version":"cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a","affectsGlobalScope":true},{"version":"c5c05907c02476e4bde6b7e76a79ffcd948aedd14b6a8f56e4674221b0417398","affectsGlobalScope":true},{"version":"5f406584aef28a331c36523df688ca3650288d14f39c5d2e555c95f0d2ff8f6f","affectsGlobalScope":true},{"version":"22f230e544b35349cfb3bd9110b6ef37b41c6d6c43c3314a31bd0d9652fcec72","affectsGlobalScope":true},{"version":"7ea0b55f6b315cf9ac2ad622b0a7813315bb6e97bf4bb3fbf8f8affbca7dc695","affectsGlobalScope":true},{"version":"3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93","affectsGlobalScope":true},{"version":"eb26de841c52236d8222f87e9e6a235332e0788af8c87a71e9e210314300410a","affectsGlobalScope":true},{"version":"3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006","affectsGlobalScope":true},{"version":"17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a","affectsGlobalScope":true},{"version":"7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98","affectsGlobalScope":true},{"version":"6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577","affectsGlobalScope":true},{"version":"81cac4cbc92c0c839c70f8ffb94eb61e2d32dc1c3cf6d95844ca099463cf37ea","affectsGlobalScope":true},{"version":"b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e","affectsGlobalScope":true},{"version":"0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a","affectsGlobalScope":true},{"version":"da233fc1c8a377ba9e0bed690a73c290d843c2c3d23a7bd7ec5cd3d7d73ba1e0","affectsGlobalScope":true},{"version":"d154ea5bb7f7f9001ed9153e876b2d5b8f5c2bb9ec02b3ae0d239ec769f1f2ae","affectsGlobalScope":true},{"version":"bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c","affectsGlobalScope":true},{"version":"c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8","affectsGlobalScope":true},{"version":"9d57b2b5d15838ed094aa9ff1299eecef40b190722eb619bac4616657a05f951","affectsGlobalScope":true},{"version":"6c51b5dd26a2c31dbf37f00cfc32b2aa6a92e19c995aefb5b97a3a64f1ac99de","affectsGlobalScope":true},{"version":"6e7997ef61de3132e4d4b2250e75343f487903ddf5370e7ce33cf1b9db9a63ed","affectsGlobalScope":true},{"version":"2ad234885a4240522efccd77de6c7d99eecf9b4de0914adb9a35c0c22433f993","affectsGlobalScope":true},{"version":"5e5e095c4470c8bab227dbbc61374878ecead104c74ab9960d3adcccfee23205","affectsGlobalScope":true},{"version":"09aa50414b80c023553090e2f53827f007a301bc34b0495bfb2c3c08ab9ad1eb","affectsGlobalScope":true},{"version":"d7f680a43f8cd12a6b6122c07c54ba40952b0c8aa140dcfcf32eb9e6cb028596","affectsGlobalScope":true},{"version":"3787b83e297de7c315d55d4a7c546ae28e5f6c0a361b7a1dcec1f1f50a54ef11","affectsGlobalScope":true},{"version":"e7e8e1d368290e9295ef18ca23f405cf40d5456fa9f20db6373a61ca45f75f40","affectsGlobalScope":true},{"version":"faf0221ae0465363c842ce6aa8a0cbda5d9296940a8e26c86e04cc4081eea21e","affectsGlobalScope":true},{"version":"06393d13ea207a1bfe08ec8d7be562549c5e2da8983f2ee074e00002629d1871","affectsGlobalScope":true},{"version":"2768ef564cfc0689a1b76106c421a2909bdff0acbe87da010785adab80efdd5c","affectsGlobalScope":true},{"version":"b248e32ca52e8f5571390a4142558ae4f203ae2f94d5bac38a3084d529ef4e58","affectsGlobalScope":true},{"version":"6c55633c733c8378db65ac3da7a767c3cf2cf3057f0565a9124a16a3a2019e87","affectsGlobalScope":true},{"version":"fb4416144c1bf0323ccbc9afb0ab289c07312214e8820ad17d709498c865a3fe","affectsGlobalScope":true},{"version":"5b0ca94ec819d68d33da516306c15297acec88efeb0ae9e2b39f71dbd9685ef7","affectsGlobalScope":true},{"version":"34c839eaaa6d78c8674ae2c37af2236dee6831b13db7b4ef4df3ec889a04d4f2","affectsGlobalScope":true},{"version":"34478567f8a80171f88f2f30808beb7da15eac0538ae91282dd33dce928d98ed","affectsGlobalScope":true},{"version":"ab7d58e6161a550ff92e5aff755dc37fe896245348332cd5f1e1203479fe0ed1","affectsGlobalScope":true},{"version":"6bda95ea27a59a276e46043b7065b55bd4b316c25e70e29b572958fa77565d43","affectsGlobalScope":true},{"version":"aedb8de1abb2ff1095c153854a6df7deae4a5709c37297f9d6e9948b6806fa66","affectsGlobalScope":true},{"version":"a4da0551fd39b90ca7ce5f68fb55d4dc0c1396d589b612e1902f68ee090aaada","affectsGlobalScope":true},{"version":"11ffe3c281f375fff9ffdde8bbec7669b4dd671905509079f866f2354a788064","affectsGlobalScope":true},{"version":"52d1bb7ab7a3306fd0375c8bff560feed26ed676a5b0457fa8027b563aecb9a4","affectsGlobalScope":true},"0990a7576222f248f0a3b888adcb7389f957928ce2afb1cd5128169086ff4d29",{"version":"bbdf156fea2fabed31a569445835aeedcc33643d404fcbaa54541f06c109df3f","affectsGlobalScope":true},"ba7617784f6b9aeac5e20c5eea869bbc3ef31b905f59c796b0fd401dae17c111","6a386ff939f180ae8ef064699d8b7b6e62bc2731a62d7fbf5e02589383838dea","f5a8b384f182b3851cec3596ccc96cb7464f8d3469f48c74bf2befb782a19de5",{"version":"ef8a481f9f2205fcc287eef2b4e461d2fc16bc8a0e49a844681f2f742d69747e","affectsGlobalScope":true},"cc69795d9954ee4ad57545b10c7bf1a7260d990231b1685c147ea71a6faa265c","54bd71c625e111b058159fc737c8f9a7170acfdb63cdb9a178558fb70e9fa9e9","1b61d259de5350f8b1e5db06290d31eaebebc6baafd5f79d314b5af9256d7153","57194e1f007f3f2cbef26fa299d4c6b21f4623a2eddc63dfeef79e38e187a36e","0f6666b58e9276ac3a38fdc80993d19208442d6027ab885580d93aec76b4ef00","05fd364b8ef02fb1e174fbac8b825bdb1e5a36a016997c8e421f5fab0a6da0a0","7e771891adaa85b690266bc37bd6eb43bc57eecc4b54693ead36467e7369952a","a69c09dbea52352f479d3e7ac949fde3d17b195abe90b045d619f747b38d6d1a",{"version":"ca72190df0eb9b09d4b600821c8c7b6c9747b75a1c700c4d57dc0bb72abc074c","affectsGlobalScope":true},"21a167fec8f933752fb8157f06d28fab6817af3ad9b0bdb1908a10762391eab9",{"version":"bb65c6267c5d6676be61acbf6604cf0a4555ac4b505df58ac15c831fcbff4e3e","affectsGlobalScope":true},"0c0cee62cb619aed81133b904f644515ba3064487002a7da83fd8aa07b1b4abd","5a94487653355b56018122d92392beb2e5f4a6c63ba5cef83bbe1c99775ef713",{"version":"d5135ad93b33adcce80b18f8065087934cdc1730d63db58562edcf017e1aad9b","affectsGlobalScope":true},"82408ed3e959ddc60d3e9904481b5a8dc16469928257af22a3f7d1a3bc7fd8c4","afcc1c426b76db7ec80e563d4fb0ba9e6bcc6e63c2d7e9342e649dc56d26347f","bb9c4ffa5e6290c6980b63c815cdd1625876dadb2efaf77edbe82984be93e55e","75ecef44f126e2ae018b4abbd85b6e8a2e2ba1638ebec56cc64274643ce3567b","f30bb836526d930a74593f7b0f5c1c46d10856415a8f69e5e2fc3db80371e362","14b5aa23c5d0ae1907bc696ac7b6915d88f7d85799cc0dc2dcf98fbce2c5a67c","5c439dafdc09abe4d6c260a96b822fa0ba5be7203c71a63ab1f1423cd9e838ea",{"version":"6b526a5ec4a401ca7c26cfe6a48e641d8f30af76673bad3b06a1b4504594a960","affectsGlobalScope":true},{"version":"816ad2e607a96de5bcac7d437f843f5afd8957f1fa5eefa6bba8e4ed7ca8fd84","affectsGlobalScope":true},"cec36af22f514322f870e81d30675c78df82ae8bf4863f5fd4e4424c040c678d","d903fafe96674bc0b2ac38a5be4a8fc07b14c2548d1cdb165a80ea24c44c0c54","b01a80007e448d035a16c74b5c95a5405b2e81b12fabcf18b75aa9eb9ef28990","04eb6578a588d6a46f50299b55f30e3a04ef27d0c5a46c57d8fcc211cd530faa","dbe5aa5a5dd8bd1c6a8d11b1310c3f0cdabaacc78a37b394a8c7b14faeb5fb84","2c828a5405191d006115ab34e191b8474bc6c86ffdc401d1a9864b1b6e088a58",{"version":"e8b18c6385ff784228a6f369694fcf1a6b475355ba89090a88de13587a9391d5","affectsGlobalScope":true},"d076fede3cb042e7b13fc29442aaa03a57806bc51e2b26a67a01fbc66a7c0c12","7c013aa892414a7fdcfd861ae524a668eaa3ede8c7c0acafaf611948122c8d93","b0973c3cbcdc59b37bf477731d468696ecaf442593ec51bab497a613a580fe30",{"version":"4989e92ba5b69b182d2caaea6295af52b7dc73a4f7a2e336a676722884e7139d","affectsGlobalScope":true},{"version":"b3624aed92dab6da8484280d3cb3e2f4130ec3f4ef3f8201c95144ae9e898bb6","affectsGlobalScope":true},"5153a2fd150e46ce57bb3f8db1318d33f6ad3261ed70ceeff92281c0608c74a3","210d54cd652ec0fec8c8916e4af59bb341065576ecda039842f9ffb2e908507c","36b03690b628eab08703d63f04eaa89c5df202e5f1edf3989f13ad389cd2c091","0effadd232a20498b11308058e334d3339cc5bf8c4c858393e38d9d4c0013dcf","25846d43937c672bab7e8195f3d881f93495df712ee901860effc109918938cc","fd93cee2621ff42dabe57b7be402783fd1aa69ece755bcba1e0290547ae60513","1b952304137851e45bc009785de89ada562d9376177c97e37702e39e60c2f1ff","69ee23dd0d215b09907ad30d23f88b7790c93329d1faf31d7835552a10cf7cbf","44b8b584a338b190a59f4f6929d072431950c7bd92ec2694821c11bce180c8a5","23b89798789dffbd437c0c423f5d02d11f9736aea73d6abf16db4f812ff36eda","213fc4f2b172d8beb74b77d7c1b41488d67348066d185e4263470cbb010cd6e8",{"version":"970a90f76d4d219ad60819d61f5994514087ba94c985647a3474a5a3d12714ed","affectsGlobalScope":true},"664d8f2d59164f2e08c543981453893bc7e003e4dfd29651ce09db13e9457980","4c8525f256873c7ba3135338c647eaf0ca7115a1a2805ae2d0056629461186ce","3c13ef48634e7b5012fcf7e8fce7496352c2d779a7201389ca96a2a81ee4314d","5d0a25ec910fa36595f85a67ac992d7a53dd4064a1ba6aea1c9f14ab73a023f2",{"version":"f0900cd5d00fe1263ff41201fb8073dbeb984397e4af3b8002a5c207a30bdc33","affectsGlobalScope":true},{"version":"f7db71191aa7aac5d6bc927ed6e7075c2763d22c7238227ec0c63c8cf5cb6a8b","affectsGlobalScope":true},"06d7c42d256f0ce6afe1b2b6cfbc97ab391f29dadb00dd0ae8e8f23f5bc916c3","ec4bd1b200670fb567920db572d6701ed42a9641d09c4ff6869768c8f81b404c","e59a892d87e72733e2a9ca21611b9beb52977be2696c7ba4b216cbbb9a48f5aa",{"version":"da26af7362f53d122283bc69fed862b9a9fe27e01bc6a69d1d682e0e5a4df3e6","affectsGlobalScope":true},"8a300fa9b698845a1f9c41ecbe2c5966634582a8e2020d51abcace9b55aa959e",{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true},"e9a8d4274033cb520ee12d6f68d161ba2b9128b87399645d3916b71187032836","30a1b56068b3820c91a055425a6af2294f8ef2bb10a59dcda413f6437093620d","db6d2d9daad8a6d83f281af12ce4355a20b9a3e71b82b9f57cddcca0a8964a96","54be1e9fa1341e79190896d0b79279b681714d79126b7e012777e328385cacb6","625e5d5e9e25017d53e65c62ff944d812d48ec1bbaaf7395c8f8cdf6c9218061","d9eb71e7c70837921557ecc76865043734dac2cd1bf1d3a7b24879de47befc89","39a3fc61a65aee8c90cd81bb2c9b508be6c5cc745cd40eaed95954a07c11bb82","254a9b57801e4f45ef7576236e5984e4abd95a03ea06b2018801ae3200e1617e","3150ee51540bdf0d4e0ccb05de6f905962dc3505bd28b7385c6924f7d9eeba11","2302818e3723d16f85c3d75de67247a1bacc23f5399b8235fde025737a6cc5b8","a13e414841a16a10e8637397f2551c52e1025278f4d8d2397824546dc272441b","98e00fba67d4b527de2929778f96c7f9453fbbb8c50968ff096dddd29057450b","b8d57d43415dc08b757f7bdfa382b596bf3627565dcb11bc325956f351abc813","481317b3d14426c2145b2a9a368f27278b20a76115bcc58ac5eb8649791e66b0","e5fe42c833993ca99b2e7628fd90bc3c0d30c9447a925d332ab90a53dff5743a","e264129e63c4e4c13586d8e166ee80c90a7da663b3d3e2a40f0fcaf89e267685","22082ac39501b626f8b4322d6bd6fb0424de438777b141f663286cf8bd048398","7efab7f15be1969d9e92bab327ec311d0bf7fc972f793cc8ca25ee95d7b720ad","bd53743631e1afc700defefceea03658ce7fa4a5a0a42622daed233b8c8d8473","16a510a8408f5a845b3e5dbe17a731b9e6dfdcd416410c36f8afcd8cf60c57a4","85cc7ba47f064d73b53d98e5384dad6e88809b8c0ecbf155846203d8736e99bb","be5dfb4c5c1bdfb0d853370c0de9a995cb39eef0f277d645a7f43caaea423d18","58902668adae2e5eb67efbccb4048afa02308fa684f1a4e4c7d47668ecf58c1b","2e14bcdfb0fd8cf0f6397a641018bb3d1409870af299707126302bd264cb3d42","11206290b4d52fa4a2ce697aef740ebb4514c58ac73a7c792e5b241b24d03c1b","837acd3f64bcd556da76827c292e82ad812170d880a490a7deb3f2de0ffa7c9a","2e94503b5076c161c7aac50b99bc5244ffc4cc3c4b699d079ce24b86208ebd18","17937316a2f7f362dd6375251a9ce9e4960cfdc0aa7ba6cbd00656f7ab92334b","2a878850cefd50fcb86b1164005cc48294edf62fc3bb100301378a448e3d2112","4e0528cf15ca199d8b363895c38e4f7b45ccd79d34f84861e8800cbd41eb2d37","8e64a4268cab5c9790d4895275ffbe654d75b877601ecb0ffadb66f95132b3bd","eaf9ff519bd303bff935b04d60d1269708fd2b5ce41b3d1d8ced373e2c02b76d","71cad090e94ca13ef78b9f4275159a76fb950ad33b47ea24f4874d1df5ad3dfa","6e5f5cee603d67ee1ba6120815497909b73399842254fc1e77a0d5cdc51d8c9c","f6404e7837b96da3ea4d38c4f1a3812c96c9dcdf264e93d5bdb199f983a3ef4b","37ac25883371c238e6c4575498d3517a25433382ed77f5181af60f9fa06eb2c4","1d5b8dfb36cd7234b297aeb66435f37ddb7579b1ef5e94a13e195d51b09c92cd","7a18dff83add08d87a614e3c28b07e919def3d72928dc846d557be176fc9e3a5","ecdfa1a2faf120fe24d456616945fee5c950b55ca60e3936592524b737a0623a","90e20fced750a875bb86a6b781a43593647f11bbb979511a4d7051d2d21f90db","7d03f9b34192444d1ae3d2dce4f88a126e51fb8e0cb0ce5a92019ff6212dc1ca","45f80f549a22887e9f85ad3c6a24a382d1e825c8e7fa72a2d1e7c53e0c4e623f","5cab8fa167ee711e4dfcd22ed632c60be36bd49dc6eea8cfdd3613c59d00c43d",{"version":"a5b7d9811cb310f8abaebedbd80023cea0c9b4011984ca0c58a52f25fee67495","affectsGlobalScope":true},"22671c0bd8afbe9238285b94a9f6bf447838f290ff054850145989d347099192","00357bb70a10782936bbfdf7c87ad632e5c2694b6714224ea0995299db1885ed","2766dee26ea113e9b491b7842cb44df57c4d79b17057b42607e09fc174bd411d","cb4047ce260c2f4585b2d592d04a1d9a9c2a1ba32679a688523ec314a977989a","0511c61c22d677da1b6bab4d3844aead1d7e27028d2f0ed1ed315e0860ed5357",{"version":"b4610d904ab939109aa8bcee6f795de8da780b6b4a4d8ff2ff9d2e3b699f55b7","affectsGlobalScope":true},{"version":"8b20e6ed022d1615533cacba5ff84521a86e86e98ef79318415235d64858a0e9","affectsGlobalScope":true},{"version":"37b859e0b3e9c67252710e6135a3e80daa5ccc5d9eaadd7728ede7ccde2d1263","affectsGlobalScope":true},"b7f9c8b05e3a56b80f6a8362b3f084ea887d3f857bc885a5f1dbc03150b981dd","1329c41c13694c2d89f4576fc3d0f04e07f311a682bf958bde5b79e6c76c0137","f77d46ee52fbe94069be9a6b7d7345144d9b64fceb68c4fd27578ba333b66b6a","65c24a8baa2cca1de069a0ba9fba82a173690f52d7e2d0f1f7542d59d5eb4db0","b7fff2d004c5879cae335db8f954eb1d61242d9f2d28515e67902032723caeab","8303df69e9d100e3df8f2d67ec77348cb6494dc406356fdd9b56e61aa7c3c758","8de50542d92f9ac659c30ead0a97e9c107dd3404a3b4fd4bf3504589a026221a","4545c1a1ceca170d5d83452dd7c4994644c35cf676a671412601689d9a62da35","7e3327a4bd457a8949d15cc317b76fc394732519b09facac6836a726b58f277e","a2d648d333cf67b9aeac5d81a1a379d563a8ffa91ddd61c6179f68de724260ff","c3a905a7fa93ca648349e934fb19356cf7b40e48d65658de3e0c77d67696fd40","a3f41ed1b4f2fc3049394b945a68ae4fdefd49fa1739c32f149d32c0545d67f5","c2489c80994d62e5b51370a6f02f537db4c37af5f914fcb5b2755b81f1906cae","47699512e6d8bebf7be488182427189f999affe3addc1c87c882d36b7f2d0b0e","38f19e920e7f0babb44119ed394e1916a16cf04b17b6724e07e1497cd5ea1445","42c686ce08bf5576ed178f4a6a62d1b580d941334fb53bdff7054e0980f2dc75","f5daecf7f124d12e92b3f640dabe6fe5f0444bb4d471fc2ee1811a5d8ba17981","cdf21eee8007e339b1b9945abf4a7b44930b1d695cc528459e68a3adc39a622e","1d079c37fa53e3c21ed3fa214a27507bda9991f2a41458705b19ed8c2b61173d","26a451bf3a5f87ebaaa7694c5b664c3d9cec296f3fa8b797b872aee0f302b3a0","5835a6e0d7cd2738e56b671af0e561e7c1b4fb77751383672f4b009f4e161d70","c0eeaaa67c85c3bb6c52b629ebbfd3b2292dc67e8c0ffda2fc6cd2f78dc471e6","195aae3bcd7fa56c83e3242a6b613be4e70bbebbeebcf366140200750a7bd05e","5b5399e88bf15a6fbf4ac3660ae8c3df467932531f6940a914987faad103072e",{"version":"7a87441a419deeff2165cf497fed7c3600c886cd41e92bce644320b9a01f5c5c","affectsGlobalScope":true},"9c00f78ac4e60d1c34d0fb415df6b2fea5f6eea200076dff4d782256a4c2802d","79d056984a8964d3917c7587067447d7565d9da696fcf6ecaa5e8437a214f04e","9269d492817e359123ac64c8205e5d05dab63d71a3a7a229e68b5d9a0e8150bf","c7ec2c9590a23b3e329bb16de5b99c3f3edd7cd0558048894f822fed47ff5581","8ce1e6f89ae9e5087406fd51d0725e52b832683077b21264c2c4cf27468718e2","d9de3d489c1c538ca404fe3cbca900872b22b31fee5d4b3c89154be94b5c4c0b","7b5910a342b94fb35f7a2843534d7d04ce44891a9891e9b4d4ab9ebb4f2fca34","618d78f17f9a1543ce41d9e9e35db01041ab89e3979f79dedb636db32ddbead4","0ded42136d0afb1afd6f7679fa0a6a513e226240c01ebdb5ce44e500b6eaeb37","6c1b6a8889ab09917e23f037fe239078735120c7cde01ddcb73c0581deb01f64","2502622e7cc17268c78291611323ee04870899b602f1d018810870d6a8341753","e860f7cb39655387a4ff584739308a031ea7091ab7366c8bad6bfe30df19d49a","4a9a415589638d1a6f3c5269eecec91e20f0554b391c5b182d85a313042383eb","edbd2a3174d152f2d0647436337abb8649baaa9bb1ca1dd6c7f17fc4b4d98ea0","531f475eaa495aabd17dfb8380ff3558f23cc5475b861e9dd2fba41c562fe16c","4a29b4634e1ba5edb19225bdbf6f24dc935df26629182112bb2449a4437b76db","7ffc7b4e7fe731d786caa126f20f451c0d86419486bf03faca2c91adebe89bfd","12550b681c2d6e569d852126ef6f4938d416b8e18cedb29c2d3708ffe47de17f","3683be39aecd7802ede7b863d63c0753ecf916b98d9a9e12c63ebeb1192a055f","5781c794623901fedd9e784af9a55a456f5993034d3771cdd64ca455a787de6d","a51abf7f447e4dd04058b8f13bed7cacf6ed8040d4a3875fcd920a1bab949c7e","29de8afa770d2b59ebcaa3f7c56d1f373e41b8c37f35b9db4bdc10f1e1a88bd0","8bb6c6ca0b01f2785835348374d18b9ead431277f728b4bb24ada0d61675b549","051710cbb4924bc139b8a3cd675a2ad7f3c407ca241e00c5919c285ae71eb31a","6e8f0e2107be3035648fd38fe306cc0752df0e129f4a795efcaaf1f1abed1443","63b53cd10c267a9ec74117e040f810c52389b259cfdc34fe507c49321d0449e7","e7700046b1c3373a89784edd6befae454435efd7db708d23a7a3e9caf9743381","571745adacc96d1aa371591a48d1eb3e666cc86266b7985ac9b07c304ad82193","c07217eafceff19d16cd8c9af30f34a5013e535c13f9271a835537a0736ab48f","3ef2416d2294bc7cc59a1d62fe4b6bbfb8f4224a30adf7bcb74e8aa185e6f64d","d77961f3be03afb5467e8d3b353bb340a77684f0a657384ae435c6d91e06736c","c079cbd90442e6c9f7ef308daf7649955166f45982428e5778733e8c88e417ff","2b0eb45a8e4fb5ecc74c0ceb320cc6c7b34abc0f45e53ab7278256d6cabdb950","460ee1ca9928a729c0241f496919cbe907896094ad88be61f5259dbb2dd8dbd0","bfcf14ed17d21ea3235d2c771ce806a9b1da7434aabcd1df9cb4157b287d7312","cc12824fb56ed61b9c5bf9f8600d83d9d7f9e21db1ccbda32426190139e460ff","c083da3e3d5900768d3bc8ceeb7949bdcd2d0cdee27e0f524bbf653dde95e84a","fbbf6a82a787f89e86e1f12a832e4d8487cf7765ac5472a7f03f35495e378fec","a5e77da482bdf0bfdf89787aaa109f99e8b4be7d09caa40ce54da5148abbccfd",{"version":"26ef9a3e012d296fe3089a8bd74f425a59317b36efd2bdd68d681de539c231cc","affectsGlobalScope":true},"4321a253772df67751278fbb89d6ef8248206e279b82c75cabd7f1a33f6ae156","413cd238f7fc468a84ce64b28296499e6c82d6ec3396dd4e491be9bd37642b3d","59669c0eb6543f5abb87d8d1aaf3c6acaf7e7f05aaaa93218a97924a79f5b7a7","c01e6bc9de9a0f0b4a6be035d26fe3a2e0f385f989d9ad772e52a3d06145af19","17d032c26bf402edc2a6d0207dc00a48474d420ac528de71939b0b98e5efd622",{"version":"17125d67321b610d98ff1d52737a346cadf99ba41bd2dbefc2bf509c8833e76e","affectsGlobalScope":true},"63aefc615e02a4042f842c82fb6e226b9f0fd834747335b6949587f43c01773a","4eeddfe398059e92e01f7cc64fca2fe31f470d1e698415a4429afaa60ce59368","ff88603bcfeb40511b03f2a37de5f1a41edc5fed903a176f1a21678abbdb7495","9fb9e7ee9d116bc85685fd02c651e430b8b8afb7394967d2da20b2e6ecc0e851","e46431d8ae39888549331e84ec742f7cdea9bdc29b5b2f007119e7a0ef403c46","857cfd569bb6d8578ea9cd6640280da237b21b8c9ba59fd4638623afd1ec4db4","221da36543b247b1448657a1759a62cf9baa981b15aa460c86f221faab8614e9","5edf2061c49c43a0d350503786e23cb7ee6932c6e3d2a5215acf034656e256fd","214d9997c977e99eb141bb68d8532058c9061097af390cf472b4bb8eff038d11","2d4888a53ae60c88515015ab40ce1d4e7cf871429f1676985eb6990c0f8edb2d","3645d40e01a9453a0a219b02d2b5d36d19057a53c2c92b3b0eadeb6569c3bc3e","9731a3f66847c66d87f38998817b2d711091f1fea7a935862b1f9d8cd6170ba2","3e23d133c0ce45310705043510bc26459b2e7ccba2daca64f1d6c8c90656c21c",{"version":"69507feba913bd2a0a04138d82170d7967b5b327b702424e5e60a8220028ce7a","signature":"abb4871090233e43e023bd881e857e552e7b636bd4082910cd2b87bf70153eda"},"4d4569fd4fe21bb713095cbc4532b6f4adf4b3d8013773df03659c124ef08017","b28da0101791d1cc54aabf797c0cfc99f044f5dd039442708b0439cadaad1d21",{"version":"63ab5f68abae596acd3821adfe5a5f54f093f726ba522bcaf70daa5c66ff7064","signature":"9e2bff617e1274e20f6ed49a77403a91af5b778523a0d483514cdc7ddb4628f1"},"0d3b10dc2e2658b3772406c0b80eef26d3463a61d99f64dcad5ca826fc873405","82e8f7bd68c2d69e9723a1c682e131cdbc3de36472f7cb054f9d1bf3b5590b71","caef5b191982cd88619282b10e1c52c3cde8c81d4eaf4650b4e62d73f77483d4","07fb5f0a7aff7d6ddfff3314324775d0a2ea6dc970fb9f4f5477478b60f5bf99","ed24327f50f01066afbebddbcc2713b253c7340c06db5dd2a83275aebdb9c4dc","f30790fb5684ec0852e01267b9d4ad0cb8d51171a30143e2b465a456ae8a87d8","a2fc195b20c7276aec831c74e53f3e577921b276fe6c1761085af24252b7caab","020e7d842030c4d8bd2d0e3b44b8aeda578acd938e3b2de09cc5d16eb6c5fdc8","ed1b0831d5ef141a09ce4244268533c39f09b69a1e2da190234ba37ebe760f44","ba79db379d966b3e73f85e5772932307fa2f88b80b4fe6bf849da25453c3f455","bfe1b52cf71aea9bf8815810cc5d9490fa9617313e3d3c2ee3809a28b80d0bb4","076a4e73e35f1a3d3beddd46262f5f7b85c5f44e8b895dc722f72246e5bf3e56","af35a13116850298e3eeba2a26cdc8d83e2fa9945ee2e9ba6e71630ca33e5628","cae42c23d4bfb8b2e82248026b90ff9e918df1930c40cc7b75aacc7a5856dc89","80cffec19bb56b72686f9fbc4e518c5df096f204ad2edf3350513461ed7709e4","09dbbeea6a62c551f144e860397fdbcedee122982a1f7970d96ce8f16d403f3c","a41c48b1eb34442f89623d36ba9cfed0989a539aa1c3840dc5cfd37542289e59","095eddebfae026d5ce5cff705b7d2078fab7213f959cf0958edcc0acea6efc20","28cc8b1d1e4eac79ee0147d4e2df06ba3e3a14a598bd5be567c4d2f93ff2f617","9c8d13b3dcd7e0c6cae278bbe5ab7566192da9a6bc5c219d2973f2e9a8f55855","715b5a442d36822135393ccd1686db7c08fbe81968e4ba292e6e8173abb31861","c55274a912a6c3b2f6bf7585ea9975aa50fc01e395cb2d3d0258aa23053612c6","b46ea79d948287ec30466aa8d806242a96b7fdc69ab2157fcccd8d7195ba1c51","919156aa05583bcf017e160ba0bd46a3777187b6838889e7c78719dcfd3b02dc","87a6ed59349a6372f2b2fce062b60e31b9f9de3591633b065aeefd4c4c5bf77e",{"version":"e5061c04d04582c948294dd449a1e76a104c13a1747152add9be2899d319e568","signature":"766f53f900ed023434b9bb82ede65c5afc4a53a6895ddf9c38a8002fa49ee0f7"},"370492184485c923482ec301dbc2bc2003b2129778de786477a2f1191a3a7e84","1e5c9c1b90a1e7cf5b58f711b553e09be23431f935a34ce1f04fa5618c4fb573","cf51a3fcabb581eb9f2db075a132e232551b9cda5ab21384eb104ec0d73a6591","e78357ee27b4afff5f923c0282252a7162338df5f3582bedd5dede04b976f326","92927871dcbc7ed7be8e86b014f7b357b6a932012ff84c12fb990e67358395b2","783063fb13d9efdc5de3c4d3ab7e9e66ee94ce179b5d005da6e3a996f86fb8bb","24a9f3b5eaeab4e1f3298b77ab8efff65cab649201181abc73590d6ed2281058","68be7e70cbf5663c1a1f14ca0d71b8699c57102073342d1fa9e486ffa951625d","144e70e6aabe6beb53a0cc30f9a8dd7d57ca6e131b3afb6072151bd58e40abfa","c86238424babc769e34eb446424c2a5fa874b77cc64dc64a496b58228f4bc136","87928cca75360486254dbbd81643daab3bad9f64e6ba2c3c015dd24e85bccca0","8c465eaa32d44c979922bbf1dfc9fdc942a7a677d3dfc9994274638841e37845","61eb3afb80a42cf8b7488a1a49130813625968e3d42a35d00bdf7fd94a0cac4d","68856b4064857598f1e524c4f7b02d13122cf6a4a081162ac80628464e6c8484","5ce85e18359f40fbe256c220bc00abf60671893a8badbd2658f097d5e61b7d36","a62a48e123b45ce27f6090510c33124d94e459677c127fdf176ce3bd561d2591","6d683195794f866a672cd6fd34eae49e1c5a5a2a5c05160e3e8253c6edc872d0","2d889187d1e979544aeea51392bdf9728504a646cd1eb04846bd9d446c15fbb6","ad7d10ab8b987ab3af340c40f620d1dd166fad1edc5032a5692bab5afb75d045","941294e09ca143b1c14fb0061ceaf2888d40f7a82e569b1cb22222b9695cfc0b","7d86310278827f3f6df7b50a8273fc436e09d996ecc6a6b44c5e171ee1ed33e9","c75614cf5e4e33ac47e6b6eda1e93ea0d6e08d57e7210cd29aa80f7a161c4efd","db7a4424e943110527dde43b887209be7a34c6850946ef08b6138abfad37b7ff","972dcfbfa150bfac41b93aa0c66f76791b1e2a1d79eef276aaa46cb18f799328","03402773ba1f8cfc91ade2a7a91ad8281758912c26369bc4f1f6a1c20a8fc74c","4528ce34e1736ed3dff81675eb4397a8304b46c7a8fd4da0d6c3be611fa5309e","aa7d347fcf1d3a8235899417323377e2ae0425fdcc717b8d2cb0bd4b778ab035","05e74bec4b219100447cb932b306243a802de3e0df662f6132770380eadc3b1d","4d563b442e04bea6bb6e8324f7ebef2370107b0635773e586ca4920c9509cec4","08a7e792ab99ebd1f8fbad774b6ab9f4e6e56e8ca88f86eedb10eb962de48a9c","414c184f32bb5d7be9ffc25d2e059b5344286808e74291f4d9c2f1544906c347","3ef379634e6dd0738fd900834a9fdf07e3fbadde053827f07f4544a79d2af719","005520fe7338391ecbb7b82bfcdb9786954c0d7a16817074a209ac4f04b002f5","41b7ae96e88e81b35e9eeb0e8a6a69475050fa546c41650281b455659f5dc387","29d9f13cb48c4a915535b4f51ad842a68f8c7c8e649bbec2006cef91b52cd0a1","db2745afea6c90ad27758bec2e70e7b1dea2cfe6dba69ecb9af422d4f2771ac6","581fba4fea195daf12a8dbd4614a1a1cbb7dda8d34dd588b93d24dcc7aaac69e","759191e5b523560538599a6941fce2329e0a742ea3cb8959185cd4bc3f641b7d","d5605a4ea242153c48263bc410ec3cca4b37cc5b74ac2a9be42e99424cce5f82","dbcfa8ccd8356be5d9d26e46b09b8f6193a9f31dbdd8156b289430283cd012f3","6562e22c1ae98c62e2a92fc0deaef6f0bccffa1033bf656e7ec32378ad9fe026","e02da657425b6ac8b02745259580ecf162b83b4914521cff283767c47cde938f","f834a2d4199b9559a0786f0757345e4088688a1a587090c97fcd867bb6595e84","345f874e51fba1e9f489dd64ab1764646e7f4888d44b55b1baffdb401d0aafa2","9691f1eb5a5e9b894d83113430a4954cc0eb7a63fc68f059449a2ba9f40af195","e36312a503d17ccd8811ee4bc575505677b0e203316485293364559d3f7a3c90","014fe0eb32be2d64539e6d65448aaba2b5d5c966c9252c5118992d55637a4d70","ab45982a0c9546d43c9e6669e0f83ccc1d44173f604773ed79eac50564b2224c","49198b20fcb18703d3e225195812bdb5e31f5f1ef6cb0e9b2d6d5909375bf622","09cb15f30cf026203a44307ac5fc6f7fe14bcd4107714f2d443bfb14862d9a20","85bee27fa0b1df0865dd1d228230111bbb4639523b7405c06715a166e49a1afc","8a640546ac205454050a6c02708e8d564d8b94696c09df6b654d41767e392d77","3ac0a9a82997601c45c5a2c890c4c2744b97dccb1070d7de2510bc29e3f19eee","c5c72753e90165c6662cd3fcc9b305674548a6e191a49913a450803c93d621fd","2d87da4dc361f9e919814af124357540e225e8721388acf56c285b27b2a2d895","f13848a1cd9bf6781e3c426a2ee5ecec495098e4e615b82083b9bc969ef8f739","5a9c45c7f3239981610674ca450b7603b256220bb4cbf77e2ea2152cefa59984","74caa38c54dac12b4fc167c631485a6ccc228ef883e1b82f74dfdf793ff7436f","d3e742564cbc4e60f8eebbbef8189495123a5f2de6f76b52f03a6bfc2592e848","f2f7daff865dafaf7627bac34ffddcc7c8acfb7728deee3d909f9a45d815d23c","007f8b715cf2758cc7922f436c476fabd28cf490891c3599da8390ae7cfbeed2","66d09d2f2fbaf81c1cfa64183b74231df88398f122c5720232a764aefc1657de","ba14aa84990270858407d696eb4a6aae0c1d5a65b60e448ee1bb192ad2724194","4171da09e87f20f7d54c8d866ca8c107d1cc024c61d321999b9b9f85f610495a","507373629c89b7f6c75984b256283bf2d3acd34daa0c20e2d5315d8881bc2149","b6b0b5b6a9a0c45600e381bb5297be305a8cc72a7550be03d3125c1402946c86","b891dbc8fe0d45fa6462bb91cf3f6bb0ff819295adfda1ecdbaf01e63625f33e","886d451c526823492b05db2682e0c97020f89f48467ec1e343a05d1e3a828ea2","6e088f0f3fe55a3f6fd4cdd5749d27cf5ad3223fc0968135d60a9782e701079b","b137477e6e40ca7086119ac4731d1ff354a303db0a3f58887a3d366b8eb7437b","a32ba437828e75ecca6237702c812b56d3381942d60fde35437491d9c7ca265a","7e120e11ccaa158d04bc90e5bd320734a445341d415315e412f55785caaf4d0e","59558346eb568cdcbc9c83598996f443b653827cc8a2834a527092fed6f46433","f7dd793c9a5a0cba18e93ff49717a94eac0fadc86125f3f31492c88527ff960f","83a4d9e5c13fd7057a1b14a587b7c69b090cdc90d241ba6af3c60395291617af","cc43577fb94d6e071e407487d70b3183d17198cd1ada047d7e9ab66b3721796c","b37cdc07362bb10b8df5dbca55a556a518f22ce9331faf01449d308561ff0237","da5dcb143b50d1430ace236021145a10fef7c9fe8be43ed6fb108bd7a47672e9","65c3124b4620eb263e2e8a8da9a5b33cc71c256e781d6ac907f2a492c36e2949","337869b02a014433d7ed1fca39934769fe23770a14c7aa2128383b487735d686","c260eb7b7f5bbaad0e39e5a149cbcff2b38e7b8f8376898959b4e0a1fdcfcfc5","b7d8117dd69e2c80ab0cc96210bf3dd7e0b48f0f1d67c12dff6ce5ee236fa065","230f8db09c47ac51086a0f4920774336fcf32403f4ef42fbb70c86e8c5da2093","dac9e17f05a9395d3db3965b5f0367ada26568bc0e4c4ca703ed6e9d1bf75771","126cac1915dcffd17eddcb28b3f9793d98abf03e32e550f54155e12e2686814c","c8eabd9d9271fc78030bd6a1c5ca4b68e4c398a92b5827f16f291929cdf611b9","184628074c60f4230e4de4c093271f8028ba3f3a1110f2676b441238b4bcd0d2","f0e4c68b5e1ee9c7cdb74b17e2483d11433ba99103cd479465d6a8d8fbdc0118","c92796c39abbc795c380e988c1c51783ba564cb35eb1febb26ed808314d00915","8a20e46d1156c77a0e8cc8aa2e751272bf08b7fc2535937a99beec4597aac4ff","8cc93db1faf3001d2961c9190052c59a4f7f1d07c3d4c2f1fd2c204909777480","c4c6268dd1567e4bbb4ed4e8d2c14305c0a48f55a728e1216c4108a436e5ce1c","89e88c6f78837d8b1951ff053ac64e0858e724de8f7af3f71c697052de365418","92fec96cc670b30c989b7b8e26e171cbf307437b2f7aa2120d9fc03769ed33d5","03bdea6a0307d4da69610b610371bdf1df906d5bb1d8c5fe5d1b4736968973f1","5756aa603323a5fd10232f9eea31c968e95969153926c1b444758cdcf07566ec",{"version":"d8f4d2f5570b44d106e299f165265ea296d52640c57b9bde50b0fb47be7666bb","signature":"85c440907608343c3e1a18a441134e9df40295acebdb6ce1372ea12a5e940ef9"},"6f094d94d2ed062ac1d29d71a50e2884adaa4ff4f07cfd4f3e652073a0e36905","5cae0df9b448b54d7b785a60c6949893929966e6ad96f848bc721a7c998ae00b","ede86dcecd9aec1146f19bdd95e03fc634d86a19ade0e6235a9d145ee535404b","06784a6f583aa809e1a0d8d744a498dfe6b09aafb4a7d7ad83d9259d6b758542",{"version":"4bbc52a7d8833b0466951cd0354beb0002e7d10e535cf9a9243a6f3071f0f243","signature":"b2b6e8849da43e3998a23c08c0aa4a43fccd3072c62ee14702fdd0fccb1c7da3"},{"version":"963696f72714910550820dedcb99c83960536790c67fcafc0037011e4c8fd347","signature":"c1f9bee19eec3de0c052f04756437cf4949421c2e99cf0dd1aa1547b16a4528b"},"44c6e1b9184d38e674f1af670a7bf04c97642a180fcba9b6b80cc5ec7e515ebd","f74cbe1d1009bc36650a447459c9ca8cfe6afa8831041470392afd02a6dd2b28","8e960cd17211d3f8eedf9facc1628f4d724194e3d6a6f999d44626466459d087","948f0af1a67252555e58a66072133660a086f66d18bc10a6bfd7f6d0e6d7c82a","23deb61c955b587c7ed30fcc18a2750ff91f4beb834ea7b7e182fcbaf30f4e8d","ca2f817e32cae7d04ce071fdc71fa009dbe58a5abe0d57a05dacaef7d83abc60","83909f07c32b3c064868f44e128824a13dd24ed06ed3756211464b063e39c05c","bace0322d7214ca1aa0aea9a6483ca05ad226d5a7e29d59b8f224752fbd2124e","d04ecb7410571cb0c21ffc0af1e4adacc36bef0da79f93c36bca36932f288e18","63819cd56213000ab4fa818365600be067856c214d7a561cbe6a3fd0e74bcc8f","b2f3fe2d2681d8ea382b669b259f229735072c60ecc80ed4770313ba53ad2cd0","6498d909da384a1958e194ec0caa74ff01beb7e1ec678bc638c6148a3c6670fd","9d5cca27f54e15612fb035a7a69e274776fc275b0a85cbf755ce029ff252b92c","84f9e687420b82fcb65055c903d7f2c12da5c84c9c26da9f246ac4cba479b877","3012f9c373899b0b47ac0879bf80c3a029f542d7e62aa4295b7d487c4951479a","afada1f16e8702086a0d217a0296332ee51dd1e2f0b0734ceeddee409fca3ffd","cd4a0aa49dafc9076d3a62e5c102d88f7c2588535aa0310e3fe9e1a8e516ae27","3dfcd0a3bfa70b53135db3cf2e4ddcb7eccc3e4418ce833ae24eecd06928328f","b26f93d773cf3aa4dc421c45323adccaead92598594a56f4a84d77910ee4f510","bc41a8e33caf4d193b0c49ec70d1e8db5ce3312eafe5447c6c1d5a2084fece12","7c33f11a56ba4e79efc4ddae85f8a4a888e216d2bf66c863f344d403437ffc74","2bb86e343b4109c784b11070735fa881af5c870a409a3b87b13800ca2afef421","fc9d4e784c9e7569911d8a6a01e1de90617942639c7c260beffdef1548b1ce06","37c1aeea4ec8df37bbe5d96bda46831acab3f70b2001ec9f51cb3146a101de89","5ac83af1a323158abc8627462fe987f7c67f957f88cdcf2237ae4dddc26677a8","df486e591f21d229d75df323fb9cf34f4b5cdbccee6a9b42227be738a13755d6","69ebf923204206eecef4310dc8bf28ab07feddaa3542066cdafbe67adf45f811","ae8189514ed306971ac9aa7d917487ee51dc3590aa5735f23c1d71811c373ea6","6de9d8858034d3197c1525e1c29c942cf7912f807d4d7f14dea247b7c05b59b0","394b4927dcc6eda44eb759f395da17b6e07f4daf272216b5cfc92eb32239f561","1adcc285d2d477ec6c51d0282d891fdf9d04a5fa8dfa479eab153ae17376f1b4","0ad294cdc42fb1f99cc94db8f77364ddc516643d9c69d4e66942f2cfd783213b","3956f34170e48abf902bc81055fb35a7e8b87109dbf3ca272d096d6d42cf7b84","f3acf8cff186f71a3a9b2da63f1378de6fe68a8578cb47d097776143cc84cd7d","1db170e5dad144b639ddf3d32710491c583f48c6e522580c8d5a8c249a611338","960923ce078ecfef6e5c34468cdba5c552b064c0db7cb0fdd3eafd1bb9d3d7e9","42f034630b3a866d4a88b37cf0f8357b36af2f7298b319d536b7413ba99f979b","33d1d46d7789bebdf9b78cd54f39022aad5d7d1d03a58bdad4fe98658acfef06","b3956ba310c0bcd45b1c77455a9754a35b49642be91bfbb412e04d378fad83a1","052854468e3d8142f440fa9a0da1d743abef903dff09597025d07703c25b601e","284147c679272283a4bea7ccaecbbab198bb1854e19269b2e59d4b5cedd5894a","325994b6f6c7598c73bbd0294bf1e3f1e229772669b3c8a08fe3170442f600b8","581656e45b2555b764e2880a39859e25ac6c0c9a74cff83dd22d3859b2231982","843563f951d16e850a0be806010f630a4a71f0a55810bb9aced67c6d7774bf2f","9af1c478e5403b39b922df9132d779bc6e1ef88cafec17fcecf26356d90ecbd6","a95a6135f2d195c93d930ba01049c33579328e55612477c0ae5652429d3974ad","24ead5861f4400218aeaafa477082022f244e3df46d18831411f3a47fc3ff515","65ce9342063fcf793e7baea7526a5a9a2f6ce05dea0cf4ae726d02eae2b98fa3","b932682e049f41e294a3429aca3b0adb4d2eed8047b4c22f91565e9353d6940c","5a1755f317ac2c0d708fbf7c1dbf076ba3a31f624c534b44275c9c43033fdc2e","75528e41fa0188a19564d06a805157606130e92bd71ccd90067b393f0ef5bd7a","9f3c1ecc6919f370f8b7fa07a74397fd103c7326f4c7f1e1d36069efd1b555ff","6e62805023c93b0419b840ab0432a09ded37de5b36284bba764fb66e6daae527","3dc15ab5846482d5a3cacc57bca38deb004faa7c50b8a3f01ff382a74f4e0a1d","ce873a8bdc6041abcf22511db1a467ba772ccec1486d218f6fc1dee0f87e78e8","6751e85e52e7824e8e1edce2273550936277ec00d0786b17cea33f5dd079db86","4f5d3b576fea6339a550106e90cd5f7c8bcdc1283570fea16d5deb97f5d02eb2","a3ec38abf8fadc8b975744458bf4ecc0d98e74cac72354f2a383dd9ff4dfcdb4","f96c10342f5295af957a366fd914438a0cb59b14c72aa105ac7af3ead6334358","316b000d08520787dd58e6301e7901e6ab21956c937c9294099877a7b3040175","6751dbfd6d2c27753ae718dc4702d11a9170001851c7b090e01cb6d51405e6af","58f4dac6f1d819120d2e963e689d0b562d185518c30cebb6ce03bbc2e5a647a2","73d50a45c94263390f2b8237a2a04535ce1946f3b23da5dcf31a2831fb88a2f1","d04b6886fd83078768eadf446844e1dbcc9ab66fa627dcd3e8b68bc551f74222","ce695d07896b074f156e38a59adcd90e670a9f930c9f565327d95024fc4f5673","633ce0eaf80d6646010d0a6c61ad7beca33d3880b101ebf0d385d0e09f83a401","c60c7b5c3ab55b925c45756176f113cfa88f6054a48ebc62b882fc4b51042efc","7b9b98f24d695e442d6e923e426c151b6d066df50e1ae336581f9439693baabe","37698160771404b4856505261dbaee188a1577a286319b63033adca0d42d8d0a","a4fa0b55111024a4968543e0405c6c07ff7cd43c147fd38a8f189ddc0e86727a","54a17447cfb05ebe4c5f9baa5f351b9fc9e66ffc0ea3072b9090eeac2dddcd36","597f2fa8ed8c3dbbbd5b909d4086db90e3a322660b206e375f6257f8f17cfd90","838aecb19e686afbc421ae4d2d05fcc9f19fd467dcd4f902b66e3c14821062b9","fd92b787853fd3bd32a479579bfa475798b594cd29723980efbcf377185abfa1","27975250d16d95779140c1c2231e2f7b9d7764f4bb716b19880c01eeea715452","ed946e3b3759ed29d628657ca0ed5b77fc363ca737f27ca2c6047d2fdf650f80","7924a0d94e3e25a76c2a3594ee79d51cd7c6192846af4e99e6e9e1e4de199516","3576074c52675857954fb074b636935b1a0b763bbde7706cc1d9e6ce62cd27a9","7cd037d87448bdd6a49b362e130d1e01b05abca8a5aa3a568892cf2d98861368","0d7cf097d54e469ac1d6e2558687a1e980ccc1b7adc5b06e2b6267902fc624e8","98d95450e28edce995361c95916bff95c072685ae365c57fa744a83e878a5732","c21b293f21509e4b4a59236a6e32ed1e66c9367ca10cca1e50b4d7492bb14ebe","18757edcba330c0274b3e63e8e3867c082c374d6a5da38c4f448bb8b99c5cee5","af9824889fdc4e378bc7211d64bc133a96b5b2bb1774f0597ccbba179a98a53f","60592f5ae1b739c9607a99895d4a3ad5c865b16903e4180e50b256e360a4a104","025c0a40f0eeae72a5d19de49ca03cec7d05f5ecf136cf2fda109cb419a67e24","1d8188b44ffe6e6ed185e64a198825aba8d6437386bb1d92f351ac91be0ed76f","01746f577cfb86855cf5bbbcd34e927208ffb306d98c6c7746f552a23f5b3e2a","4fea1e3a67e0c9194bd60e8e7a1b28d9bc11f8fa912d29dbc00e5a89d9a49962","86ef3a6c7970603bd7dc9f14ae6949450fc5ca26ac6f7a8a6eeeed0089b504df","11bb79d6b15799d61b4ab58b399c7636accc050d669a5a234637bfa3f69fb87d","3dff3ed99374fd9c87f1f9aa5f6ee1b3bbe1a04785384752d71376edd3ac8e36","8b9066450972839de9cee208c6048a4560b4762f1b8d0f9d75ff77839984d5b1","d11937d5fdadf6602bf368a3cd2f4dda3474d57747068d392c4fb8e9a40c7a86",{"version":"e81a4cfa7752961e08f501f877e9d9d4e679d5a709e8099ede562bcbd2f5a89b","signature":"bca5f58c31b238c4bc8fd0d13785002153cb6b6130069abc4b36e9abaad0951d"},"d99ea95bad25565d1d252308e7ec6815a948a6144ccdf63fcfb6b0280f43634f","3f2197bbd44332d8083f33ca5b4a3dc7ec5067cfd306f2760c82ecf52cb4063e","4eb45d036594fcda8981f866a4a639a80381cc54edd418bd772e4d82a44cf076","3b711d8e6d75d37110f377105a876f76b99d1af2aaae601e3b3542f06331a80c","e056301ca761170511b8ca7b1221f9e51e957576eb598881c838bbe6b73cd7d0","444afe177af0d05a7635c716002d0731c1c40df3ed5af10bd836673015db1c0e","55ecd0759f8f63d37be081b033caa1f893fbc9021b06e2533bb4efacbd16c757","3d744887998be6e881a529a645a94e857d45f4a0bbb9bb455421cfda2621e449","432c95c1d2ce612c2dad1850bbef775bc97c6792550bc3c340b6863abc4c97f9","18fd098eb2c40205d3e102334d0883fda4e0a2c955e00b3f94719a70cd251bde","6a9c5127096b35264eb7cd21b2417bfc1d42cceca9ba4ce2bb0c3410b7816042","78828b06c0d3b586954015e9ebde5480b009e166c71244763bda328ec0920f41","cddf5c26907c0b8378bc05543161c11637b830da9fadf59e02a11e675d11e180","3d2cd8f3047fff04a71e7037a6a4cb9f4accb28dbd8c0d83164d414811025af0","f3e604694b624fa3f83f6684185452992088f5efb2cf136b62474aa106d6f1b6","96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","2a2e2c6463bcf3c59f31bc9ab4b6ef963bbf7dffb049cd017e2c1834e3adca63","f313731860257325f13351575f381fef333d4dfe30daf5a2e72f894208feea08","951b37f7d86f6012f09e6b35f1de57c69d75f16908cb0adaa56b93675ea0b853","3816fc03ffd9cbd1a7a3362a264756a4a1d547caabea50ca68303046be40e376","0c417b4ec46b88fb62a43ec00204700b560d01eb5677c7faa8ecd34610f096a8","13d29cdeb64e8496424edf42749bbb47de5e42d201cf958911a4638cbcffbd3f","2b8264b2fefd7367e0f20e2c04eed5d3038831fe00f5efbc110ff0131aab899b","bd85e061719661505dc7c273cb72a4c7fba05fb4e24520e8caca9f9f074462c3",{"version":"fd624f7d7b264922476685870f08c5e1c6d6a0f05dee2429a9747b41f6b699d4","affectsGlobalScope":true},"1781e7a2a01c07c7295d3ce885d5d2905bec6449725937e3b8776c9b5ab4bf5b","74b0245c42990ed8a849df955db3f4362c81b13f799ebc981b7bec2d5b414a57","2b93035328f7778d200252681c1d86285d501ed424825a18f81e4c3028aa51d9","2ac9c8332c5f8510b8bdd571f8271e0f39b0577714d5e95c1e79a12b2616f069","42c21aa963e7b86fa00801d96e88b36803188018d5ad91db2a9101bccd40b3ff","d31eb848cdebb4c55b4893b335a7c0cca95ad66dee13cbb7d0893810c0a9c301","77c1d91a129ba60b8c405f9f539e42df834afb174fe0785f89d92a2c7c16b77a","7a9e0a564fee396cacf706523b5aeed96e04c6b871a8bebefad78499fbffc5bc","906c751ef5822ec0dadcea2f0e9db64a33fb4ee926cc9f7efa38afe5d5371b2a","5387c049e9702f2d2d7ece1a74836a14b47fbebe9bbeb19f94c580a37c855351","c68391fb9efad5d99ff332c65b1606248c4e4a9f1dd9a087204242b56c7126d6","e9cf02252d3a0ced987d24845dcb1f11c1be5541f17e5daa44c6de2d18138d0c","e8b02b879754d85f48489294f99147aeccc352c760d95a6fe2b6e49cd400b2fe","9f6908ab3d8a86c68b86e38578afc7095114e66b2fc36a2a96e9252aac3998e0","0eedb2344442b143ddcd788f87096961cd8572b64f10b4afc3356aa0460171c6","71405cc70f183d029cc5018375f6c35117ffdaf11846c35ebf85ee3956b1b2a6","c68baff4d8ba346130e9753cefe2e487a16731bf17e05fdacc81e8c9a26aae9d","2cd15528d8bb5d0453aa339b4b52e0696e8b07e790c153831c642c3dea5ac8af","479d622e66283ffa9883fbc33e441f7fc928b2277ff30aacbec7b7761b4e9579","ade307876dc5ca267ca308d09e737b611505e015c535863f22420a11fffc1c54","f8cdefa3e0dee639eccbe9794b46f90291e5fd3989fcba60d2f08fde56179fb9","86c5a62f99aac7053976e317dbe9acb2eaf903aaf3d2e5bb1cafe5c2df7b37a8","2b300954ce01a8343866f737656e13243e86e5baef51bd0631b21dcef1f6e954","a2d409a9ffd872d6b9d78ead00baa116bbc73cfa959fce9a2f29d3227876b2a1","b288936f560cd71f4a6002953290de9ff8dfbfbf37f5a9391be5c83322324898","61178a781ef82e0ff54f9430397e71e8f365fc1e3725e0e5346f2de7b0d50dfa","6a6ccb37feb3aad32d9be026a3337db195979cd5727a616fc0f557e974101a54","c649ea79205c029a02272ef55b7ab14ada0903db26144d2205021f24727ac7a3","38e2b02897c6357bbcff729ef84c736727b45cc152abe95a7567caccdfad2a1d","d6610ea7e0b1a7686dba062a1e5544dd7d34140f4545305b7c6afaebfb348341","3dee35db743bdba2c8d19aece7ac049bde6fa587e195d86547c882784e6ba34c","b15e55c5fa977c2f25ca0b1db52cfa2d1fd4bf0baf90a8b90d4a7678ca462ff1","f41d30972724714763a2698ae949fbc463afb203b5fa7c4ad7e4de0871129a17","843dd7b6a7c6269fd43827303f5cbe65c1fecabc30b4670a50d5a15d57daeeb9","f06d8b8567ee9fd799bf7f806efe93b67683ef24f4dea5b23ef12edff4434d9d","6017384f697ff38bc3ef6a546df5b230c3c31329db84cbfe686c83bec011e2b2","e1a5b30d9248549ca0c0bb1d653bafae20c64c4aa5928cc4cd3017b55c2177b0","a593632d5878f17295bd53e1c77f27bf4c15212822f764a2bfc1702f4b413fa0","a868a534ba1c2ca9060b8a13b0ffbbbf78b4be7b0ff80d8c75b02773f7192c29","da7545aba8f54a50fde23e2ede00158dc8112560d934cee58098dfb03aae9b9d","34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","6aee496bf0ecfbf6731aa8cca32f4b6e92cdc0a444911a7d88410408a45ecc5d","61f41da9aaa809e5142b1d849d4e70f3e09913a5cb32c629bf6e61ef27967ff7","fab58e600970e66547644a44bc9918e3223aa2cbd9e8763cec004b2cfb48827e"],"options":{"esModuleInterop":true,"jsx":1,"module":99,"noImplicitAny":true,"skipLibCheck":true,"strict":true,"target":99},"fileIdsList":[[115,244,245],[62,115,189,365,366],[62,115,275,382,388],[62,115,275,341,382,384,388],[62,115,192,275,382,388,391],[62,78,115,258,259,275,347,364,366,382,384,388,391,475],[62,115,382,384,388],[62,115,192,245,382,384,388],[62,115,189,382,384,388,389],[62,115,382,384],[62,115,271,382],[115,364,366],[62,115,275,364,366,382],[62,115,267,364,366],[62,115,191,192,254,255,256,257,258,275,279,281,283,351,353,360,364,366,387,388,390,391],[62,115,364,366,382],[115],[115,305,364,388,394,395],[115,267,348,364,388,401],[62,115,192,257,258,259,267,344,352,354,364,388,391,475,476],[115,382],[62,115,283,340],[62,115,364,366,401],[62,115,400],[115,399,401],[115,275],[62,115,271,388,396],[62,115,249,275,292,293,364,382,388],[62,115,189,266,267,275,364,366,367,388,440],[62,115,249,364,366,405],[62,115,189,275,364,366,388,393,404,405,406,442,444],[115,189,192,329,364,366],[115,275,446],[115,189],[115,275,448],[62,115,192,291,328,330,336,364,366,388,391],[115,267,450],[62,115,189,192,254,256,267,275,312,337,364,366,382,385,386],[62,115,192,337,357,364,366],[62,115,192,202,307],[62,115,275,314,367,388,453],[115,275,289,364,366,388],[62,115,191,275,314,384,388],[62,115,192,275,342,360,388],[62,115,192,250,263,275,282,309,364,366,384,388],[115,248,249,250,251,252,253,254,255,256,257,258,260,261,262],[115,279,280],[78,115],[115,250,284,285,286],[115,250],[115,250,265,286,288],[115,264],[115,249],[115,249,290,291],[115,249,259],[115,259,294],[115,247],[115,244,245,246],[115,199,277],[115,248],[62,115,189,192,259,275,296,303,364,366,405],[62,115,189,267,275,304,364,366],[62,115,189,192,258,259,275,298,300,304,364,366,388],[62,115,189,192,258,259,275,301,364,366],[115,305],[62,115],[115,199,200],[115,363],[62,115,365],[62,115,368,369],[62,115,368],[115,370,371,372,373,374,375,376,377,378,379,380,381],[115,204],[115,204,206,207,208,221,228,229,231,234,235],[115,206],[115,207,208,220,221,223,226,229],[115,203,204,205,209,210,214,215,216,217,218,220,223,226,227,228],[115,229],[115,211,213],[115,204,205,215,218,220,221,226,228,229,231,236],[115,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242],[115,219,230],[115,217],[115,205,213,226,228,229,231,232,234],[115,203,204,205,209,215,218,219,220,221,226,227],[115,222],[115,223],[115,220],[115,218,226],[115,212],[115,213],[115,216,218,224,225,227],[115,206,207,224,233],[115,496],[115,498],[115,507],[115,503,504,505,506],[69,115],[72,115],[73,78,106,115],[74,85,86,93,103,114,115],[74,75,85,93,115],[76,115],[77,78,86,94,115],[78,103,111,115],[79,81,85,93,115],[80,115],[81,82,115],[85,115],[83,85,115],[85,86,87,103,114,115],[85,86,87,100,103,106,115],[115,119],[88,93,103,114,115],[85,86,88,89,93,103,111,114,115],[88,90,103,111,114,115],[69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121],[85,91,115],[92,114,115],[81,85,93,103,115],[94,115],[95,115],[72,96,115],[97,113,115,119],[98,115],[99,115],[85,100,101,115],[100,102,115,117],[73,85,103,104,105,106,115],[73,103,105,115],[103,104,115],[106,115],[107,115],[85,109,110,115],[109,110,115],[78,93,103,111,115],[112,115],[93,113,115],[73,88,99,114,115],[103,115,116],[115,117],[115,118],[73,78,85,87,96,103,114,115,117,119],[103,115,120],[62,115,272,510],[58,59,60,61,115],[115,513,552],[115,513,537,552],[115,552],[115,513],[115,513,538,552],[115,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551],[115,538,552],[62,115,177,268,271,272,275],[115,271,273],[115,268,271,274],[115,276],[67,115],[115,176],[115,178],[115,126,129,165],[115,131],[115,124,137],[115,124,137,138],[115,124],[62,114,115,122],[62,115,137,171],[62,115,137],[115,169,173],[62,115,170,175],[115,125],[62,115,166,175],[62,115,175],[88,115,122,130,175],[88,115,122,129,131],[88,103,115,122,130,131,135],[88,99,114,115,122,125,126,127,129,130,131,133,135,136,137,140,147,148,150,152,153,154,156,158,165],[88,103,115,122],[115,124,126,127,128,165],[115,129],[99,114,115,122,126,129,130,131,133,136,146,151,153,155,159,161,162],[88,114,115,122,129,135,158],[115,123,165,175],[88,99,114,115,122,126,129,130,133,135,136,139,140,146,147,148,150,151,152,154,155,158,159,160,175],[88,115,122,135,161,163],[88,115,122],[62,88,99,115,122,125,127,131,135,140,152,153,165],[88,99,114,115,122,130,134],[115,157],[115,122,140],[99,115,122,125,126,130,133,135],[88,115,122,140,149],[88,115,122,130,150],[115,146],[115,143],[115,129,141,142,146],[115,129,141,142],[115,129,134,143,144,145],[62,115,123,152,165,175],[62,99,114,115,122,125,168,170,172,175],[115,130,133,137],[99,115,122],[115,132],[62,88,99,115,122,125,165,166,167,173,174],[57,62,63,64,65,115,165,271],[115,180],[115,182],[115,184],[115,186],[115,188],[66,68,115,165,177,179,181,183,185,187,189,191,192,194,197,198],[115,190],[115,170],[115,193],[115,143,144,145,146,195,196],[115,122],[62,66,88,99,115,122,125,131,164,175,271],[115,243],[62,66,115,165,268,269,270,271],[115,268,271],[62,115,268,271],[115,409,423,425,429,431,432],[115,417,418,425,431],[115,431],[115,409,413,415,416,418,421,423,425,430,432],[115,408],[115,408,409,413,415,416,417,418,421,422,423,425,429,430,431,433,434,435,436,437,438,439],[115,412,415,421],[115,412,413,415,416,424,425,429,431],[115,418,425],[115,413,415,416,421,424,429,430,431],[115,412,413,415,416,418,419,420,424,425,429,430],[115,412,425,429],[115,424,425,431],[115,412,413,414,418,421,424,425,429],[115,408,410,411,413,417,418,421,422,425,432],[115,409,413,425,429],[115,429],[115,426,427,428],[115,410,423,425,431,433],[115,417,421,423,425],[115,417,423],[115,413,415,416,418,419,423,424,425],[115,412,416,417,440],[115,412,413,415,417,418,421,424],[115,423,430,431],[115,413,415,416,421,425,430,431],[115,187,189,191],[62,115,192,275,278,297,383,388,452,459,460],[62,115,192,360],[62,115,187,189,192,253,256,260,267,275,278,280,295,299,302,324,325,350,360,364,366,388,391,397,401,407,441,443,445,452,461],[62,115,187],[62,115,192,333,465],[62,115,191,192,275,278,281,350,364,365,366,385],[62,115,192],[62,78,115,187,192,258,259,275,278,319,320,331,334,335,356,447,449,451,452,483,484],[62,115,187,189,191,192,263,275,278,360,364,366,367,384,388,391],[115,189,278],[62,115,189,192,250,278,282,284,311,316,318,364,366,384,388,465],[115,187,189],[62,115,187,245,275,278,279,339,403,452],[62,115,187,192,256,267,275,278,279,337,339,342,343,345,346,355,360,364,366,384,388,452,487,488,489],[62,115,187,192,256,275,278,282,287,289,364,366,384,388,391,452],[62,115,187,192,275,278,321,322,323,349,355,360,361,364,366,384,388,398,402,452,492],[62,115,187,189,191,192,275,278,308,360,454,455,456,457,458],[62,115,187,189,191,192,250,263,282,284,289,310,315,364,366,384,388,465,475,476],[62,115,187,189,192,256,257,267,275,278,279,351,359,364,366,388,452,489,494],[62,115,187,189,191,278,313,384,388],[62],[244],[99,199]],"referencedMap":[[246,1],[388,2],[483,3],[487,4],[494,5],[492,6],[394,7],[488,8],[390,9],[395,10],[396,11],[367,12],[383,13],[384,14],[392,15],[391,16],[397,12],[389,17],[398,18],[402,19],[489,20],[393,21],[403,22],[399,23],[401,24],[400,25],[404,26],[405,14],[406,27],[407,28],[441,29],[442,13],[443,30],[445,31],[446,32],[447,33],[448,34],[449,35],[450,36],[451,37],[387,38],[452,39],[362,40],[454,41],[455,42],[456,43],[457,44],[458,45],[263,46],[281,47],[282,17],[283,17],[245,17],[250,48],[287,49],[258,50],[289,51],[265,52],[266,17],[267,17],[262,17],[290,53],[292,54],[293,53],[260,55],[295,56],[248,57],[261,58],[278,59],[202,17],[296,60],[297,60],[298,60],[299,60],[300,60],[301,60],[302,60],[459,61],[460,62],[461,63],[444,64],[303,17],[304,17],[306,65],[305,66],[201,67],[363,17],[365,68],[385,68],[386,68],[364,68],[366,69],[370,70],[371,70],[372,70],[373,71],[374,70],[375,70],[376,70],[377,71],[378,71],[379,71],[380,70],[381,70],[382,72],[368,66],[369,71],[167,17],[203,17],[205,73],[236,74],[207,75],[209,17],[206,17],[210,17],[208,17],[224,76],[237,17],[229,77],[219,78],[214,79],[215,17],[238,17],[230,80],[243,81],[231,82],[216,17],[211,17],[218,83],[235,84],[222,17],[225,17],[217,17],[239,17],[228,85],[223,86],[232,87],[221,88],[204,17],[227,89],[212,17],[213,90],[233,17],[241,91],[240,17],[226,92],[234,93],[220,17],[242,17],[497,94],[499,95],[272,66],[500,17],[501,17],[284,17],[502,95],[504,17],[503,17],[506,96],[507,97],[505,96],[496,17],[69,98],[70,98],[72,99],[73,100],[74,101],[75,102],[76,103],[77,104],[78,105],[79,106],[80,107],[81,108],[82,108],[84,109],[83,110],[85,109],[86,111],[87,112],[71,113],[121,17],[88,114],[89,115],[90,116],[122,117],[91,118],[92,119],[93,120],[94,121],[95,122],[96,123],[97,124],[98,125],[99,126],[100,127],[101,127],[102,128],[103,129],[105,130],[104,131],[106,132],[107,133],[108,17],[109,134],[110,135],[111,136],[112,137],[113,138],[114,139],[115,48],[116,140],[117,141],[118,142],[119,143],[120,144],[508,17],[60,17],[509,17],[511,145],[58,17],[62,146],[512,17],[61,17],[537,147],[538,148],[513,149],[516,149],[535,147],[536,147],[526,147],[525,150],[523,147],[518,147],[531,147],[529,147],[533,147],[517,147],[530,147],[534,147],[519,147],[520,147],[532,147],[514,147],[521,147],[522,147],[524,147],[528,147],[539,151],[527,147],[515,147],[552,152],[551,17],[546,151],[548,153],[547,151],[540,151],[541,151],[543,151],[545,151],[549,153],[550,153],[542,153],[544,153],[498,17],[553,17],[554,17],[59,17],[268,17],[264,17],[273,154],[274,155],[276,26],[275,156],[277,157],[68,158],[177,159],[179,160],[137,161],[147,162],[138,163],[139,164],[148,165],[128,165],[188,66],[190,166],[172,167],[171,168],[170,169],[193,66],[169,170],[196,17],[124,17],[126,171],[176,170],[180,172],[184,173],[131,174],[130,175],[151,176],[159,177],[134,178],[129,179],[125,180],[163,181],[162,180],[152,17],[123,17],[160,182],[153,183],[161,184],[164,185],[140,186],[154,187],[135,188],[158,189],[157,190],[136,191],[150,192],[149,193],[141,180],[142,194],[144,195],[143,196],[145,197],[195,17],[146,198],[67,17],[174,17],[182,66],[186,66],[166,199],[127,17],[168,17],[173,200],[156,201],[155,202],[133,203],[132,17],[178,17],[175,204],[57,17],[66,205],[63,66],[64,17],[65,17],[181,206],[183,207],[185,208],[187,209],[200,210],[189,210],[199,211],[191,212],[192,213],[194,214],[197,215],[198,216],[165,217],[244,218],[465,17],[453,66],[271,219],[270,220],[269,221],[510,17],[476,17],[475,17],[11,17],[12,17],[14,17],[13,17],[2,17],[15,17],[16,17],[17,17],[18,17],[19,17],[20,17],[21,17],[22,17],[3,17],[4,17],[26,17],[23,17],[24,17],[25,17],[27,17],[28,17],[29,17],[5,17],[30,17],[31,17],[32,17],[33,17],[6,17],[37,17],[34,17],[35,17],[36,17],[38,17],[7,17],[39,17],[44,17],[45,17],[40,17],[41,17],[42,17],[43,17],[8,17],[49,17],[46,17],[47,17],[48,17],[50,17],[9,17],[51,17],[52,17],[53,17],[54,17],[55,17],[1,17],[10,17],[56,17],[433,222],[410,17],[419,223],[432,224],[431,225],[409,226],[440,227],[411,17],[420,228],[430,229],[414,230],[425,231],[421,232],[413,233],[412,234],[415,235],[416,235],[423,236],[426,237],[427,238],[428,238],[429,239],[434,17],[408,17],[435,238],[436,240],[418,241],[422,242],[417,243],[437,244],[438,245],[424,246],[439,247],[462,248],[480,249],[285,60],[307,60],[308,17],[309,17],[310,17],[311,17],[316,17],[288,60],[251,17],[252,17],[312,60],[317,17],[318,17],[313,17],[314,17],[286,60],[247,17],[315,17],[319,60],[320,60],[321,60],[322,60],[323,60],[253,60],[324,60],[294,60],[325,60],[326,60],[333,60],[327,60],[328,60],[329,60],[330,60],[331,60],[334,60],[335,60],[332,60],[336,60],[341,60],[342,60],[343,60],[344,60],[345,60],[337,60],[338,60],[254,60],[339,60],[255,60],[279,60],[346,60],[340,60],[347,60],[348,60],[349,60],[256,60],[280,60],[350,60],[351,60],[352,60],[353,60],[354,60],[355,60],[356,60],[259,60],[357,60],[358,60],[360,60],[359,60],[361,60],[257,60],[463,250],[481,251],[464,252],[466,253],[467,253],[482,254],[468,255],[485,256],[469,257],[470,253],[471,258],[472,259],[473,260],[486,261],[490,262],[491,263],[493,264],[474,265],[477,266],[495,267],[478,253],[479,268],[291,17],[249,17],[484,17]],"exportedModulesMap":[[246,1],[388,2],[483,3],[487,4],[494,5],[492,6],[394,7],[488,8],[395,10],[396,11],[367,12],[383,13],[384,269],[392,15],[391,16],[397,12],[398,18],[402,19],[489,20],[393,21],[403,22],[399,23],[401,24],[400,25],[404,26],[405,14],[406,27],[407,28],[441,29],[442,13],[443,30],[445,31],[446,32],[447,33],[448,34],[449,35],[450,36],[451,37],[387,38],[452,39],[362,40],[454,41],[455,42],[456,43],[457,44],[458,45],[263,46],[281,47],[282,17],[283,17],[245,17],[250,48],[289,51],[265,52],[266,17],[267,17],[262,17],[290,53],[292,54],[293,53],[260,55],[295,56],[248,57],[261,270],[278,59],[202,17],[296,60],[297,60],[298,60],[299,60],[300,60],[301,60],[302,60],[459,61],[460,62],[461,63],[444,64],[303,17],[304,17],[306,65],[305,66],[201,67],[363,17],[365,68],[385,68],[386,68],[364,68],[366,69],[370,70],[371,70],[372,70],[373,71],[374,70],[375,70],[376,70],[377,71],[378,71],[379,71],[380,70],[381,70],[382,72],[368,66],[369,71],[167,17],[203,17],[205,73],[236,74],[207,75],[209,17],[206,17],[210,17],[208,17],[224,76],[237,17],[229,77],[219,78],[214,79],[215,17],[238,17],[230,80],[243,81],[231,82],[216,17],[211,17],[218,83],[235,84],[222,17],[225,17],[217,17],[239,17],[228,85],[223,86],[232,87],[221,88],[204,17],[227,89],[212,17],[213,90],[233,17],[241,91],[240,17],[226,92],[234,93],[220,17],[242,17],[497,94],[499,95],[272,66],[500,17],[501,17],[284,17],[502,95],[504,17],[503,17],[506,96],[507,97],[505,96],[496,17],[69,98],[70,98],[72,99],[73,100],[74,101],[75,102],[76,103],[77,104],[78,105],[79,106],[80,107],[81,108],[82,108],[84,109],[83,110],[85,109],[86,111],[87,112],[71,113],[121,17],[88,114],[89,115],[90,116],[122,117],[91,118],[92,119],[93,120],[94,121],[95,122],[96,123],[97,124],[98,125],[99,126],[100,127],[101,127],[102,128],[103,129],[105,130],[104,131],[106,132],[107,133],[108,17],[109,134],[110,135],[111,136],[112,137],[113,138],[114,139],[115,48],[116,140],[117,141],[118,142],[119,143],[120,144],[508,17],[60,17],[509,17],[511,145],[58,17],[62,146],[512,17],[61,17],[537,147],[538,148],[513,149],[516,149],[535,147],[536,147],[526,147],[525,150],[523,147],[518,147],[531,147],[529,147],[533,147],[517,147],[530,147],[534,147],[519,147],[520,147],[532,147],[514,147],[521,147],[522,147],[524,147],[528,147],[539,151],[527,147],[515,147],[552,152],[551,17],[546,151],[548,153],[547,151],[540,151],[541,151],[543,151],[545,151],[549,153],[550,153],[542,153],[544,153],[498,17],[553,17],[554,17],[59,17],[268,17],[264,17],[273,154],[274,155],[276,26],[275,156],[277,157],[68,158],[177,159],[179,160],[137,161],[147,162],[138,163],[139,164],[148,165],[128,165],[188,66],[190,166],[172,167],[171,168],[170,169],[193,66],[169,170],[196,17],[124,17],[126,171],[176,170],[180,172],[184,173],[131,174],[130,175],[151,176],[159,177],[134,178],[129,179],[125,180],[163,181],[162,180],[152,17],[123,17],[160,182],[153,183],[161,184],[164,185],[140,186],[154,187],[135,188],[158,189],[157,190],[136,191],[150,192],[149,193],[141,180],[142,194],[144,195],[143,196],[145,197],[195,17],[146,198],[67,17],[174,17],[182,66],[186,66],[166,199],[127,17],[168,17],[173,200],[156,201],[155,202],[133,203],[132,17],[178,17],[175,204],[57,17],[66,205],[63,66],[64,17],[65,17],[181,206],[183,207],[185,208],[187,209],[200,210],[189,210],[199,211],[191,212],[192,213],[194,214],[197,215],[198,216],[165,217],[244,218],[465,17],[453,66],[271,219],[270,220],[269,221],[510,17],[476,17],[475,17],[11,17],[12,17],[14,17],[13,17],[2,17],[15,17],[16,17],[17,17],[18,17],[19,17],[20,17],[21,17],[22,17],[3,17],[4,17],[26,17],[23,17],[24,17],[25,17],[27,17],[28,17],[29,17],[5,17],[30,17],[31,17],[32,17],[33,17],[6,17],[37,17],[34,17],[35,17],[36,17],[38,17],[7,17],[39,17],[44,17],[45,17],[40,17],[41,17],[42,17],[43,17],[8,17],[49,17],[46,17],[47,17],[48,17],[50,17],[9,17],[51,17],[52,17],[53,17],[54,17],[55,17],[1,17],[10,17],[56,17],[433,222],[410,17],[419,223],[432,224],[431,225],[409,226],[440,227],[411,17],[420,228],[430,229],[414,230],[425,231],[421,232],[413,233],[412,234],[415,235],[416,235],[423,236],[426,237],[427,238],[428,238],[429,239],[434,17],[408,17],[435,238],[436,240],[418,241],[422,242],[417,243],[437,244],[438,245],[424,246],[439,247],[462,248],[480,249],[285,60],[307,60],[308,17],[309,17],[310,17],[311,17],[316,17],[288,60],[251,17],[252,17],[312,60],[317,17],[318,17],[313,17],[314,17],[286,60],[247,17],[315,17],[319,60],[320,60],[321,60],[322,60],[323,60],[253,60],[324,60],[294,60],[325,60],[326,60],[333,60],[327,60],[328,60],[329,60],[330,60],[331,60],[334,60],[335,60],[332,60],[336,60],[341,60],[342,60],[343,60],[344,60],[345,60],[337,60],[338,60],[254,60],[339,60],[255,60],[279,60],[346,60],[340,60],[347,60],[348,60],[349,60],[256,60],[280,60],[350,60],[351,60],[352,60],[353,60],[354,60],[355,60],[356,60],[259,60],[357,60],[358,60],[360,60],[359,60],[361,60],[257,60],[463,250],[481,251],[464,252],[466,253],[467,253],[482,254],[468,255],[485,271],[469,257],[470,253],[471,258],[472,259],[473,260],[486,261],[490,262],[491,263],[493,264],[474,265],[477,266],[495,267],[478,253],[479,268],[291,17],[249,17],[484,17]],"semanticDiagnosticsPerFile":[246,388,483,487,494,492,394,488,390,395,396,367,383,384,392,391,397,389,398,402,489,393,403,399,401,400,404,405,406,407,441,442,443,445,446,447,448,449,450,451,387,452,362,454,455,456,457,458,263,281,282,283,245,250,287,258,289,265,266,267,262,290,292,293,260,295,248,261,278,202,296,297,298,299,300,301,302,459,460,461,444,303,304,306,305,201,363,365,385,386,364,366,370,371,372,373,374,375,376,377,378,379,380,381,382,368,369,167,203,205,236,207,209,206,210,208,224,237,229,219,214,215,238,230,243,231,216,211,218,235,222,225,217,239,228,223,232,221,204,227,212,213,233,241,240,226,234,220,242,497,499,272,500,501,284,502,504,503,506,507,505,496,69,70,72,73,74,75,76,77,78,79,80,81,82,84,83,85,86,87,71,121,88,89,90,122,91,92,93,94,95,96,97,98,99,100,101,102,103,105,104,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,508,60,509,511,58,62,512,61,537,538,513,516,535,536,526,525,523,518,531,529,533,517,530,534,519,520,532,514,521,522,524,528,539,527,515,552,551,546,548,547,540,541,543,545,549,550,542,544,498,553,554,59,268,264,273,274,276,275,277,68,177,179,137,147,138,139,148,128,188,190,172,171,170,193,169,196,124,126,176,180,184,131,130,151,159,134,129,125,163,162,152,123,160,153,161,164,140,154,135,158,157,136,150,149,141,142,144,143,145,195,146,67,174,182,186,166,127,168,173,156,155,133,132,178,175,57,66,63,64,65,181,183,185,187,200,189,199,191,192,194,197,198,165,244,465,453,271,270,269,510,476,475,11,12,14,13,2,15,16,17,18,19,20,21,22,3,4,26,23,24,25,27,28,29,5,30,31,32,33,6,37,34,35,36,38,7,39,44,45,40,41,42,43,8,49,46,47,48,50,9,51,52,53,54,55,1,10,56,433,410,419,432,431,409,440,411,420,430,414,425,421,413,412,415,416,423,426,427,428,429,434,408,435,436,418,422,417,437,438,424,439,462,480,285,307,308,309,310,311,316,288,251,252,312,317,318,313,314,286,247,315,319,320,321,322,323,253,324,294,325,326,333,327,328,329,330,331,334,335,332,336,341,342,343,344,345,337,338,254,339,255,279,346,340,347,348,349,256,280,350,351,352,353,354,355,356,259,357,358,360,359,361,257,463,481,464,466,467,482,468,485,469,470,471,472,473,486,490,491,493,474,477,495,478,479,291,249,484],"affectedFilesPendingEmit":[[246,1],[388,1],[483,1],[487,1],[494,1],[492,1],[394,1],[488,1],[390,1],[395,1],[396,1],[367,1],[383,1],[384,1],[392,1],[391,1],[397,1],[555,1],[389,1],[398,1],[402,1],[489,1],[393,1],[403,1],[399,1],[401,1],[400,1],[404,1],[405,1],[406,1],[407,1],[441,1],[442,1],[443,1],[445,1],[446,1],[447,1],[448,1],[449,1],[450,1],[451,1],[387,1],[452,1],[362,1],[454,1],[455,1],[456,1],[457,1],[458,1],[263,1],[281,1],[282,1],[283,1],[245,1],[250,1],[287,1],[258,1],[289,1],[265,1],[266,1],[267,1],[262,1],[290,1],[292,1],[293,1],[260,1],[295,1],[248,1],[261,1],[278,1],[202,1],[296,1],[297,1],[298,1],[299,1],[300,1],[301,1],[302,1],[459,1],[460,1],[461,1],[444,1],[303,1],[304,1],[306,1],[305,1],[201,1],[363,1],[365,1],[385,1],[386,1],[364,1],[366,1],[370,1],[371,1],[372,1],[373,1],[374,1],[375,1],[376,1],[377,1],[378,1],[379,1],[380,1],[381,1],[382,1],[368,1],[369,1],[167,1],[203,1],[205,1],[236,1],[207,1],[209,1],[206,1],[210,1],[208,1],[224,1],[237,1],[229,1],[219,1],[214,1],[215,1],[238,1],[230,1],[243,1],[231,1],[216,1],[211,1],[218,1],[235,1],[222,1],[225,1],[217,1],[239,1],[228,1],[223,1],[232,1],[221,1],[204,1],[227,1],[212,1],[213,1],[233,1],[241,1],[240,1],[226,1],[234,1],[220,1],[242,1],[497,1],[499,1],[272,1],[500,1],[501,1],[284,1],[502,1],[504,1],[503,1],[506,1],[507,1],[505,1],[496,1],[69,1],[70,1],[72,1],[73,1],[74,1],[75,1],[76,1],[77,1],[78,1],[79,1],[80,1],[81,1],[82,1],[84,1],[83,1],[85,1],[86,1],[87,1],[71,1],[121,1],[88,1],[89,1],[90,1],[122,1],[91,1],[92,1],[93,1],[94,1],[95,1],[96,1],[97,1],[98,1],[99,1],[100,1],[101,1],[102,1],[103,1],[105,1],[104,1],[106,1],[107,1],[108,1],[109,1],[110,1],[111,1],[112,1],[113,1],[114,1],[115,1],[116,1],[117,1],[118,1],[119,1],[120,1],[508,1],[60,1],[509,1],[511,1],[58,1],[62,1],[512,1],[61,1],[537,1],[538,1],[513,1],[516,1],[535,1],[536,1],[526,1],[525,1],[523,1],[518,1],[531,1],[529,1],[533,1],[517,1],[530,1],[534,1],[519,1],[520,1],[532,1],[514,1],[521,1],[522,1],[524,1],[528,1],[539,1],[527,1],[515,1],[552,1],[551,1],[546,1],[548,1],[547,1],[540,1],[541,1],[543,1],[545,1],[549,1],[550,1],[542,1],[544,1],[498,1],[553,1],[554,1],[59,1],[268,1],[264,1],[273,1],[274,1],[276,1],[275,1],[277,1],[68,1],[177,1],[179,1],[137,1],[147,1],[138,1],[139,1],[148,1],[128,1],[188,1],[190,1],[172,1],[171,1],[170,1],[193,1],[169,1],[196,1],[124,1],[126,1],[176,1],[180,1],[184,1],[131,1],[130,1],[151,1],[159,1],[134,1],[129,1],[125,1],[163,1],[162,1],[152,1],[123,1],[160,1],[153,1],[161,1],[164,1],[140,1],[154,1],[135,1],[158,1],[157,1],[136,1],[150,1],[149,1],[141,1],[142,1],[144,1],[143,1],[145,1],[195,1],[146,1],[67,1],[174,1],[182,1],[186,1],[166,1],[127,1],[168,1],[173,1],[156,1],[155,1],[133,1],[132,1],[178,1],[175,1],[57,1],[66,1],[63,1],[64,1],[65,1],[181,1],[183,1],[185,1],[187,1],[200,1],[189,1],[199,1],[191,1],[192,1],[194,1],[197,1],[198,1],[165,1],[244,1],[465,1],[453,1],[271,1],[270,1],[269,1],[510,1],[476,1],[475,1],[2,1],[3,1],[4,1],[5,1],[6,1],[7,1],[8,1],[9,1],[10,1],[433,1],[410,1],[419,1],[432,1],[431,1],[409,1],[440,1],[411,1],[420,1],[430,1],[414,1],[425,1],[421,1],[413,1],[412,1],[415,1],[416,1],[423,1],[426,1],[427,1],[428,1],[429,1],[434,1],[408,1],[435,1],[436,1],[418,1],[422,1],[417,1],[437,1],[438,1],[424,1],[439,1],[462,1],[480,1],[285,1],[307,1],[308,1],[309,1],[310,1],[311,1],[316,1],[288,1],[251,1],[252,1],[312,1],[317,1],[318,1],[313,1],[314,1],[286,1],[247,1],[315,1],[319,1],[320,1],[321,1],[322,1],[323,1],[253,1],[324,1],[294,1],[325,1],[326,1],[333,1],[327,1],[328,1],[329,1],[330,1],[331,1],[334,1],[335,1],[332,1],[336,1],[341,1],[342,1],[343,1],[344,1],[345,1],[337,1],[338,1],[254,1],[339,1],[255,1],[279,1],[346,1],[340,1],[347,1],[348,1],[349,1],[256,1],[280,1],[350,1],[351,1],[352,1],[353,1],[354,1],[355,1],[356,1],[259,1],[357,1],[358,1],[360,1],[359,1],[361,1],[257,1],[463,1],[481,1],[464,1],[466,1],[467,1],[482,1],[468,1],[485,1],[469,1],[470,1],[471,1],[472,1],[473,1],[486,1],[490,1],[491,1],[493,1],[474,1],[477,1],[495,1],[478,1],[479,1],[291,1],[249,1],[484,1]]},"version":"4.9.3"} \ No newline at end of file