From 8d5bd051a18fb7e982f570930c3bea2542730293 Mon Sep 17 00:00:00 2001 From: Andrew Bastin Date: Wed, 6 Oct 2021 19:31:16 +0530 Subject: [PATCH] refactor: extract cache info to separate files and add more mutations --- .../helpers/backend/GQLClient.ts | 92 +---------- .../helpers/backend/caching/keys.ts | 7 + .../helpers/backend/caching/optimistic.ts | 13 ++ .../helpers/backend/caching/updates.ts | 147 ++++++++++++++++++ .../helpers/backend/mutations/Team.ts | 95 +++++++++++ 5 files changed, 268 insertions(+), 86 deletions(-) create mode 100644 packages/hoppscotch-app/helpers/backend/caching/keys.ts create mode 100644 packages/hoppscotch-app/helpers/backend/caching/optimistic.ts create mode 100644 packages/hoppscotch-app/helpers/backend/caching/updates.ts diff --git a/packages/hoppscotch-app/helpers/backend/GQLClient.ts b/packages/hoppscotch-app/helpers/backend/GQLClient.ts index 049fb7de9..5a6c64603 100644 --- a/packages/hoppscotch-app/helpers/backend/GQLClient.ts +++ b/packages/hoppscotch-app/helpers/backend/GQLClient.ts @@ -25,7 +25,9 @@ import * as TE from "fp-ts/TaskEither" import { pipe, constVoid } from "fp-ts/function" import { subscribe } from "wonka" import clone from "lodash/clone" -import gql from "graphql-tag" +import { keyDefs } from "./caching/keys" +import { optimisticDefs } from "./caching/optimistic" +import { updatesDef } from "./caching/updates" import { getAuthIDToken, probableUser$, @@ -49,91 +51,9 @@ const client = createClient({ dedupExchange, // TODO: Extract this outttttttt offlineExchange({ - keys: { - User: (data) => (data as any).uid, - TeamMember: (data) => (data as any).membershipID, - Team: (data) => data.id as any, - }, - optimistic: { - deleteTeam: () => true, - leaveTeam: () => true, - }, - updates: { - Mutation: { - deleteTeam: (_r, { teamID }, cache, _info) => { - cache.updateQuery( - { - query: gql` - query { - myTeams { - id - } - } - `, - }, - (data: any) => { - console.log(data) - data.myTeams = (data as any).myTeams.filter( - (x: any) => x.id !== teamID - ) - - return data - } - ) - - cache.invalidate({ - __typename: "Team", - id: teamID as any, - }) - }, - leaveTeam: (_r, { teamID }, cache, _info) => { - cache.updateQuery( - { - query: gql` - query { - myTeams { - id - } - } - `, - }, - (data: any) => { - console.log(data) - data.myTeams = (data as any).myTeams.filter( - (x: any) => x.id !== teamID - ) - - return data - } - ) - - cache.invalidate({ - __typename: "Team", - id: teamID as any, - }) - }, - createTeam: (result, _args, cache, _info) => { - cache.updateQuery( - { - query: gql` - { - myTeams { - id - } - } - `, - }, - (data: any) => { - console.log(result) - console.log(data) - - data.myTeams.push(result.createTeam) - return data - } - ) - }, - }, - }, + keys: keyDefs, + optimistic: optimisticDefs, + updates: updatesDef, storage, }), authExchange({ diff --git a/packages/hoppscotch-app/helpers/backend/caching/keys.ts b/packages/hoppscotch-app/helpers/backend/caching/keys.ts new file mode 100644 index 000000000..41f3d4626 --- /dev/null +++ b/packages/hoppscotch-app/helpers/backend/caching/keys.ts @@ -0,0 +1,7 @@ +import { KeyingConfig } from "@urql/exchange-graphcache"; + +export const keyDefs: KeyingConfig = { + User: (data) => (data as any).uid, + TeamMember: (data) => (data as any).membershipID, + Team: (data) => data.id as any, +} \ No newline at end of file diff --git a/packages/hoppscotch-app/helpers/backend/caching/optimistic.ts b/packages/hoppscotch-app/helpers/backend/caching/optimistic.ts new file mode 100644 index 000000000..4f06fb063 --- /dev/null +++ b/packages/hoppscotch-app/helpers/backend/caching/optimistic.ts @@ -0,0 +1,13 @@ +import { OptimisticMutationConfig } from "@urql/exchange-graphcache" + +export const optimisticDefs: OptimisticMutationConfig = { + deleteTeam: () => true, + leaveTeam: () => true, + renameTeam: ({ teamID, newName }) => ({ + __typename: "Team", + id: teamID, + name: newName, + }), + removeTeamMember: () => true, + // TODO: updateTeamMemberRole +} diff --git a/packages/hoppscotch-app/helpers/backend/caching/updates.ts b/packages/hoppscotch-app/helpers/backend/caching/updates.ts new file mode 100644 index 000000000..b2a0f82b3 --- /dev/null +++ b/packages/hoppscotch-app/helpers/backend/caching/updates.ts @@ -0,0 +1,147 @@ +import { UpdatesConfig } from "@urql/exchange-graphcache" +import gql from "graphql-tag" + +export const updatesDef: Partial = { + Mutation: { + deleteTeam: (_r, { teamID }, cache, _info) => { + cache.updateQuery( + { + query: gql` + query { + myTeams { + id + } + } + `, + }, + (data: any) => { + data.myTeams = (data as any).myTeams.filter( + (x: any) => x.id !== teamID + ) + + return data + } + ) + + cache.invalidate({ + __typename: "Team", + id: teamID as any, + }) + }, + leaveTeam: (_r, { teamID }, cache, _info) => { + cache.updateQuery( + { + query: gql` + query { + myTeams { + id + } + } + `, + }, + (data: any) => { + data.myTeams = (data as any).myTeams.filter( + (x: any) => x.id !== teamID + ) + + return data + } + ) + + cache.invalidate({ + __typename: "Team", + id: teamID as any, + }) + }, + createTeam: (result, _args, cache, _info) => { + cache.updateQuery( + { + query: gql` + { + myTeams { + id + } + } + `, + }, + (data: any) => { + data.myTeams.push(result.createTeam) + return data + } + ) + }, + renameTeam: (_result, { teamID, newName }, cache, _info) => { + cache.updateQuery( + { + query: gql` + query GetTeam($teamID: ID!) { + team(teamID: $teamID) { + id + name + } + } + `, + variables: { + teamID, + }, + }, + (data: any) => { + data.team.name = newName + return data + } + ) + }, + removeTeamMember: (_result, { userUid, teamID }, cache) => { + cache.updateQuery( + { + query: gql` + query GetTeam($teamID: ID!) { + team(teamID: $teamID) { + members { + user { + uid + } + } + } + } + `, + variables: { + teamID, + }, + }, + (data: any) => { + data.team.members = data.team.members.filter( + (x: any) => x.user.uid !== userUid + ) + return data + } + ) + }, + updateTeamMemberRole: (result, { userUid, teamID }, cache) => { + cache.updateQuery( + { + query: gql` + query GetTeam($teamID: ID!) { + team(teamID: $teamID) { + members { + user { + uid + } + } + } + } + `, + variables: { + teamID, + }, + }, + (data: any) => { + data.team.members = data.team.members.map((x: any) => + x.user.uid !== userUid ? x : result + ) + return data + } + ) + }, + }, +} diff --git a/packages/hoppscotch-app/helpers/backend/mutations/Team.ts b/packages/hoppscotch-app/helpers/backend/mutations/Team.ts index 8d23a33cf..480463854 100644 --- a/packages/hoppscotch-app/helpers/backend/mutations/Team.ts +++ b/packages/hoppscotch-app/helpers/backend/mutations/Team.ts @@ -18,6 +18,21 @@ type ExitTeamErrors = type CreateTeamErrors = "team/name_invalid" | "ea/not_invite_or_admin" +type RenameTeamErrors = + | "ea/not_invite_or_admin" + | "team/invalid_id" + | "team/not_required_role" + +type UpdateTeamMemberRoleErrors = + | "ea/not_invite_or_admin" + | "team/invalid_id" + | "team/not_required_role" + +type RemoveTeamMemberErrors = + | "ea/not_invite_or_admin" + | "team/invalid_id" + | "team/not_required_role" + export const createTeam = (name: TeamName) => pipe( runMutation< @@ -85,3 +100,83 @@ export const leaveTeam = (teamID: string) => additionalTypenames: ["Team"], } ) + +export const renameTeam = (teamID: string, newName: TeamName) => + pipe( + runMutation< + { + renameTeam: { + id: string + name: TeamName + } + }, + RenameTeamErrors + >( + gql` + mutation RenameTeam($newName: String!, $teamID: ID!) { + renameTeam(newName: $newName, teamID: $teamID) { + id + name + } + } + `, + { + newName, + teamID, + } + ), + TE.map(({ renameTeam }) => renameTeam) + ) + +export const updateTeamMemberRole = ( + userUid: string, + teamID: string, + newRole: TeamMemberRole +) => + pipe( + runMutation< + { + updateTeamMemberRole: { + membershipID: string + role: TeamMemberRole + } + }, + UpdateTeamMemberRoleErrors + >( + gql` + mutation UpdateTeamMemberRole( + $newRole: TeamMemberRole!, + $userUid: ID!, + teamID: ID! + ) { + updateTeamMemberRole( + newRole: $newRole + userUid: $userUid + teamID: $teamID + ) { + membershipID + role + } + } + `, + { + newRole, + userUid, + teamID, + } + ), + TE.map(({ updateTeamMemberRole }) => updateTeamMemberRole) + ) + +export const removeTeamMember = (userUid: string, teamID: string) => + runMutation( + gql` + mutation RemoveTeamMember($userUid: ID!, $teamID: ID!) { + removeTeamMember(userUid: $userUid, teamID: $teamID) + } + `, + { + userUid, + teamID, + } + )