From d360c1f7419f8763d834844bc36506d7f32a58bf Mon Sep 17 00:00:00 2001 From: Matti Nannt Date: Thu, 20 Jul 2023 14:44:58 +0200 Subject: [PATCH] Fix legacy sdk endpoints not working with new services (#591) --- .../responses/[responseId]/index.ts | 104 ++++++++++++++++-- .../[environmentId]/responses/index.ts | 100 +++++++++++++++-- packages/lib/services/attributeClass.ts | 7 +- 3 files changed, 185 insertions(+), 26 deletions(-) diff --git a/apps/web/pages/api/v1/client/environments/[environmentId]/responses/[responseId]/index.ts b/apps/web/pages/api/v1/client/environments/[environmentId]/responses/[responseId]/index.ts index 2e9b757261..8311ab4fa7 100644 --- a/apps/web/pages/api/v1/client/environments/[environmentId]/responses/[responseId]/index.ts +++ b/apps/web/pages/api/v1/client/environments/[environmentId]/responses/[responseId]/index.ts @@ -1,9 +1,11 @@ -import { INTERNAL_SECRET, WEBAPP_URL } from "@formbricks/lib/constants"; -import { prisma } from "@formbricks/database"; -import type { NextApiRequest, NextApiResponse } from "next"; -import { TPipelineInput } from "@formbricks/types/v1/pipelines"; -import { updateResponse } from "@formbricks/lib/services/response"; import { sendToPipeline } from "@/lib/pipelines"; +import { prisma } from "@formbricks/database"; +import { INTERNAL_SECRET, WEBAPP_URL } from "@formbricks/lib/constants"; +import { TPerson } from "@formbricks/types/v1/people"; +import { TPipelineInput } from "@formbricks/types/v1/pipelines"; +import { TResponse } from "@formbricks/types/v1/responses"; +import { TTag } from "@formbricks/types/v1/tags"; +import type { NextApiRequest, NextApiResponse } from "next"; export default async function handle(req: NextApiRequest, res: NextApiResponse) { const environmentId = req.query.environmentId?.toString(); @@ -45,7 +47,89 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) ...response.data, }; - const updatedResponse = await updateResponse(responseId, { ...response, data: newResponseData }); + const responsePrisma = await prisma.response.update({ + where: { + id: responseId, + }, + data: { + ...response, + data: newResponseData, + }, + select: { + id: true, + createdAt: true, + updatedAt: true, + surveyId: true, + finished: true, + data: true, + meta: true, + personAttributes: true, + person: { + select: { + id: true, + createdAt: true, + updatedAt: true, + attributes: { + select: { + value: true, + attributeClass: { + select: { + name: true, + }, + }, + }, + }, + }, + }, + notes: { + select: { + id: true, + createdAt: true, + updatedAt: true, + text: true, + user: { + select: { + id: true, + name: true, + }, + }, + }, + }, + tags: { + select: { + tag: { + select: { + id: true, + createdAt: true, + updatedAt: true, + name: true, + environmentId: true, + }, + }, + }, + }, + }, + }); + + const transformPrismaPerson = (person): TPerson => { + const attributes = person.attributes.reduce((acc, attr) => { + acc[attr.attributeClass.name] = attr.value; + return acc; + }, {} as Record); + + return { + id: person.id, + attributes: attributes, + createdAt: person.createdAt, + updatedAt: person.updatedAt, + }; + }; + + const responseData: TResponse = { + ...responsePrisma, + person: responsePrisma.person ? transformPrismaPerson(responsePrisma.person) : null, + tags: responsePrisma.tags.map((tagPrisma: { tag: TTag }) => tagPrisma.tag), + }; // send response update to pipeline // don't await to not block the response @@ -57,9 +141,9 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) body: JSON.stringify({ internalSecret: INTERNAL_SECRET, environmentId, - surveyId: updatedResponse.surveyId, + surveyId: responseData.surveyId, event: "responseUpdated", - response: updatedResponse, + response: responseData, } as TPipelineInput), }); @@ -68,9 +152,9 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) // don't await to not block the response sendToPipeline({ environmentId, - surveyId: updatedResponse.surveyId, + surveyId: responseData.surveyId, event: "responseFinished", - response: updatedResponse, + response: responseData, }); } diff --git a/apps/web/pages/api/v1/client/environments/[environmentId]/responses/index.ts b/apps/web/pages/api/v1/client/environments/[environmentId]/responses/index.ts index ed1a639cbf..fe60f88873 100644 --- a/apps/web/pages/api/v1/client/environments/[environmentId]/responses/index.ts +++ b/apps/web/pages/api/v1/client/environments/[environmentId]/responses/index.ts @@ -1,8 +1,10 @@ import { sendToPipeline } from "@/lib/pipelines"; import { prisma } from "@formbricks/database"; import { capturePosthogEvent } from "@formbricks/lib/posthogServer"; -import { createResponse } from "@formbricks/lib/services/response"; import { captureTelemetry } from "@formbricks/lib/telemetry"; +import { TPerson } from "@formbricks/types/v1/people"; +import { TResponse } from "@formbricks/types/v1/responses"; +import { TTag } from "@formbricks/types/v1/tags"; import type { NextApiRequest, NextApiResponse } from "next"; export default async function handle(req: NextApiRequest, res: NextApiResponse) { @@ -14,7 +16,7 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) // CORS if (req.method === "OPTIONS") { - res.status(200).end(); + return res.status(200).end(); } // POST @@ -76,19 +78,17 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) // find team owner const teamOwnerId = environment.product.team.memberships.find((m) => m.role === "owner")?.userId; - const createBody = { - data: { - survey: { - connect: { - id: surveyId, - }, + const responseInput = { + survey: { + connect: { + id: surveyId, }, - ...response, }, + ...response, }; if (personId) { - createBody.data.person = { + responseInput.data.person = { connect: { id: personId, }, @@ -96,7 +96,85 @@ export default async function handle(req: NextApiRequest, res: NextApiResponse) } // create new response - const responseData = await createResponse(createBody); + const responsePrisma = await prisma.response.create({ + data: { + ...responseInput, + }, + select: { + id: true, + createdAt: true, + updatedAt: true, + surveyId: true, + finished: true, + data: true, + meta: true, + personAttributes: true, + person: { + select: { + id: true, + createdAt: true, + updatedAt: true, + attributes: { + select: { + value: true, + attributeClass: { + select: { + name: true, + }, + }, + }, + }, + }, + }, + notes: { + select: { + id: true, + createdAt: true, + updatedAt: true, + text: true, + user: { + select: { + id: true, + name: true, + }, + }, + }, + }, + tags: { + select: { + tag: { + select: { + id: true, + createdAt: true, + updatedAt: true, + name: true, + environmentId: true, + }, + }, + }, + }, + }, + }); + + const transformPrismaPerson = (person): TPerson => { + const attributes = person.attributes.reduce((acc, attr) => { + acc[attr.attributeClass.name] = attr.value; + return acc; + }, {} as Record); + + return { + id: person.id, + attributes: attributes, + createdAt: person.createdAt, + updatedAt: person.updatedAt, + }; + }; + + const responseData: TResponse = { + ...responsePrisma, + person: responsePrisma.person ? transformPrismaPerson(responsePrisma.person) : null, + tags: responsePrisma.tags.map((tagPrisma: { tag: TTag }) => tagPrisma.tag), + }; // send response to pipeline // don't await to not block the response diff --git a/packages/lib/services/attributeClass.ts b/packages/lib/services/attributeClass.ts index cf727686ae..0e77dc5c95 100644 --- a/packages/lib/services/attributeClass.ts +++ b/packages/lib/services/attributeClass.ts @@ -1,6 +1,5 @@ "use server"; -import 'server-only' - +import "server-only"; import { prisma } from "@formbricks/database"; import { DatabaseError } from "@formbricks/errors"; import { TAttributeClass } from "@formbricks/types/v1/attributeClasses"; @@ -55,8 +54,6 @@ export const updatetAttributeClass = async ( return transformedAttributeClass; } catch (error) { - throw new DatabaseError( - `Database error when updating attribute class with id ${attributeClassId}` - ); + throw new DatabaseError(`Database error when updating attribute class with id ${attributeClassId}`); } };