feat: adds a POST endpoint for response creation in management apis (#2652)

Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
Anshuman Pandey
2024-05-23 19:46:57 +05:30
committed by GitHub
parent 4544cba858
commit 223937adcc
3 changed files with 102 additions and 22 deletions

View File

@@ -1,10 +1,12 @@
import { authenticateRequest } from "@/app/api/v1/auth";
import { responses } from "@/app/lib/api/response";
import { transformErrorToDetails } from "@/app/lib/api/validator";
import { NextRequest } from "next/server";
import { getResponses, getResponsesByEnvironmentId } from "@formbricks/lib/response/service";
import { DatabaseError } from "@formbricks/types/errors";
import { TResponse } from "@formbricks/types/responses";
import { createResponse, getResponses, getResponsesByEnvironmentId } from "@formbricks/lib/response/service";
import { getSurvey } from "@formbricks/lib/survey/service";
import { DatabaseError, InvalidInputError } from "@formbricks/types/errors";
import { TResponse, ZResponseInput } from "@formbricks/types/responses";
export const GET = async (request: NextRequest) => {
const searchParams = request.nextUrl.searchParams;
@@ -30,3 +32,76 @@ export const GET = async (request: NextRequest) => {
throw error;
}
};
export const POST = async (request: Request): Promise<Response> => {
try {
const authentication = await authenticateRequest(request);
if (!authentication) return responses.notAuthenticatedResponse();
const environmentId = authentication.environmentId;
let jsonInput;
try {
jsonInput = await request.json();
} catch (err) {
console.error(`Error parsing JSON input: ${err}`);
return responses.badRequestResponse("Malformed JSON input, please check your request body");
}
// add environmentId to response
jsonInput.environmentId = environmentId;
const inputValidation = ZResponseInput.safeParse(jsonInput);
if (!inputValidation.success) {
return responses.badRequestResponse(
"Fields are missing or incorrectly formatted",
transformErrorToDetails(inputValidation.error),
true
);
}
const responseInput = inputValidation.data;
// get and check survey
const survey = await getSurvey(responseInput.surveyId);
if (!survey) {
return responses.notFoundResponse("Survey", responseInput.surveyId, true);
}
if (survey.environmentId !== environmentId) {
return responses.badRequestResponse(
"Survey is part of another environment",
{
"survey.environmentId": survey.environmentId,
environmentId,
},
true
);
}
// if there is a createdAt but no updatedAt, set updatedAt to createdAt
if (responseInput.createdAt && !responseInput.updatedAt) {
responseInput.updatedAt = responseInput.createdAt;
}
let response: TResponse;
try {
response = await createResponse(inputValidation.data);
} catch (error) {
if (error instanceof InvalidInputError) {
return responses.badRequestResponse(error.message);
} else {
console.error(error);
return responses.internalServerErrorResponse(error.message);
}
}
return responses.successResponse(response, true);
} catch (error) {
if (error instanceof DatabaseError) {
return responses.badRequestResponse(error.message);
}
throw error;
}
};

View File

@@ -203,6 +203,7 @@ export const createResponse = async (responseInput: TResponseInput): Promise<TRe
singleUseId,
ttc: initialTtc,
} = responseInput;
try {
let person: TPerson | null = null;
let attributes: TAttributes | null = null;
@@ -221,28 +222,30 @@ export const createResponse = async (responseInput: TResponseInput): Promise<TRe
const ttc = initialTtc ? (finished ? calculateTtcTotal(initialTtc) : initialTtc) : {};
const responsePrisma = await prisma.response.create({
data: {
survey: {
const prismaData: Prisma.ResponseCreateInput = {
survey: {
connect: {
id: surveyId,
},
},
finished: finished,
data: data,
language: language,
...(person?.id && {
person: {
connect: {
id: surveyId,
id: person.id,
},
},
finished: finished,
data: data,
language: language,
...(person?.id && {
person: {
connect: {
id: person.id,
},
},
personAttributes: attributes,
}),
...(meta && ({ meta } as Prisma.JsonObject)),
singleUseId,
ttc: ttc,
},
personAttributes: attributes,
}),
...(meta && ({ meta } as Prisma.JsonObject)),
singleUseId,
ttc: ttc,
};
const responsePrisma = await prisma.response.create({
data: prismaData,
select: responseSelection,
});

View File

@@ -238,6 +238,8 @@ export const ZResponse = z.object({
export type TResponse = z.infer<typeof ZResponse>;
export const ZResponseInput = z.object({
createdAt: z.coerce.date().optional(),
updatedAt: z.coerce.date().optional(),
environmentId: z.string().cuid2(),
surveyId: z.string().cuid2(),
userId: z.string().nullish(),