diff --git a/api.planx.uk/admin/session/summary.test.ts b/api.planx.uk/admin/session/summary.test.ts index fd35686a41..08c7b2b838 100644 --- a/api.planx.uk/admin/session/summary.test.ts +++ b/api.planx.uk/admin/session/summary.test.ts @@ -14,7 +14,7 @@ describe("Session summary admin endpoint", () => { sessionId: "abc123", }, data: { - lowcal_sessions_by_pk: {}, + lowcalSession: {}, }, }); }); diff --git a/api.planx.uk/admin/session/summary.ts b/api.planx.uk/admin/session/summary.ts index d0975c9e0a..344a6c283b 100644 --- a/api.planx.uk/admin/session/summary.ts +++ b/api.planx.uk/admin/session/summary.ts @@ -6,8 +6,8 @@ import { import { NextFunction, Request, Response } from "express"; import { gql } from "graphql-request"; -import { adminGraphQLClient as adminClient } from "../../hasura"; import { Breadcrumb, Flow, LowCalSession, Passport, Team } from "../../types"; +import { $api } from "../../client"; /** * @swagger @@ -28,9 +28,9 @@ export async function getSessionSummary( next: NextFunction, ) { try { - const data = await getSessionSummaryById(req.params.sessionId); - if (data) { - res.send(data); + const session = await getSessionSummaryById(req.params.sessionId); + if (session) { + res.send(session); } else { res.send({ message: `Cannot find data for this session; double-check your sessionId is correct`, @@ -72,11 +72,13 @@ interface SessionSummary { const getSessionSummaryById = async ( sessionId: Session["id"], -): Promise => { - const data = await adminClient.request( +): Promise => { + const { lowcalSession } = await $api.client.request< + Record<"lowcalSession", SessionSummary | null> + >( gql` query GetSessionSummary($sessionId: uuid!) { - lowcal_sessions_by_pk(id: $sessionId) { + lowcalSession: lowcal_sessions_by_pk(id: $sessionId) { flow { id slug @@ -112,5 +114,5 @@ const getSessionSummaryById = async ( }, ); - return data?.lowcal_sessions_by_pk; + return lowcalSession; }; diff --git a/api.planx.uk/editor/copyFlow.test.ts b/api.planx.uk/editor/copyFlow.test.ts index 7cf73cb670..15c683719f 100644 --- a/api.planx.uk/editor/copyFlow.test.ts +++ b/api.planx.uk/editor/copyFlow.test.ts @@ -10,7 +10,7 @@ beforeEach(() => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: mockFlowData, }, }, @@ -20,7 +20,7 @@ beforeEach(() => { name: "InsertFlow", matchOnVariables: false, data: { - insert_flows_one: { + flow: { id: 2, }, }, @@ -30,7 +30,7 @@ beforeEach(() => { name: "InsertOperation", matchOnVariables: false, data: { - insert_operations_one: { + operation: { id: 1, }, }, diff --git a/api.planx.uk/editor/copyPortalAsFlow.test.ts b/api.planx.uk/editor/copyPortalAsFlow.test.ts index 46b84d0268..a13fe8baa5 100644 --- a/api.planx.uk/editor/copyPortalAsFlow.test.ts +++ b/api.planx.uk/editor/copyPortalAsFlow.test.ts @@ -10,7 +10,7 @@ beforeEach(() => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: mockFlowData, }, }, diff --git a/api.planx.uk/editor/findReplace.test.ts b/api.planx.uk/editor/findReplace.test.ts index 8678d8e476..f1ded631ee 100644 --- a/api.planx.uk/editor/findReplace.test.ts +++ b/api.planx.uk/editor/findReplace.test.ts @@ -10,7 +10,7 @@ beforeEach(() => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: mockFlowData, slug: "test", }, @@ -21,7 +21,7 @@ beforeEach(() => { name: "UpdateFlow", matchOnVariables: false, data: { - update_flows_by_pk: { + flow: { data: replacedFlowData, slug: "test", }, diff --git a/api.planx.uk/editor/findReplace.ts b/api.planx.uk/editor/findReplace.ts index 5e5a2a0f93..a0beaae8eb 100644 --- a/api.planx.uk/editor/findReplace.ts +++ b/api.planx.uk/editor/findReplace.ts @@ -1,8 +1,9 @@ import { Flow } from "./../types"; -import { adminGraphQLClient as adminClient } from "../hasura"; import { gql } from "graphql-request"; import { getFlowData } from "../helpers"; import { Request, Response, NextFunction } from "express"; +import { getClient } from "../client"; +import { FlowGraph } from "@opensystemslab/planx-core/types"; interface MatchResult { matches: Flow["data"]; @@ -49,6 +50,15 @@ const getMatches = ( }; }; +interface UpdateFlow { + flow: { + id: string; + slug: string; + data: FlowGraph; + updatedAt: string; + }; +} + /** * @swagger * /flows/{flowId}/search: @@ -136,14 +146,18 @@ const findAndReplaceInFlow = async ( } // if matches, proceed with mutation to update flow data - const response = await adminClient.request( + const { client: $client } = getClient(); + const response = await $client.request( gql` mutation UpdateFlow($data: jsonb = {}, $id: uuid!) { - update_flows_by_pk(pk_columns: { id: $id }, _set: { data: $data }) { + flow: update_flows_by_pk( + pk_columns: { id: $id } + _set: { data: $data } + ) { id slug data - updated_at + updatedAt: updated_at } } `, @@ -153,8 +167,7 @@ const findAndReplaceInFlow = async ( }, ); - const updatedFlow = - response.update_flows_by_pk && response.update_flows_by_pk.data; + const updatedFlow = response.flow && response.flow.data; res.json({ message: `Found ${ diff --git a/api.planx.uk/editor/moveFlow.test.ts b/api.planx.uk/editor/moveFlow.test.ts index f4be83a537..f8d377777e 100644 --- a/api.planx.uk/editor/moveFlow.test.ts +++ b/api.planx.uk/editor/moveFlow.test.ts @@ -26,7 +26,7 @@ beforeEach(() => { team_id: "1", }, data: { - update_flows_by_pk: { + flow: { id: "1", }, }, diff --git a/api.planx.uk/editor/moveFlow.ts b/api.planx.uk/editor/moveFlow.ts index add5717705..0135f81f37 100644 --- a/api.planx.uk/editor/moveFlow.ts +++ b/api.planx.uk/editor/moveFlow.ts @@ -1,7 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { gql } from "graphql-request"; -import { adminGraphQLClient as adminClient } from "../hasura"; import { Flow, Team } from "../types"; +import { $public, getClient } from "../client"; const moveFlow = async ( req: Request, @@ -36,8 +36,12 @@ const moveFlow = async ( } }; +interface GetTeam { + teams: Pick[]; +} + const getTeamIdBySlug = async (slug: Team["slug"]): Promise => { - const data = await adminClient.request( + const data = await $public.client.request( gql` query GetTeam($slug: String!) { teams(where: { slug: { _eq: $slug } }) { @@ -53,14 +57,19 @@ const getTeamIdBySlug = async (slug: Team["slug"]): Promise => { return data?.teams[0].id; }; +interface UpdateFlow { + flow: Pick; +} + const updateFlow = async ( flowId: Flow["id"], teamId: Team["id"], ): Promise => { - const data = await adminClient.request( + const { client: $client } = getClient(); + const { flow } = await $client.request( gql` mutation UpdateFlow($id: uuid!, $team_id: Int!) { - update_flows_by_pk( + flow: update_flows_by_pk( pk_columns: { id: $id } _set: { team_id: $team_id } ) { @@ -74,7 +83,7 @@ const updateFlow = async ( }, ); - return data?.update_flows_by_pk?.id; + return flow.id; }; export { moveFlow }; diff --git a/api.planx.uk/editor/publish.test.ts b/api.planx.uk/editor/publish.test.ts index af840293c7..41f6165887 100644 --- a/api.planx.uk/editor/publish.test.ts +++ b/api.planx.uk/editor/publish.test.ts @@ -1,17 +1,28 @@ import supertest from "supertest"; import { queryMock } from "../tests/graphqlQueryMock"; -import { authHeader } from "../tests/mockJWT"; +import { authHeader, getJWT } from "../tests/mockJWT"; import app from "../server"; import { flowWithInviteToPay } from "../tests/mocks/inviteToPayData"; import { FlowGraph } from "@opensystemslab/planx-core/types"; +import { userContext } from "../modules/auth/middleware"; + +beforeAll(() => { + const getStoreMock = jest.spyOn(userContext, "getStore"); + getStoreMock.mockReturnValue({ + user: { + sub: "123", + jwt: getJWT({ role: "teamEditor" }), + }, + }); +}); beforeEach(() => { queryMock.mockQuery({ name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: mockFlowData, }, }, @@ -21,8 +32,8 @@ beforeEach(() => { name: "GetMostRecentPublishedFlow", matchOnVariables: false, data: { - flows_by_pk: { - published_flows: [ + flow: { + publishedFlows: [ { data: mockFlowData, }, @@ -35,7 +46,7 @@ beforeEach(() => { name: "PublishFlow", matchOnVariables: false, data: { - insert_published_flows_one: { + publishedFlow: { data: mockFlowData, }, }, @@ -89,7 +100,7 @@ describe("publish", () => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: alteredFlow, }, }, @@ -99,7 +110,7 @@ describe("publish", () => { name: "PublishFlow", matchOnVariables: false, data: { - insert_published_flows_one: { + publishedFlow: { data: alteredFlow, }, }, @@ -147,7 +158,7 @@ describe("sections validation on diff", () => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: alteredFlow, }, }, @@ -182,7 +193,7 @@ describe("sections validation on diff", () => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: flowWithSections, }, }, @@ -214,7 +225,7 @@ describe("invite to pay validation on diff", () => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: invalidatedFlow, }, }, @@ -247,7 +258,7 @@ describe("invite to pay validation on diff", () => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: alteredFlow, }, }, @@ -276,7 +287,7 @@ describe("invite to pay validation on diff", () => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: invalidatedFlow, }, }, @@ -307,7 +318,7 @@ describe("invite to pay validation on diff", () => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: invalidFlow, }, }, @@ -340,7 +351,7 @@ describe("invite to pay validation on diff", () => { name: "GetFlowData", matchOnVariables: false, data: { - flows_by_pk: { + flow: { data: invalidatedFlow, }, }, diff --git a/api.planx.uk/editor/publish.ts b/api.planx.uk/editor/publish.ts index 25efd4b81e..ca4d8976f6 100644 --- a/api.planx.uk/editor/publish.ts +++ b/api.planx.uk/editor/publish.ts @@ -1,6 +1,5 @@ import * as jsondiffpatch from "jsondiffpatch"; import { Request, Response, NextFunction } from "express"; -import { adminGraphQLClient as adminClient } from "../hasura"; import { dataMerged, getMostRecentPublishedFlow } from "../helpers"; import { gql } from "graphql-request"; import intersection from "lodash/intersection"; @@ -11,6 +10,7 @@ import { } from "@opensystemslab/planx-core/types"; import { userContext } from "../modules/auth/middleware"; import type { Entry } from "type-fest"; +import { getClient } from "../client"; const validateAndDiffFlow = async ( req: Request, @@ -69,6 +69,16 @@ const validateAndDiffFlow = async ( } }; +interface PublishFlow { + publishedFlow: { + id: string; + flowId: string; + publisherId: string; + createdAt: string; + data: FlowGraph; + }; +} + const publishFlow = async ( req: Request, res: Response, @@ -83,7 +93,8 @@ const publishFlow = async ( if (!userId) throw Error("User details missing from request"); if (delta) { - const response = await adminClient.request( + const { client: $client } = getClient(); + const response = await $client.request( gql` mutation PublishFlow( $data: jsonb = {} @@ -91,7 +102,7 @@ const publishFlow = async ( $publisher_id: Int $summary: String ) { - insert_published_flows_one( + publishedFlow: insert_published_flows_one( object: { data: $data flow_id: $flow_id @@ -100,9 +111,9 @@ const publishFlow = async ( } ) { id - flow_id - publisher_id - created_at + flowId: flow_id + publisherId: publisher_id + createdAt: created_at data } } @@ -116,8 +127,7 @@ const publishFlow = async ( ); const publishedFlow = - response.insert_published_flows_one && - response.insert_published_flows_one.data; + response.publishedFlow && response.publishedFlow.data; const alteredNodes = Object.keys(delta).map((key) => ({ id: key, diff --git a/api.planx.uk/hasura/index.ts b/api.planx.uk/hasura/index.ts deleted file mode 100644 index 0837de56c4..0000000000 --- a/api.planx.uk/hasura/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { GraphQLClient } from "graphql-request"; - -/** - * Connect to Hasura using the "Admin" role - */ -const adminGraphQLClient = new GraphQLClient(process.env.HASURA_GRAPHQL_URL!, { - headers: { - "x-hasura-admin-secret": process.env.HASURA_GRAPHQL_ADMIN_SECRET!, - }, -}); - -export { adminGraphQLClient }; diff --git a/api.planx.uk/helpers.test.ts b/api.planx.uk/helpers.test.ts index 2d10a91201..d862f88a94 100644 --- a/api.planx.uk/helpers.test.ts +++ b/api.planx.uk/helpers.test.ts @@ -1,6 +1,8 @@ import { ComponentType } from "@opensystemslab/planx-core/types"; import { dataMerged, getFormattedEnvironment, isLiveEnv } from "./helpers"; import { queryMock } from "./tests/graphqlQueryMock"; +import { userContext } from "./modules/auth/middleware"; +import { getJWT } from "./tests/mockJWT"; describe("getEnvironment function", () => { const OLD_ENV = process.env; @@ -62,6 +64,14 @@ describe("isLiveEnv() function", () => { }); describe("dataMerged() function", () => { + const getStoreMock = jest.spyOn(userContext, "getStore"); + getStoreMock.mockReturnValue({ + user: { + sub: "123", + jwt: getJWT({ role: "teamEditor" }), + }, + }); + beforeEach(() => { const unflattenedParent = { _root: { @@ -135,7 +145,7 @@ describe("dataMerged() function", () => { id: "child-id", }, data: { - flows_by_pk: { + flow: { slug: "child-flow", data: unflattenedChild, team_id: 123, @@ -149,7 +159,7 @@ describe("dataMerged() function", () => { id: "parent-id", }, data: { - flows_by_pk: { + flow: { slug: "parent-flow", data: unflattenedParent, team_id: 123, diff --git a/api.planx.uk/helpers.ts b/api.planx.uk/helpers.ts index 0ab9bd860c..47e38c9be2 100644 --- a/api.planx.uk/helpers.ts +++ b/api.planx.uk/helpers.ts @@ -1,15 +1,16 @@ import { gql } from "graphql-request"; import { capitalize } from "lodash"; -import { adminGraphQLClient as adminClient } from "./hasura"; import { Flow, Node } from "./types"; import { ComponentType, FlowGraph } from "@opensystemslab/planx-core/types"; +import { $public, getClient } from "./client"; // Get a flow's data (unflattened, without external portal nodes) const getFlowData = async (id: string): Promise => { - const data = await adminClient.request( + const { client: $client } = getClient(); + const { flow } = await $client.request<{ flow: Flow | null }>( gql` query GetFlowData($id: uuid!) { - flows_by_pk(id: $id) { + flow: flows_by_pk(id: $id) { slug data team_id @@ -18,8 +19,9 @@ const getFlowData = async (id: string): Promise => { `, { id }, ); + if (!flow) throw Error(`Unable to get flow with id ${id}`); - return data.flows_by_pk; + return flow; }; // Insert a new flow into the `flows` table @@ -30,7 +32,8 @@ const insertFlow = async ( creatorId?: number, copiedFrom?: Flow["id"], ) => { - const data = await adminClient.request( + const { client: $client } = getClient(); + const data = await $client.request<{ flow: { id: string } }>( gql` mutation InsertFlow( $team_id: Int! @@ -39,7 +42,7 @@ const insertFlow = async ( $creator_id: Int $copied_from: uuid ) { - insert_flows_one( + flow: insert_flows_one( object: { team_id: $team_id slug: $slug @@ -62,16 +65,17 @@ const insertFlow = async ( }, ); - if (data) await createAssociatedOperation(data?.insert_flows_one?.id); - return data?.insert_flows_one; + if (data) await createAssociatedOperation(data?.flow?.id); + return data?.flow; }; // Add a row to `operations` for an inserted flow, otherwise ShareDB throws a silent error when opening the flow in the UI const createAssociatedOperation = async (flowId: Flow["id"]) => { - const data = await adminClient.request( + const { client: $client } = getClient(); + const data = await $client.request<{ operation: { id: string } }>( gql` mutation InsertOperation($flow_id: uuid!, $data: jsonb = {}) { - insert_operations_one( + operation: insert_operations_one( object: { flow_id: $flow_id, version: 1, data: $data } ) { id @@ -83,53 +87,42 @@ const createAssociatedOperation = async (flowId: Flow["id"]) => { }, ); - return data?.insert_operations_one; + return data?.operation; }; +interface PublishedFlows { + flow: { + publishedFlows: { + // TODO: use FlowGraph from planx-core here + data: Flow["data"]; + }[]; + } | null; +} + // Get the most recent version of a published flow's data (flattened, with external portal nodes) const getMostRecentPublishedFlow = async ( id: string, ): Promise => { - const data = await adminClient.request( + const { flow } = await $public.client.request( gql` query GetMostRecentPublishedFlow($id: uuid!) { - flows_by_pk(id: $id) { - published_flows(limit: 1, order_by: { created_at: desc }) { - data - } - } - } - `, - { id }, - ); - - return data.flows_by_pk.published_flows?.[0]?.data; -}; - -// Get the snapshot of the published flow for a certain point in time (flattened, with external portal nodes) -// created_at refers to published date, value passed in as param should be lowcal_session.updated_at -const getPublishedFlowByDate = async (id: string, created_at: string) => { - const data = await adminClient.request( - gql` - query GetPublishedFlowByDate($id: uuid!, $created_at: timestamptz!) { - flows_by_pk(id: $id) { - published_flows( + flow: flows_by_pk(id: $id) { + publishedFlows: published_flows( limit: 1 order_by: { created_at: desc } - where: { created_at: { _lte: $created_at } } ) { data } } } `, - { - id, - created_at, - }, + { id }, ); - return data.flows_by_pk.published_flows?.[0]?.data; + const mostRecent = flow?.publishedFlows?.[0]?.data; + if (!mostRecent) throw Error(`Published flow not found for flow ${id}`); + + return mostRecent; }; // Flatten a flow's data to include main content & portals in a single JSON representation @@ -249,7 +242,6 @@ const getFormattedEnvironment = (): string => { export { getFlowData, getMostRecentPublishedFlow, - getPublishedFlowByDate, dataMerged, getChildren, makeUniqueFlow, diff --git a/api.planx.uk/inviteToPay/createPaymentSendEvents.test.ts b/api.planx.uk/inviteToPay/createPaymentSendEvents.test.ts index b63371afd7..727eb227f8 100644 --- a/api.planx.uk/inviteToPay/createPaymentSendEvents.test.ts +++ b/api.planx.uk/inviteToPay/createPaymentSendEvents.test.ts @@ -38,8 +38,8 @@ describe("Create payment send events webhook", () => { name: "GetMostRecentPublishedFlow", matchOnVariables: false, data: { - flows_by_pk: { - published_flows: [ + flow: { + publishedFlows: [ { data: flowWithInviteToPay, }, diff --git a/api.planx.uk/inviteToPay/paymentRequest.ts b/api.planx.uk/inviteToPay/paymentRequest.ts index e9d35dffd6..39d6321afa 100644 --- a/api.planx.uk/inviteToPay/paymentRequest.ts +++ b/api.planx.uk/inviteToPay/paymentRequest.ts @@ -1,12 +1,27 @@ import { gql } from "graphql-request"; import { NextFunction, Request, Response } from "express"; -import { adminGraphQLClient as client } from "../hasura"; import { ServerError } from "../errors"; import { postPaymentNotificationToSlack, fetchPaymentViaProxyWithCallback, } from "../pay"; import { GovUKPayment } from "@opensystemslab/planx-core/types"; +import { $api } from "../client"; + +interface GetPaymentRequestDetails { + paymentRequest: { + sessionId: string; + paymentAmount: number; + session: { + flowId: string; + flow: { + team: { + slug: string; + }; + }; + }; + } | null; +} // middleware used by routes: // * /payment-request/:paymentRequest/pay @@ -18,11 +33,11 @@ export async function fetchPaymentRequestDetails( ) { const query = gql` query GetPaymentRequestDetails($paymentRequestId: uuid!) { - payment_requests_by_pk(id: $paymentRequestId) { - session_id - payment_amount + paymentRequest: payment_requests_by_pk(id: $paymentRequestId) { + sessionId: session_id + paymentAmount: payment_amount session { - flow_id + flowId: flow_id flow { team { slug @@ -32,10 +47,11 @@ export async function fetchPaymentRequestDetails( } } `; - const { payment_requests_by_pk } = await client.request(query, { - paymentRequestId: req.params.paymentRequest, - }); - if (!payment_requests_by_pk) { + const { paymentRequest } = + await $api.client.request(query, { + paymentRequestId: req.params.paymentRequest, + }); + if (!paymentRequest) { return next( new ServerError({ message: "payment request not found", @@ -43,16 +59,16 @@ export async function fetchPaymentRequestDetails( }), ); } - const sessionId = payment_requests_by_pk.session_id; + const sessionId = paymentRequest.sessionId; if (sessionId) req.query.sessionId = sessionId; - const localAuthority = payment_requests_by_pk.session?.flow?.team?.slug; + const localAuthority = paymentRequest.session?.flow?.team?.slug; if (localAuthority) req.params.localAuthority = localAuthority; - const flowId = payment_requests_by_pk.session?.flow_id; + const flowId = paymentRequest.session?.flowId; if (flowId) req.query.flowId = flowId; - const paymentAmount = payment_requests_by_pk.payment_amount; + const paymentAmount = paymentRequest.paymentAmount.toString(); if (paymentAmount) req.params.paymentAmount = paymentAmount; next(); @@ -109,7 +125,7 @@ export const addGovPayPaymentIdToPaymentRequest = async ( } `; try { - await client.request(query, { + await $api.client.request(query, { paymentRequestId, govPayPaymentId: govUKPayment.payment_id, }); @@ -118,6 +134,15 @@ export const addGovPayPaymentIdToPaymentRequest = async ( } }; +interface MarkPaymentRequestAsPaid { + updatePaymentRequestPaidAt: { + affectedRows: number; + }; + appendGovUKPaymentToSessionData: { + affectedRows: number; + }; +} + export const markPaymentRequestAsPaid = async ( paymentRequestId: string, govUkPayment: GovUKPayment, @@ -147,7 +172,7 @@ export const markPaymentRequestAsPaid = async ( `; try { const { updatePaymentRequestPaidAt, appendGovUKPaymentToSessionData } = - await client.request(query, { + await $api.client.request(query, { paymentRequestId, govUkPayment: { govUkPayment }, }); diff --git a/api.planx.uk/modules/analytics/index.test.ts b/api.planx.uk/modules/analytics/index.test.ts index 8ec20b9d44..2c8d4df4b7 100644 --- a/api.planx.uk/modules/analytics/index.test.ts +++ b/api.planx.uk/modules/analytics/index.test.ts @@ -34,8 +34,8 @@ describe("Logging analytics", () => { user_exit: true, }, data: { - update_analytics_logs_by_pk: { - analytics_id: 12345, + analyticsLog: { + analyticsId: 12345, }, }, }); @@ -57,8 +57,8 @@ describe("Logging analytics", () => { user_exit: false, }, data: { - update_analytics_logs_by_pk: { - analytics_id: 12345, + analyticsLog: { + analyticsId: 12345, }, }, }); @@ -77,8 +77,8 @@ describe("Logging analytics", () => { name: "UpdateAnalyticsLogUserExit", matchOnVariables: false, data: { - update_analytics_logs_by_pk: { - analytics_id: 12345, + analyticsLogs: { + analyticsId: 12345, }, }, graphqlErrors: [ diff --git a/api.planx.uk/modules/analytics/service.ts b/api.planx.uk/modules/analytics/service.ts index 01018a2eb7..9defd29fc5 100644 --- a/api.planx.uk/modules/analytics/service.ts +++ b/api.planx.uk/modules/analytics/service.ts @@ -1,5 +1,13 @@ import { gql } from "graphql-request"; -import { adminGraphQLClient as adminClient } from "../../hasura"; +import { $public } from "../../client"; + +interface UpdateAnalyticsLogUserExit { + analyticsLog: { + id: string; + userExit: boolean; + analyticsId: string; + }; +} export const trackAnalyticsLogExit = async ({ id, @@ -9,16 +17,16 @@ export const trackAnalyticsLogExit = async ({ isUserExit: boolean; }) => { try { - const result = await adminClient.request( + const result = await $public.client.request( gql` mutation UpdateAnalyticsLogUserExit($id: bigint!, $user_exit: Boolean) { - update_analytics_logs_by_pk( + analyticsLog: update_analytics_logs_by_pk( pk_columns: { id: $id } _set: { user_exit: $user_exit } ) { id - user_exit - analytics_id + userExit: user_exit + analyticsId: analytics_id } } `, @@ -28,8 +36,8 @@ export const trackAnalyticsLogExit = async ({ }, ); - const analyticsId = result.update_analytics_logs_by_pk.analytics_id; - await adminClient.request( + const analyticsId = result.analyticsLog.analyticsId; + await $public.client.request( gql` mutation SetAnalyticsEndedDate($id: bigint!, $ended_at: timestamptz) { update_analytics_by_pk( diff --git a/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/mocks/queries.ts b/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/mocks/queries.ts index ea4a041122..73be6c851a 100644 --- a/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/mocks/queries.ts +++ b/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/mocks/queries.ts @@ -4,7 +4,7 @@ export const mockSanitiseLowcalSessionsMutation = { name: "SanitiseLowcalSessions", matchOnVariables: false, data: { - update_lowcal_sessions: { + sessions: { returning: mockIds, }, }, @@ -14,7 +14,7 @@ export const mockSanitiseUniformApplicationsMutation = { name: "SanitiseUniformApplications", matchOnVariables: false, data: { - update_uniform_applications: { + uniformApplications: { returning: mockIds, }, }, @@ -24,7 +24,7 @@ export const mockSanitiseBOPSApplicationsMutation = { name: "SanitiseBOPSApplications", matchOnVariables: false, data: { - update_bops_applications: { + bopsApplications: { returning: mockIds, }, }, @@ -34,7 +34,7 @@ export const mockSanitiseEmailApplicationsMutation = { name: "SanitiseEmailApplications", matchOnVariables: false, data: { - update_email_applications: { + emailApplications: { returning: mockIds, }, }, @@ -44,7 +44,7 @@ export const mockDeleteReconciliationRequestsMutation = { name: "DeleteReconciliationRequests", matchOnVariables: false, data: { - delete_reconciliation_requests: { + reconciliationRequests: { returning: mockIds, }, }, @@ -54,7 +54,7 @@ export const mockDeletePaymentRequests = { name: "DeletePaymentRequests", matchOnVariables: false, data: { - delete_payment_requests: { + paymentRequests: { returning: mockIds, }, }, diff --git a/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/operations.test.ts b/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/operations.test.ts index eba539c049..c6d77a547b 100644 --- a/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/operations.test.ts +++ b/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/operations.test.ts @@ -29,12 +29,25 @@ jest.mock("../../../../hasura/schema"); const mockRunSQL = runSQL as jest.MockedFunction; const mockFindSession = jest.fn(); -jest.mock("../../../../client", () => { + +jest.mock("@opensystemslab/planx-core", () => { + const actualCoreDomainClient = jest.requireActual( + "@opensystemslab/planx-core", + ).CoreDomainClient; + + const actualPassport = jest.requireActual( + "@opensystemslab/planx-core", + ).Passport; + return { - $api: { - session: { - find: jest.fn().mockImplementation(() => mockFindSession()), - }, + Passport: actualPassport, + CoreDomainClient: class extends actualCoreDomainClient { + constructor() { + super(); + this.session.find = jest + .fn() + .mockImplementation(() => mockFindSession()); + } }, }; }); diff --git a/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/operations.ts b/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/operations.ts index 31d29ed578..b3c19658fd 100644 --- a/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/operations.ts +++ b/api.planx.uk/modules/webhooks/service/sanitiseApplicationData/operations.ts @@ -1,11 +1,11 @@ import { gql } from "graphql-request"; import { subMonths } from "date-fns"; -import { Operation, OperationResult } from "./types"; -import { adminGraphQLClient } from "../../../../hasura"; +import { Operation, OperationResult, QueryResult } from "./types"; import { runSQL } from "../../../../hasura/schema"; import { getFilesForSession } from "../../../../session/files"; import { deleteFilesByURL } from "../../../../s3/deleteFile"; +import { $api } from "../../../../client"; const RETENTION_PERIOD_MONTHS = 6; export const getRetentionPeriod = () => @@ -78,10 +78,12 @@ export const getExpiredSessionIds = async (): Promise => { `; const { lowcal_sessions: sessions, - }: { lowcal_sessions: Record<"id", string>[] } = - await adminGraphQLClient.request(query, { + }: { lowcal_sessions: Record<"id", string>[] } = await $api.client.request( + query, + { retentionPeriod: getRetentionPeriod(), - }); + }, + ); const sessionIds = sessions.map((session) => session.id); return sessionIds; }; @@ -105,10 +107,12 @@ export const deleteApplicationFiles: Operation = async () => { return deletedFiles; }; +type Result = { returning: QueryResult }; + export const sanitiseLowcalSessions: Operation = async () => { const mutation = gql` mutation SanitiseLowcalSessions($retentionPeriod: timestamptz) { - update_lowcal_sessions( + sessions: update_lowcal_sessions( _set: { data: {}, email: "", sanitised_at: "now()" } where: { sanitised_at: { _is_null: true } @@ -125,8 +129,8 @@ export const sanitiseLowcalSessions: Operation = async () => { } `; const { - update_lowcal_sessions: { returning: result }, - } = await adminGraphQLClient.request(mutation, { + sessions: { returning: result }, + } = await $api.client.request<{ sessions: Result }>(mutation, { retentionPeriod: getRetentionPeriod(), }); return result; @@ -135,7 +139,7 @@ export const sanitiseLowcalSessions: Operation = async () => { export const sanitiseUniformApplications: Operation = async () => { const mutation = gql` mutation SanitiseUniformApplications($retentionPeriod: timestamptz) { - update_uniform_applications( + uniformApplications: update_uniform_applications( _set: { payload: null, sanitised_at: "now()" } where: { sanitised_at: { _is_null: true } @@ -149,8 +153,8 @@ export const sanitiseUniformApplications: Operation = async () => { } `; const { - update_uniform_applications: { returning: result }, - } = await adminGraphQLClient.request(mutation, { + uniformApplications: { returning: result }, + } = await $api.client.request<{ uniformApplications: Result }>(mutation, { retentionPeriod: getRetentionPeriod(), }); return result; @@ -159,7 +163,7 @@ export const sanitiseUniformApplications: Operation = async () => { export const sanitiseBOPSApplications: Operation = async () => { const mutation = gql` mutation SanitiseBOPSApplications($retentionPeriod: timestamptz) { - update_bops_applications( + bopsApplications: update_bops_applications( _set: { request: {}, sanitised_at: "now()" } where: { sanitised_at: { _is_null: true } @@ -173,8 +177,8 @@ export const sanitiseBOPSApplications: Operation = async () => { } `; const { - update_bops_applications: { returning: result }, - } = await adminGraphQLClient.request(mutation, { + bopsApplications: { returning: result }, + } = await $api.client.request<{ bopsApplications: Result }>(mutation, { retentionPeriod: getRetentionPeriod(), }); return result; @@ -183,7 +187,7 @@ export const sanitiseBOPSApplications: Operation = async () => { export const sanitiseEmailApplications: Operation = async () => { const mutation = gql` mutation SanitiseEmailApplications($retentionPeriod: timestamptz) { - update_email_applications( + emailApplications: update_email_applications( _set: { request: {}, sanitised_at: "now()" } where: { sanitised_at: { _is_null: true } @@ -197,8 +201,8 @@ export const sanitiseEmailApplications: Operation = async () => { } `; const { - update_email_applications: { returning: result }, - } = await adminGraphQLClient.request(mutation, { + emailApplications: { returning: result }, + } = await $api.client.request<{ emailApplications: Result }>(mutation, { retentionPeriod: getRetentionPeriod(), }); return result; @@ -207,7 +211,7 @@ export const sanitiseEmailApplications: Operation = async () => { export const deleteReconciliationRequests: Operation = async () => { const mutation = gql` mutation DeleteReconciliationRequests($retentionPeriod: timestamptz) { - delete_reconciliation_requests( + reconciliationRequests: delete_reconciliation_requests( where: { created_at: { _lt: $retentionPeriod } } ) { returning { @@ -217,8 +221,8 @@ export const deleteReconciliationRequests: Operation = async () => { } `; const { - delete_reconciliation_requests: { returning: result }, - } = await adminGraphQLClient.request(mutation, { + reconciliationRequests: { returning: result }, + } = await $api.client.request<{ reconciliationRequests: Result }>(mutation, { retentionPeriod: getRetentionPeriod(), }); return result; @@ -227,7 +231,7 @@ export const deleteReconciliationRequests: Operation = async () => { export const deletePaymentRequests: Operation = async () => { const mutation = gql` mutation DeletePaymentRequests($retentionPeriod: timestamptz) { - delete_payment_requests( + paymentRequests: delete_payment_requests( where: { created_at: { _lt: $retentionPeriod } } ) { returning { @@ -237,8 +241,8 @@ export const deletePaymentRequests: Operation = async () => { } `; const { - delete_payment_requests: { returning: result }, - } = await adminGraphQLClient.request(mutation, { + paymentRequests: { returning: result }, + } = await $api.client.request<{ paymentRequests: Result }>(mutation, { retentionPeriod: getRetentionPeriod(), }); return result; diff --git a/api.planx.uk/send/helpers.ts b/api.planx.uk/send/helpers.ts index c9360e88c2..eca20463a5 100644 --- a/api.planx.uk/send/helpers.ts +++ b/api.planx.uk/send/helpers.ts @@ -1,6 +1,6 @@ import { gql } from "graphql-request"; import airbrake from "../airbrake"; -import { adminGraphQLClient } from "../hasura"; +import { $api } from "../client"; export async function logPaymentStatus({ sessionId, @@ -78,7 +78,7 @@ async function insertPaymentStatus({ status: string; amount: number; }): Promise { - const _response = await adminGraphQLClient.request( + const _response = await $api.client.request( gql` mutation InsertPaymentStatus( $flowId: uuid! diff --git a/api.planx.uk/tests/mocks/saveAndReturnMocks.ts b/api.planx.uk/tests/mocks/saveAndReturnMocks.ts index aa0877cd86..4e3828ca70 100644 --- a/api.planx.uk/tests/mocks/saveAndReturnMocks.ts +++ b/api.planx.uk/tests/mocks/saveAndReturnMocks.ts @@ -103,8 +103,8 @@ export const mockNotFoundSession = { export const mockGetMostRecentPublishedFlow = (data: Flow["data"]) => ({ name: "GetMostRecentPublishedFlow", data: { - flows_by_pk: { - published_flows: [ + flow: { + publishedFlows: [ { data, },