diff --git a/frontend/src/atoms.ts b/frontend/src/atoms.ts index ba44274c..d702102f 100644 --- a/frontend/src/atoms.ts +++ b/frontend/src/atoms.ts @@ -28,6 +28,7 @@ export const HydrateAtoms = ({ children }: { children: ReactElement }) => { const CURRENT_VIEWER_QUERY = graphql(/* GraphQL */ ` query CurrentViewerQuery { viewer { + __typename ... on User { id } @@ -52,6 +53,7 @@ export const currentUserIdAtom = atom(async (get) => { const CURRENT_VIEWER_SESSION_QUERY = graphql(/* GraphQL */ ` query CurrentViewerSessionQuery { viewerSession { + __typename ... on BrowserSession { id } diff --git a/frontend/src/components/AddEmailForm.tsx b/frontend/src/components/AddEmailForm.tsx index 86b9785c..bd7c1697 100644 --- a/frontend/src/components/AddEmailForm.tsx +++ b/frontend/src/components/AddEmailForm.tsx @@ -14,12 +14,13 @@ import React, { useRef, useTransition } from "react"; import { atomWithMutation } from "jotai-urql"; -import { useAtom } from "jotai"; +import { useAtom, useSetAtom } from "jotai"; import { graphql } from "../gql"; import Button from "./Button"; import UserEmail from "./UserEmail"; import Input from "./Input"; import Typography from "./Typography"; +import { emailPageResultFamily } from "./UserEmailList"; const ADD_EMAIL_MUTATION = graphql(/* GraphQL */ ` mutation AddEmail($userId: ID!, $email: String!) { @@ -42,12 +43,15 @@ const AddEmailForm: React.FC<{ userId: string }> = ({ userId }) => { const formRef = useRef(null); const [addEmailResult, addEmail] = useAtom(addUserEmailAtom); const [pending, startTransition] = useTransition(); + // XXX: is this the right way to do this? + const refetchList = useSetAtom(emailPageResultFamily(userId)); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); const email = e.currentTarget.email.value; startTransition(() => { addEmail({ userId, email }).then(() => { + refetchList(); if (formRef.current) { formRef.current.reset(); } @@ -59,7 +63,7 @@ const AddEmailForm: React.FC<{ userId: string }> = ({ userId }) => { <> {addEmailResult.data?.addEmail.status === "ADDED" && ( <> -
+
Email added!
@@ -67,7 +71,7 @@ const AddEmailForm: React.FC<{ userId: string }> = ({ userId }) => { )} {addEmailResult.data?.addEmail.status === "EXISTS" && ( <> -
+
Email already exists!
diff --git a/frontend/src/components/BrowserSessionList.tsx b/frontend/src/components/BrowserSessionList.tsx index cb1f0894..dc9cd570 100644 --- a/frontend/src/components/BrowserSessionList.tsx +++ b/frontend/src/components/BrowserSessionList.tsx @@ -15,42 +15,58 @@ import BlockList from "./BlockList"; import BrowserSession from "./BrowserSession"; import { Title } from "./Typography"; -import { FragmentType, graphql, useFragment } from "../gql"; +import { graphql } from "../gql"; +import { atomFamily } from "jotai/utils"; +import { atomWithQuery } from "jotai-urql"; +import { useAtomValue } from "jotai"; +import { currentBrowserSessionIdAtom } from "../atoms"; -const FRAGMENT = graphql(/* GraphQL */ ` - fragment BrowserSessionList_user on User { - browserSessions(first: 10) { - edges { - cursor - node { - id - ...BrowserSession_session +const QUERY = graphql(/* GraphQL */ ` + query BrowserSessionList($userId: ID!) { + user(id: $userId) { + id + browserSessions(first: 10) { + edges { + cursor + node { + id + ...BrowserSession_session + } } } } } `); -type Props = { - user: FragmentType; - currentSessionId: string; -}; +const browserSessionListFamily = atomFamily((userId: string) => { + const browserSessionList = atomWithQuery({ + query: QUERY, + getVariables: () => ({ userId }), + }); + return browserSessionList; +}); -const BrowserSessionList: React.FC = ({ user, currentSessionId }) => { - const data = useFragment(FRAGMENT, user); +const BrowserSessionList: React.FC<{ userId: string }> = ({ userId }) => { + const result = useAtomValue(browserSessionListFamily(userId)); + const currentSessionId = useAtomValue(currentBrowserSessionIdAtom); - return ( - - List of browser sessions: - {data.browserSessions.edges.map((n) => ( - - ))} - - ); + if (result.data?.user?.browserSessions) { + const data = result.data.user.browserSessions; + return ( + + List of browser sessions: + {data.edges.map((n) => ( + + ))} + + ); + } + + return <>Failed to load browser sessions; }; export default BrowserSessionList; diff --git a/frontend/src/components/CompatSsoLoginList.tsx b/frontend/src/components/CompatSsoLoginList.tsx index 22c45c74..346250a8 100644 --- a/frontend/src/components/CompatSsoLoginList.tsx +++ b/frontend/src/components/CompatSsoLoginList.tsx @@ -15,36 +15,52 @@ import BlockList from "./BlockList"; import CompatSsoLogin from "./CompatSsoLogin"; import { Title } from "./Typography"; -import { FragmentType, graphql, useFragment } from "../gql"; +import { graphql } from "../gql"; +import { atomFamily } from "jotai/utils"; +import { atomWithQuery } from "jotai-urql"; +import { useAtomValue } from "jotai"; -const FRAGMENT = graphql(/* GraphQL */ ` - fragment CompatSsoLoginList_user on User { - compatSsoLogins(first: 10) { - edges { - node { - id - ...CompatSsoLogin_login +const QUERY = graphql(/* GraphQL */ ` + query CompatSsoLoginList($userId: ID!) { + user(id: $userId) { + id + compatSsoLogins(first: 10) { + edges { + node { + id + ...CompatSsoLogin_login + } } } } } `); -type Props = { - user: FragmentType; -}; +const compatSsoLoginListFamily = atomFamily((userId: string) => { + const compatSsoLoginList = atomWithQuery({ + query: QUERY, + getVariables: () => ({ userId }), + }); -const CompatSsoLoginList: React.FC = ({ user }) => { - const data = useFragment(FRAGMENT, user); + return compatSsoLoginList; +}); - return ( - - List of compatibility sessions: - {data.compatSsoLogins.edges.map((n) => ( - - ))} - - ); +const CompatSsoLoginList: React.FC<{ userId: string }> = ({ userId }) => { + const result = useAtomValue(compatSsoLoginListFamily(userId)); + + if (result.data?.user?.compatSsoLogins) { + const data = result.data.user.compatSsoLogins; + return ( + + List of compatibility sessions: + {data.edges.map((n) => ( + + ))} + + ); + } + + return <>Failed to load list of compatibility sessions.; }; export default CompatSsoLoginList; diff --git a/frontend/src/components/OAuth2SessionList.tsx b/frontend/src/components/OAuth2SessionList.tsx index 2506e34d..68e511a1 100644 --- a/frontend/src/components/OAuth2SessionList.tsx +++ b/frontend/src/components/OAuth2SessionList.tsx @@ -12,41 +12,62 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { atomFamily } from "jotai/utils"; +import { atomWithQuery } from "jotai-urql"; +import { useAtomValue } from "jotai"; + import BlockList from "./BlockList"; import OAuth2Session from "./OAuth2Session"; import { Title } from "./Typography"; -import { FragmentType, graphql, useFragment } from "../gql"; +import { graphql } from "../gql"; -const FRAGMENT = graphql(/* GraphQL */ ` - fragment OAuth2SessionList_user on User { - oauth2Sessions(first: 10) { - edges { - cursor - node { - id - ...OAuth2Session_session +const QUERY = graphql(/* GraphQL */ ` + query OAuth2SessionListQuery($userId: ID!) { + user(id: $userId) { + id + oauth2Sessions(first: 10) { + edges { + cursor + node { + id + ...OAuth2Session_session + } } } } } `); +const oauth2SessionListFamily = atomFamily((userId: string) => { + const oauth2SessionList = atomWithQuery({ + query: QUERY, + getVariables: () => ({ userId }), + }); + + return oauth2SessionList; +}); + type Props = { - user: FragmentType; + userId: string; }; -const OAuth2SessionList: React.FC = ({ user }) => { - const data = useFragment(FRAGMENT, user); +const OAuth2SessionList: React.FC = ({ userId }) => { + const result = useAtomValue(oauth2SessionListFamily(userId)); - return ( - - List of OAuth 2.0 sessions: - {data.oauth2Sessions.edges.map((n) => ( - - ))} - - ); + if (result.data?.user?.oauth2Sessions) { + const data = result.data.user.oauth2Sessions; + return ( + + List of OAuth 2.0 sessions: + {data.edges.map((n) => ( + + ))} + + ); + } else { + return <>Failed to load OAuth 2.0 session list; + } }; export default OAuth2SessionList; diff --git a/frontend/src/components/UserEmailList.tsx b/frontend/src/components/UserEmailList.tsx index 158ccacc..387b71e9 100644 --- a/frontend/src/components/UserEmailList.tsx +++ b/frontend/src/components/UserEmailList.tsx @@ -83,7 +83,7 @@ const currentPagination = atomWithDefault((get) => ({ after: null, })); -const emailPageResultFamily = atomFamily((userId: string) => { +export const emailPageResultFamily = atomFamily((userId: string) => { const emailPageResult = atomWithQuery({ query: QUERY, getVariables: (get) => ({ userId, ...get(currentPagination) }), diff --git a/frontend/src/components/UserGreeting.tsx b/frontend/src/components/UserGreeting.tsx new file mode 100644 index 00000000..4ab2cd81 --- /dev/null +++ b/frontend/src/components/UserGreeting.tsx @@ -0,0 +1,49 @@ +// Copyright 2023 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { graphql } from "../gql"; +import { atomFamily } from "jotai/utils"; +import { atomWithQuery } from "jotai-urql"; +import { useAtomValue } from "jotai"; +import { Title } from "./Typography"; + +const QUERY = graphql(/* GraphQL */ ` + query UserGreeting($userId: ID!) { + user(id: $userId) { + id + username + } + } +`); + +const userGreetingFamily = atomFamily((userId: string) => { + const userGreeting = atomWithQuery({ + query: QUERY, + getVariables: () => ({ userId }), + }); + + return userGreeting; +}); + +const UserGreeting: React.FC<{ userId: string }> = ({ userId }) => { + const result = useAtomValue(userGreetingFamily(userId)); + + if (result.data?.user) { + return Hello, {result.data.user.username}!; + } + + return <>Failed to load user; +}; + +export default UserGreeting; diff --git a/frontend/src/gql/gql.ts b/frontend/src/gql/gql.ts index 78937d10..92822882 100644 --- a/frontend/src/gql/gql.ts +++ b/frontend/src/gql/gql.ts @@ -13,34 +13,32 @@ import { TypedDocumentNode as DocumentNode } from "@graphql-typed-document-node/ * Therefore it is highly recommended to use the babel or swc plugin for production. */ const documents = { - "\n query CurrentViewerQuery {\n viewer {\n ... on User {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n": + "\n query CurrentViewerQuery {\n viewer {\n __typename\n ... on User {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n": types.CurrentViewerQueryDocument, - "\n query CurrentViewerSessionQuery {\n viewerSession {\n ... on BrowserSession {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n": + "\n query CurrentViewerSessionQuery {\n viewerSession {\n __typename\n ... on BrowserSession {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n": types.CurrentViewerSessionQueryDocument, "\n mutation AddEmail($userId: ID!, $email: String!) {\n addEmail(input: { userId: $userId, email: $email }) {\n status\n user {\n id\n }\n email {\n id\n ...UserEmail_email\n }\n }\n }\n": types.AddEmailDocument, "\n fragment BrowserSession_session on BrowserSession {\n id\n createdAt\n lastAuthentication {\n id\n createdAt\n }\n }\n": types.BrowserSession_SessionFragmentDoc, - "\n fragment BrowserSessionList_user on User {\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n }\n }\n": - types.BrowserSessionList_UserFragmentDoc, + "\n query BrowserSessionList($userId: ID!) {\n user(id: $userId) {\n id\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n }\n }\n }\n": + types.BrowserSessionListDocument, "\n fragment CompatSsoLogin_login on CompatSsoLogin {\n id\n redirectUri\n createdAt\n session {\n id\n createdAt\n deviceId\n finishedAt\n }\n }\n": types.CompatSsoLogin_LoginFragmentDoc, - "\n fragment CompatSsoLoginList_user on User {\n compatSsoLogins(first: 10) {\n edges {\n node {\n id\n ...CompatSsoLogin_login\n }\n }\n }\n }\n": - types.CompatSsoLoginList_UserFragmentDoc, + "\n query CompatSsoLoginList($userId: ID!) {\n user(id: $userId) {\n id\n compatSsoLogins(first: 10) {\n edges {\n node {\n id\n ...CompatSsoLogin_login\n }\n }\n }\n }\n }\n": + types.CompatSsoLoginListDocument, "\n fragment OAuth2Session_session on Oauth2Session {\n id\n scope\n client {\n id\n clientId\n clientName\n clientUri\n }\n }\n": types.OAuth2Session_SessionFragmentDoc, - "\n fragment OAuth2SessionList_user on User {\n oauth2Sessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...OAuth2Session_session\n }\n }\n }\n }\n": - types.OAuth2SessionList_UserFragmentDoc, + "\n query OAuth2SessionListQuery($userId: ID!) {\n user(id: $userId) {\n id\n oauth2Sessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...OAuth2Session_session\n }\n }\n }\n }\n }\n": + types.OAuth2SessionListQueryDocument, "\n fragment UserEmail_email on UserEmail {\n id\n email\n createdAt\n confirmedAt\n }\n": types.UserEmail_EmailFragmentDoc, "\n query UserEmailListQuery(\n $userId: ID!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n user(id: $userId) {\n id\n emails(first: $first, after: $after, last: $last, before: $before) {\n edges {\n cursor\n node {\n id\n ...UserEmail_email\n }\n }\n totalCount\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n }\n }\n }\n": types.UserEmailListQueryDocument, - "\n query AccountQuery($id: ID!) {\n user(id: $id) {\n id\n username\n }\n }\n": - types.AccountQueryDocument, + "\n query UserGreeting($userId: ID!) {\n user(id: $userId) {\n id\n username\n }\n }\n": + types.UserGreetingDocument, "\n query BrowserSessionQuery($id: ID!) {\n browserSession(id: $id) {\n id\n createdAt\n lastAuthentication {\n id\n createdAt\n }\n user {\n id\n username\n }\n }\n }\n": types.BrowserSessionQueryDocument, - "\n query HomeQuery {\n # eslint-disable-next-line @graphql-eslint/no-deprecated\n currentBrowserSession {\n id\n user {\n id\n username\n\n ...CompatSsoLoginList_user\n ...BrowserSessionList_user\n ...OAuth2SessionList_user\n }\n }\n }\n": - types.HomeQueryDocument, "\n query OAuth2ClientQuery($id: ID!) {\n oauth2Client(id: $id) {\n id\n clientId\n clientName\n clientUri\n tosUri\n policyUri\n redirectUris\n }\n }\n": types.OAuth2ClientQueryDocument, }; @@ -63,14 +61,14 @@ export function graphql(source: string): unknown; * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: "\n query CurrentViewerQuery {\n viewer {\n ... on User {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n" -): (typeof documents)["\n query CurrentViewerQuery {\n viewer {\n ... on User {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n"]; + source: "\n query CurrentViewerQuery {\n viewer {\n __typename\n ... on User {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n" +): (typeof documents)["\n query CurrentViewerQuery {\n viewer {\n __typename\n ... on User {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: "\n query CurrentViewerSessionQuery {\n viewerSession {\n ... on BrowserSession {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n" -): (typeof documents)["\n query CurrentViewerSessionQuery {\n viewerSession {\n ... on BrowserSession {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n"]; + source: "\n query CurrentViewerSessionQuery {\n viewerSession {\n __typename\n ... on BrowserSession {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n" +): (typeof documents)["\n query CurrentViewerSessionQuery {\n viewerSession {\n __typename\n ... on BrowserSession {\n id\n }\n\n ... on Anonymous {\n id\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -87,8 +85,8 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: "\n fragment BrowserSessionList_user on User {\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n }\n }\n" -): (typeof documents)["\n fragment BrowserSessionList_user on User {\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n }\n }\n"]; + source: "\n query BrowserSessionList($userId: ID!) {\n user(id: $userId) {\n id\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n }\n }\n }\n" +): (typeof documents)["\n query BrowserSessionList($userId: ID!) {\n user(id: $userId) {\n id\n browserSessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...BrowserSession_session\n }\n }\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -99,8 +97,8 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: "\n fragment CompatSsoLoginList_user on User {\n compatSsoLogins(first: 10) {\n edges {\n node {\n id\n ...CompatSsoLogin_login\n }\n }\n }\n }\n" -): (typeof documents)["\n fragment CompatSsoLoginList_user on User {\n compatSsoLogins(first: 10) {\n edges {\n node {\n id\n ...CompatSsoLogin_login\n }\n }\n }\n }\n"]; + source: "\n query CompatSsoLoginList($userId: ID!) {\n user(id: $userId) {\n id\n compatSsoLogins(first: 10) {\n edges {\n node {\n id\n ...CompatSsoLogin_login\n }\n }\n }\n }\n }\n" +): (typeof documents)["\n query CompatSsoLoginList($userId: ID!) {\n user(id: $userId) {\n id\n compatSsoLogins(first: 10) {\n edges {\n node {\n id\n ...CompatSsoLogin_login\n }\n }\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -111,8 +109,8 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: "\n fragment OAuth2SessionList_user on User {\n oauth2Sessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...OAuth2Session_session\n }\n }\n }\n }\n" -): (typeof documents)["\n fragment OAuth2SessionList_user on User {\n oauth2Sessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...OAuth2Session_session\n }\n }\n }\n }\n"]; + source: "\n query OAuth2SessionListQuery($userId: ID!) {\n user(id: $userId) {\n id\n oauth2Sessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...OAuth2Session_session\n }\n }\n }\n }\n }\n" +): (typeof documents)["\n query OAuth2SessionListQuery($userId: ID!) {\n user(id: $userId) {\n id\n oauth2Sessions(first: 10) {\n edges {\n cursor\n node {\n id\n ...OAuth2Session_session\n }\n }\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -129,20 +127,14 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: "\n query AccountQuery($id: ID!) {\n user(id: $id) {\n id\n username\n }\n }\n" -): (typeof documents)["\n query AccountQuery($id: ID!) {\n user(id: $id) {\n id\n username\n }\n }\n"]; + source: "\n query UserGreeting($userId: ID!) {\n user(id: $userId) {\n id\n username\n }\n }\n" +): (typeof documents)["\n query UserGreeting($userId: ID!) {\n user(id: $userId) {\n id\n username\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( source: "\n query BrowserSessionQuery($id: ID!) {\n browserSession(id: $id) {\n id\n createdAt\n lastAuthentication {\n id\n createdAt\n }\n user {\n id\n username\n }\n }\n }\n" ): (typeof documents)["\n query BrowserSessionQuery($id: ID!) {\n browserSession(id: $id) {\n id\n createdAt\n lastAuthentication {\n id\n createdAt\n }\n user {\n id\n username\n }\n }\n }\n"]; -/** - * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - */ -export function graphql( - source: "\n query HomeQuery {\n # eslint-disable-next-line @graphql-eslint/no-deprecated\n currentBrowserSession {\n id\n user {\n id\n username\n\n ...CompatSsoLoginList_user\n ...BrowserSessionList_user\n ...OAuth2SessionList_user\n }\n }\n }\n" -): (typeof documents)["\n query HomeQuery {\n # eslint-disable-next-line @graphql-eslint/no-deprecated\n currentBrowserSession {\n id\n user {\n id\n username\n\n ...CompatSsoLoginList_user\n ...BrowserSessionList_user\n ...OAuth2SessionList_user\n }\n }\n }\n"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/frontend/src/gql/graphql.ts b/frontend/src/gql/graphql.ts index 597d18a6..021d7a52 100644 --- a/frontend/src/gql/graphql.ts +++ b/frontend/src/gql/graphql.ts @@ -582,8 +582,8 @@ export type CurrentViewerQueryQueryVariables = Exact<{ [key: string]: never }>; export type CurrentViewerQueryQuery = { __typename?: "Query"; viewer: - | { __typename?: "Anonymous"; id: string } - | { __typename?: "User"; id: string }; + | { __typename: "Anonymous"; id: string } + | { __typename: "User"; id: string }; }; export type CurrentViewerSessionQueryQueryVariables = Exact<{ @@ -593,8 +593,8 @@ export type CurrentViewerSessionQueryQueryVariables = Exact<{ export type CurrentViewerSessionQueryQuery = { __typename?: "Query"; viewerSession: - | { __typename?: "Anonymous"; id: string } - | { __typename?: "BrowserSession"; id: string }; + | { __typename: "Anonymous"; id: string } + | { __typename: "BrowserSession"; id: string }; }; export type AddEmailMutationVariables = Exact<{ @@ -625,21 +625,29 @@ export type BrowserSession_SessionFragment = { } | null; } & { " $fragmentName"?: "BrowserSession_SessionFragment" }; -export type BrowserSessionList_UserFragment = { - __typename?: "User"; - browserSessions: { - __typename?: "BrowserSessionConnection"; - edges: Array<{ - __typename?: "BrowserSessionEdge"; - cursor: string; - node: { __typename?: "BrowserSession"; id: string } & { - " $fragmentRefs"?: { - BrowserSession_SessionFragment: BrowserSession_SessionFragment; +export type BrowserSessionListQueryVariables = Exact<{ + userId: Scalars["ID"]; +}>; + +export type BrowserSessionListQuery = { + __typename?: "Query"; + user?: { + __typename?: "User"; + id: string; + browserSessions: { + __typename?: "BrowserSessionConnection"; + edges: Array<{ + __typename?: "BrowserSessionEdge"; + cursor: string; + node: { __typename?: "BrowserSession"; id: string } & { + " $fragmentRefs"?: { + BrowserSession_SessionFragment: BrowserSession_SessionFragment; + }; }; - }; - }>; - }; -} & { " $fragmentName"?: "BrowserSessionList_UserFragment" }; + }>; + }; + } | null; +}; export type CompatSsoLogin_LoginFragment = { __typename?: "CompatSsoLogin"; @@ -655,20 +663,28 @@ export type CompatSsoLogin_LoginFragment = { } | null; } & { " $fragmentName"?: "CompatSsoLogin_LoginFragment" }; -export type CompatSsoLoginList_UserFragment = { - __typename?: "User"; - compatSsoLogins: { - __typename?: "CompatSsoLoginConnection"; - edges: Array<{ - __typename?: "CompatSsoLoginEdge"; - node: { __typename?: "CompatSsoLogin"; id: string } & { - " $fragmentRefs"?: { - CompatSsoLogin_LoginFragment: CompatSsoLogin_LoginFragment; +export type CompatSsoLoginListQueryVariables = Exact<{ + userId: Scalars["ID"]; +}>; + +export type CompatSsoLoginListQuery = { + __typename?: "Query"; + user?: { + __typename?: "User"; + id: string; + compatSsoLogins: { + __typename?: "CompatSsoLoginConnection"; + edges: Array<{ + __typename?: "CompatSsoLoginEdge"; + node: { __typename?: "CompatSsoLogin"; id: string } & { + " $fragmentRefs"?: { + CompatSsoLogin_LoginFragment: CompatSsoLogin_LoginFragment; + }; }; - }; - }>; - }; -} & { " $fragmentName"?: "CompatSsoLoginList_UserFragment" }; + }>; + }; + } | null; +}; export type OAuth2Session_SessionFragment = { __typename?: "Oauth2Session"; @@ -683,21 +699,29 @@ export type OAuth2Session_SessionFragment = { }; } & { " $fragmentName"?: "OAuth2Session_SessionFragment" }; -export type OAuth2SessionList_UserFragment = { - __typename?: "User"; - oauth2Sessions: { - __typename?: "Oauth2SessionConnection"; - edges: Array<{ - __typename?: "Oauth2SessionEdge"; - cursor: string; - node: { __typename?: "Oauth2Session"; id: string } & { - " $fragmentRefs"?: { - OAuth2Session_SessionFragment: OAuth2Session_SessionFragment; +export type OAuth2SessionListQueryQueryVariables = Exact<{ + userId: Scalars["ID"]; +}>; + +export type OAuth2SessionListQueryQuery = { + __typename?: "Query"; + user?: { + __typename?: "User"; + id: string; + oauth2Sessions: { + __typename?: "Oauth2SessionConnection"; + edges: Array<{ + __typename?: "Oauth2SessionEdge"; + cursor: string; + node: { __typename?: "Oauth2Session"; id: string } & { + " $fragmentRefs"?: { + OAuth2Session_SessionFragment: OAuth2Session_SessionFragment; + }; }; - }; - }>; - }; -} & { " $fragmentName"?: "OAuth2SessionList_UserFragment" }; + }>; + }; + } | null; +}; export type UserEmail_EmailFragment = { __typename?: "UserEmail"; @@ -743,11 +767,11 @@ export type UserEmailListQueryQuery = { } | null; }; -export type AccountQueryQueryVariables = Exact<{ - id: Scalars["ID"]; +export type UserGreetingQueryVariables = Exact<{ + userId: Scalars["ID"]; }>; -export type AccountQueryQuery = { +export type UserGreetingQuery = { __typename?: "Query"; user?: { __typename?: "User"; id: string; username: string } | null; }; @@ -771,23 +795,6 @@ export type BrowserSessionQueryQuery = { } | null; }; -export type HomeQueryQueryVariables = Exact<{ [key: string]: never }>; - -export type HomeQueryQuery = { - __typename?: "Query"; - currentBrowserSession?: { - __typename?: "BrowserSession"; - id: string; - user: { __typename?: "User"; id: string; username: string } & { - " $fragmentRefs"?: { - CompatSsoLoginList_UserFragment: CompatSsoLoginList_UserFragment; - BrowserSessionList_UserFragment: BrowserSessionList_UserFragment; - OAuth2SessionList_UserFragment: OAuth2SessionList_UserFragment; - }; - }; - } | null; -}; - export type OAuth2ClientQueryQueryVariables = Exact<{ id: Scalars["ID"]; }>; @@ -837,99 +844,6 @@ export const BrowserSession_SessionFragmentDoc = { }, ], } as unknown as DocumentNode; -export const BrowserSessionList_UserFragmentDoc = { - kind: "Document", - definitions: [ - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "BrowserSessionList_user" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "User" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "browserSessions" }, - arguments: [ - { - kind: "Argument", - name: { kind: "Name", value: "first" }, - value: { kind: "IntValue", value: "10" }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "edges" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "cursor" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "node" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "id" }, - }, - { - kind: "FragmentSpread", - name: { - kind: "Name", - value: "BrowserSession_session", - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "BrowserSession_session" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "BrowserSession" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "createdAt" } }, - { - kind: "Field", - name: { kind: "Name", value: "lastAuthentication" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "createdAt" } }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode; export const CompatSsoLogin_LoginFragmentDoc = { kind: "Document", definitions: [ @@ -964,98 +878,6 @@ export const CompatSsoLogin_LoginFragmentDoc = { }, ], } as unknown as DocumentNode; -export const CompatSsoLoginList_UserFragmentDoc = { - kind: "Document", - definitions: [ - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "CompatSsoLoginList_user" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "User" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "compatSsoLogins" }, - arguments: [ - { - kind: "Argument", - name: { kind: "Name", value: "first" }, - value: { kind: "IntValue", value: "10" }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "edges" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "node" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "id" }, - }, - { - kind: "FragmentSpread", - name: { - kind: "Name", - value: "CompatSsoLogin_login", - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "CompatSsoLogin_login" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "CompatSsoLogin" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "redirectUri" } }, - { kind: "Field", name: { kind: "Name", value: "createdAt" } }, - { - kind: "Field", - name: { kind: "Name", value: "session" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "createdAt" } }, - { kind: "Field", name: { kind: "Name", value: "deviceId" } }, - { kind: "Field", name: { kind: "Name", value: "finishedAt" } }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode; export const OAuth2Session_SessionFragmentDoc = { kind: "Document", definitions: [ @@ -1089,101 +911,6 @@ export const OAuth2Session_SessionFragmentDoc = { }, ], } as unknown as DocumentNode; -export const OAuth2SessionList_UserFragmentDoc = { - kind: "Document", - definitions: [ - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "OAuth2SessionList_user" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "User" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "oauth2Sessions" }, - arguments: [ - { - kind: "Argument", - name: { kind: "Name", value: "first" }, - value: { kind: "IntValue", value: "10" }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "edges" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "cursor" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "node" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "id" }, - }, - { - kind: "FragmentSpread", - name: { - kind: "Name", - value: "OAuth2Session_session", - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "OAuth2Session_session" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "Oauth2Session" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "scope" } }, - { - kind: "Field", - name: { kind: "Name", value: "client" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "clientId" } }, - { kind: "Field", name: { kind: "Name", value: "clientName" } }, - { kind: "Field", name: { kind: "Name", value: "clientUri" } }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode; export const UserEmail_EmailFragmentDoc = { kind: "Document", definitions: [ @@ -1222,6 +949,7 @@ export const CurrentViewerQueryDocument = { selectionSet: { kind: "SelectionSet", selections: [ + { kind: "Field", name: { kind: "Name", value: "__typename" } }, { kind: "InlineFragment", typeCondition: { @@ -1275,6 +1003,7 @@ export const CurrentViewerSessionQueryDocument = { selectionSet: { kind: "SelectionSet", selections: [ + { kind: "Field", name: { kind: "Name", value: "__typename" } }, { kind: "InlineFragment", typeCondition: { @@ -1432,6 +1161,385 @@ export const AddEmailDocument = { }, ], } as unknown as DocumentNode; +export const BrowserSessionListDocument = { + kind: "Document", + definitions: [ + { + kind: "OperationDefinition", + operation: "query", + name: { kind: "Name", value: "BrowserSessionList" }, + variableDefinitions: [ + { + kind: "VariableDefinition", + variable: { + kind: "Variable", + name: { kind: "Name", value: "userId" }, + }, + type: { + kind: "NonNullType", + type: { kind: "NamedType", name: { kind: "Name", value: "ID" } }, + }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "user" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "id" }, + value: { + kind: "Variable", + name: { kind: "Name", value: "userId" }, + }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { + kind: "Field", + name: { kind: "Name", value: "browserSessions" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "first" }, + value: { kind: "IntValue", value: "10" }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "edges" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "cursor" }, + }, + { + kind: "Field", + name: { kind: "Name", value: "node" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "id" }, + }, + { + kind: "FragmentSpread", + name: { + kind: "Name", + value: "BrowserSession_session", + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + { + kind: "FragmentDefinition", + name: { kind: "Name", value: "BrowserSession_session" }, + typeCondition: { + kind: "NamedType", + name: { kind: "Name", value: "BrowserSession" }, + }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { kind: "Field", name: { kind: "Name", value: "createdAt" } }, + { + kind: "Field", + name: { kind: "Name", value: "lastAuthentication" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { kind: "Field", name: { kind: "Name", value: "createdAt" } }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode< + BrowserSessionListQuery, + BrowserSessionListQueryVariables +>; +export const CompatSsoLoginListDocument = { + kind: "Document", + definitions: [ + { + kind: "OperationDefinition", + operation: "query", + name: { kind: "Name", value: "CompatSsoLoginList" }, + variableDefinitions: [ + { + kind: "VariableDefinition", + variable: { + kind: "Variable", + name: { kind: "Name", value: "userId" }, + }, + type: { + kind: "NonNullType", + type: { kind: "NamedType", name: { kind: "Name", value: "ID" } }, + }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "user" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "id" }, + value: { + kind: "Variable", + name: { kind: "Name", value: "userId" }, + }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { + kind: "Field", + name: { kind: "Name", value: "compatSsoLogins" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "first" }, + value: { kind: "IntValue", value: "10" }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "edges" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "node" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "id" }, + }, + { + kind: "FragmentSpread", + name: { + kind: "Name", + value: "CompatSsoLogin_login", + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + { + kind: "FragmentDefinition", + name: { kind: "Name", value: "CompatSsoLogin_login" }, + typeCondition: { + kind: "NamedType", + name: { kind: "Name", value: "CompatSsoLogin" }, + }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { kind: "Field", name: { kind: "Name", value: "redirectUri" } }, + { kind: "Field", name: { kind: "Name", value: "createdAt" } }, + { + kind: "Field", + name: { kind: "Name", value: "session" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { kind: "Field", name: { kind: "Name", value: "createdAt" } }, + { kind: "Field", name: { kind: "Name", value: "deviceId" } }, + { kind: "Field", name: { kind: "Name", value: "finishedAt" } }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode< + CompatSsoLoginListQuery, + CompatSsoLoginListQueryVariables +>; +export const OAuth2SessionListQueryDocument = { + kind: "Document", + definitions: [ + { + kind: "OperationDefinition", + operation: "query", + name: { kind: "Name", value: "OAuth2SessionListQuery" }, + variableDefinitions: [ + { + kind: "VariableDefinition", + variable: { + kind: "Variable", + name: { kind: "Name", value: "userId" }, + }, + type: { + kind: "NonNullType", + type: { kind: "NamedType", name: { kind: "Name", value: "ID" } }, + }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "user" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "id" }, + value: { + kind: "Variable", + name: { kind: "Name", value: "userId" }, + }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { + kind: "Field", + name: { kind: "Name", value: "oauth2Sessions" }, + arguments: [ + { + kind: "Argument", + name: { kind: "Name", value: "first" }, + value: { kind: "IntValue", value: "10" }, + }, + ], + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "edges" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "cursor" }, + }, + { + kind: "Field", + name: { kind: "Name", value: "node" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "id" }, + }, + { + kind: "FragmentSpread", + name: { + kind: "Name", + value: "OAuth2Session_session", + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + { + kind: "FragmentDefinition", + name: { kind: "Name", value: "OAuth2Session_session" }, + typeCondition: { + kind: "NamedType", + name: { kind: "Name", value: "Oauth2Session" }, + }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { kind: "Field", name: { kind: "Name", value: "scope" } }, + { + kind: "Field", + name: { kind: "Name", value: "client" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { kind: "Field", name: { kind: "Name", value: "clientId" } }, + { kind: "Field", name: { kind: "Name", value: "clientName" } }, + { kind: "Field", name: { kind: "Name", value: "clientUri" } }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode< + OAuth2SessionListQueryQuery, + OAuth2SessionListQueryQueryVariables +>; export const UserEmailListQueryDocument = { kind: "Document", definitions: [ @@ -1634,17 +1742,20 @@ export const UserEmailListQueryDocument = { UserEmailListQueryQuery, UserEmailListQueryQueryVariables >; -export const AccountQueryDocument = { +export const UserGreetingDocument = { kind: "Document", definitions: [ { kind: "OperationDefinition", operation: "query", - name: { kind: "Name", value: "AccountQuery" }, + name: { kind: "Name", value: "UserGreeting" }, variableDefinitions: [ { kind: "VariableDefinition", - variable: { kind: "Variable", name: { kind: "Name", value: "id" } }, + variable: { + kind: "Variable", + name: { kind: "Name", value: "userId" }, + }, type: { kind: "NonNullType", type: { kind: "NamedType", name: { kind: "Name", value: "ID" } }, @@ -1663,7 +1774,7 @@ export const AccountQueryDocument = { name: { kind: "Name", value: "id" }, value: { kind: "Variable", - name: { kind: "Name", value: "id" }, + name: { kind: "Name", value: "userId" }, }, }, ], @@ -1679,7 +1790,7 @@ export const AccountQueryDocument = { }, }, ], -} as unknown as DocumentNode; +} as unknown as DocumentNode; export const BrowserSessionQueryDocument = { kind: "Document", definitions: [ @@ -1757,328 +1868,6 @@ export const BrowserSessionQueryDocument = { BrowserSessionQueryQuery, BrowserSessionQueryQueryVariables >; -export const HomeQueryDocument = { - kind: "Document", - definitions: [ - { - kind: "OperationDefinition", - operation: "query", - name: { kind: "Name", value: "HomeQuery" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "currentBrowserSession" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { - kind: "Field", - name: { kind: "Name", value: "user" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { - kind: "Field", - name: { kind: "Name", value: "username" }, - }, - { - kind: "FragmentSpread", - name: { - kind: "Name", - value: "CompatSsoLoginList_user", - }, - }, - { - kind: "FragmentSpread", - name: { - kind: "Name", - value: "BrowserSessionList_user", - }, - }, - { - kind: "FragmentSpread", - name: { kind: "Name", value: "OAuth2SessionList_user" }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "CompatSsoLogin_login" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "CompatSsoLogin" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "redirectUri" } }, - { kind: "Field", name: { kind: "Name", value: "createdAt" } }, - { - kind: "Field", - name: { kind: "Name", value: "session" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "createdAt" } }, - { kind: "Field", name: { kind: "Name", value: "deviceId" } }, - { kind: "Field", name: { kind: "Name", value: "finishedAt" } }, - ], - }, - }, - ], - }, - }, - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "BrowserSession_session" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "BrowserSession" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "createdAt" } }, - { - kind: "Field", - name: { kind: "Name", value: "lastAuthentication" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "createdAt" } }, - ], - }, - }, - ], - }, - }, - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "OAuth2Session_session" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "Oauth2Session" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "scope" } }, - { - kind: "Field", - name: { kind: "Name", value: "client" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { kind: "Field", name: { kind: "Name", value: "id" } }, - { kind: "Field", name: { kind: "Name", value: "clientId" } }, - { kind: "Field", name: { kind: "Name", value: "clientName" } }, - { kind: "Field", name: { kind: "Name", value: "clientUri" } }, - ], - }, - }, - ], - }, - }, - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "CompatSsoLoginList_user" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "User" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "compatSsoLogins" }, - arguments: [ - { - kind: "Argument", - name: { kind: "Name", value: "first" }, - value: { kind: "IntValue", value: "10" }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "edges" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "node" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "id" }, - }, - { - kind: "FragmentSpread", - name: { - kind: "Name", - value: "CompatSsoLogin_login", - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "BrowserSessionList_user" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "User" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "browserSessions" }, - arguments: [ - { - kind: "Argument", - name: { kind: "Name", value: "first" }, - value: { kind: "IntValue", value: "10" }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "edges" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "cursor" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "node" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "id" }, - }, - { - kind: "FragmentSpread", - name: { - kind: "Name", - value: "BrowserSession_session", - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - { - kind: "FragmentDefinition", - name: { kind: "Name", value: "OAuth2SessionList_user" }, - typeCondition: { - kind: "NamedType", - name: { kind: "Name", value: "User" }, - }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "oauth2Sessions" }, - arguments: [ - { - kind: "Argument", - name: { kind: "Name", value: "first" }, - value: { kind: "IntValue", value: "10" }, - }, - ], - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "edges" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "cursor" }, - }, - { - kind: "Field", - name: { kind: "Name", value: "node" }, - selectionSet: { - kind: "SelectionSet", - selections: [ - { - kind: "Field", - name: { kind: "Name", value: "id" }, - }, - { - kind: "FragmentSpread", - name: { - kind: "Name", - value: "OAuth2Session_session", - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], - }, - }, - ], -} as unknown as DocumentNode; export const OAuth2ClientQueryDocument = { kind: "Document", definitions: [ diff --git a/frontend/src/graphql.ts b/frontend/src/graphql.ts index fd2745a9..09c71aeb 100644 --- a/frontend/src/graphql.ts +++ b/frontend/src/graphql.ts @@ -43,8 +43,6 @@ const cache = cacheExchange({ export const client = createClient({ url: "/graphql", - // XXX: else queries don't refetch on cache invalidation for some reason - requestPolicy: "cache-and-network", exchanges: import.meta.env.DEV ? [devtoolsExchange, cache, fetchExchange] : [cache, fetchExchange], diff --git a/frontend/src/pages/Account.tsx b/frontend/src/pages/Account.tsx index 72d7e74a..fa06f68b 100644 --- a/frontend/src/pages/Account.tsx +++ b/frontend/src/pages/Account.tsx @@ -22,26 +22,12 @@ import UserEmailList from "../components/UserEmailList"; import { Title } from "../components/Typography"; import AddEmailForm from "../components/AddEmailForm"; import { currentUserIdAtom } from "../atoms"; - -const QUERY = graphql(/* GraphQL */ ` - query AccountQuery($id: ID!) { - user(id: $id) { - id - username - } - } -`); - -const accountAtomFamily = atomFamily((id: string) => - atomWithQuery({ query: QUERY, getVariables: () => ({ id }) }) -); +import UserGreeting from "../components/UserGreeting"; const UserAccount: React.FC<{ id: string }> = ({ id }) => { - const result = useAtomValue(accountAtomFamily(id)); - return (
- Hello {result.data?.user?.username} +
diff --git a/frontend/src/pages/BrowserSession.tsx b/frontend/src/pages/BrowserSession.tsx index a5a5ca94..50645ba9 100644 --- a/frontend/src/pages/BrowserSession.tsx +++ b/frontend/src/pages/BrowserSession.tsx @@ -16,6 +16,7 @@ import { useAtomValue } from "jotai"; import { atomWithQuery } from "jotai-urql"; import { useMemo } from "react"; import { graphql } from "../gql"; +import { atomFamily } from "jotai/utils"; const QUERY = graphql(/* GraphQL */ ` query BrowserSessionQuery($id: ID!) { @@ -34,25 +35,27 @@ const QUERY = graphql(/* GraphQL */ ` } `); -const BrowserSession: React.FC<{ id: string }> = ({ id }) => { - const result = useAtomValue( - useMemo( - () => atomWithQuery({ query: QUERY, getVariables: () => ({ id }) }), - [id] - ) - ); +const browserSessionFamily = atomFamily((id: string) => { + const browserSessionAtom = atomWithQuery({ + query: QUERY, + getVariables: () => ({ id }), + }); - if (result.error) { - throw result.error; + return browserSessionAtom; +}); + +const BrowserSession: React.FC<{ id: string }> = ({ id }) => { + const result = useAtomValue(browserSessionFamily(id)); + + if (result.data?.browserSession) { + return ( +
+        {JSON.stringify(result.data.browserSession, null, 2)}
+      
+ ); } - const data = result.data!!; - - return ( -
-      {JSON.stringify(data.browserSession, null, 2)}
-    
- ); + return <>Failed to load browser session; }; export default BrowserSession; diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx index 37e84955..f2266871 100644 --- a/frontend/src/pages/Home.tsx +++ b/frontend/src/pages/Home.tsx @@ -20,48 +20,20 @@ import CompatSsoLoginList from "../components/CompatSsoLoginList"; import OAuth2SessionList from "../components/OAuth2SessionList"; import Typography from "../components/Typography"; import { graphql } from "../gql"; - -const QUERY = graphql(/* GraphQL */ ` - query HomeQuery { - # eslint-disable-next-line @graphql-eslint/no-deprecated - currentBrowserSession { - id - user { - id - username - - ...CompatSsoLoginList_user - ...BrowserSessionList_user - ...OAuth2SessionList_user - } - } - } -`); - -const homeDataAtom = atomWithQuery({ - query: QUERY, -}); +import { currentUserIdAtom } from "../atoms"; +import UserGreeting from "../components/UserGreeting"; const Home: React.FC = () => { - const result = useAtomValue(homeDataAtom); - - if (result.error) { - throw result.error; - } - - const data = result.data!!; - - if (data.currentBrowserSession) { - const session = data.currentBrowserSession; - const user = session.user; + const currentUserId = useAtomValue(currentUserIdAtom); + if (currentUserId) { return ( <> - Hello {user.username}! +
- - - + + +
); diff --git a/frontend/src/pages/OAuth2Client.tsx b/frontend/src/pages/OAuth2Client.tsx index 1c683af3..e5686cfb 100644 --- a/frontend/src/pages/OAuth2Client.tsx +++ b/frontend/src/pages/OAuth2Client.tsx @@ -16,6 +16,7 @@ import { useAtomValue } from "jotai"; import { useMemo } from "react"; import { atomWithQuery } from "jotai-urql"; import { graphql } from "../gql"; +import { atomFamily } from "jotai/utils"; const QUERY = graphql(/* GraphQL */ ` query OAuth2ClientQuery($id: ID!) { @@ -31,25 +32,27 @@ const QUERY = graphql(/* GraphQL */ ` } `); -const OAuth2Client: React.FC<{ id: string }> = ({ id }) => { - const result = useAtomValue( - useMemo( - () => atomWithQuery({ query: QUERY, getVariables: () => ({ id }) }), - [id] - ) - ); +const oauth2ClientFamily = atomFamily((id: string) => { + const oauth2ClientAtom = atomWithQuery({ + query: QUERY, + getVariables: () => ({ id }), + }); - if (result.error) { - throw result.error; + return oauth2ClientAtom; +}); + +const OAuth2Client: React.FC<{ id: string }> = ({ id }) => { + const result = useAtomValue(oauth2ClientFamily(id)); + + if (result.data?.oauth2Client) { + return ( +
+        {JSON.stringify(result.data.oauth2Client, null, 2)}
+      
+ ); } - const data = result.data!!; - - return ( -
-      {JSON.stringify(data.oauth2Client, null, 2)}
-    
- ); + return <>Failed to load OAuth2 client; }; export default OAuth2Client;