resolved merge conflicts

This commit is contained in:
Piyush Gupta
2023-10-04 20:55:45 +05:30
37 changed files with 443 additions and 209 deletions

View File

@@ -104,8 +104,8 @@ NEXT_PUBLIC_FORMBRICKS_ONBOARDING_SURVEY_ID=
# Cron Secret
CRON_SECRET=
*/
# Encryption key
# You can use: `openssl rand -base64 16` to generate one
FORMBRICKS_ENCRYPTION_KEY=
FORMBRICKS_ENCRYPTION_KEY=
*/

View File

@@ -11,7 +11,7 @@ import {
getActionCountInLast24Hours,
getActionCountInLast7Days,
getActionCountInLastHour,
} from "@formbricks/lib/services/actions";
} from "@formbricks/lib/action/service";
import { getSurveysByActionClassId } from "@formbricks/lib/survey/service";
import { AuthorizationError } from "@formbricks/types/v1/errors";

View File

@@ -5,7 +5,7 @@ import type { AttributeClass } from "@prisma/client";
import { useForm } from "react-hook-form";
import { ArchiveBoxArrowDownIcon, ArchiveBoxXMarkIcon } from "@heroicons/react/24/solid";
import { useRouter } from "next/navigation";
import { updatetAttributeClass } from "@formbricks/lib/services/attributeClass";
import { updatetAttributeClass } from "@formbricks/lib/attributeClass/service";
import { useState } from "react";
interface AttributeSettingsTabProps {

View File

@@ -5,7 +5,7 @@ import AttributeClassDataRow from "@/app/(app)/environments/[environmentId]/(act
import AttributeTableHeading from "@/app/(app)/environments/[environmentId]/(actionsAndAttributes)/attributes/AttributeTableHeading";
import HowToAddAttributesButton from "@/app/(app)/environments/[environmentId]/(actionsAndAttributes)/attributes/HowToAddAttributesButton";
import { REVALIDATION_INTERVAL } from "@formbricks/lib/constants";
import { getAttributeClasses } from "@formbricks/lib/services/attributeClass";
import { getAttributeClasses } from "@formbricks/lib/attributeClass/service";
import { Metadata } from "next";
export const metadata: Metadata = {

View File

@@ -4,7 +4,7 @@ import { updateEnvironmentAction } from "@/app/(app)/environments/[environmentId
import EnvironmentNotice from "@/components/shared/EnvironmentNotice";
import WidgetStatusIndicator from "@/components/shared/WidgetStatusIndicator";
import { REVALIDATION_INTERVAL } from "@formbricks/lib/constants";
import { getActionsByEnvironmentId } from "@formbricks/lib/services/actions";
import { getActionsByEnvironmentId } from "@formbricks/lib/action/service";
import { getEnvironment } from "@formbricks/lib/services/environment";
import { ErrorComponent } from "@formbricks/ui";
import SettingsCard from "../SettingsCard";

View File

@@ -109,7 +109,7 @@ export default function LinkSingleUseSurveyModal({
title="Preview survey"
aria-label="Preview survey"
className="flex justify-center"
href={`${defaultSurveyUrl}?suId=${singleUseIds[0]}preview=true`}
href={`${defaultSurveyUrl}?suId=${singleUseIds[0]}&preview=true`}
target="_blank"
EndIcon={EyeIcon}>
Preview

View File

@@ -20,6 +20,7 @@ import {
import { QuestionMarkCircleIcon, TrashIcon } from "@heroicons/react/24/solid";
import { ChevronDown, SplitIcon } from "lucide-react";
import { useMemo } from "react";
import { toast } from "react-hot-toast";
import { BsArrowDown, BsArrowReturnRight } from "react-icons/bs";
interface LogicEditorProps {
@@ -141,6 +142,19 @@ export default function LogicEditor({
};
const addLogic = () => {
if (question.logic && question.logic?.length >= 0) {
const hasUndefinedLogic = question.logic.some(
(logic) =>
logic.condition === undefined && logic.value === undefined && logic.destination === undefined
);
if (hasUndefinedLogic) {
toast("Please fill current logic jumps first.", {
icon: "🤓",
});
return;
}
}
const newLogic: TSurveyLogic[] = !question.logic ? [] : question.logic;
newLogic.push({
condition: undefined,

View File

@@ -33,6 +33,7 @@ export default function MultipleChoiceMultiForm({
const [isNew, setIsNew] = useState(true);
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const questionRef = useRef<HTMLInputElement>(null);
const [isInvalidValue, setIsInvalidValue] = useState<string | null>(null);
const shuffleOptionsTypes = {
none: {
@@ -76,6 +77,24 @@ export default function MultipleChoiceMultiForm({
updateQuestion(questionIdx, { choices: newChoices, logic: newLogic });
};
const findDuplicateLabel = () => {
for (let i = 0; i < question.choices.length; i++) {
for (let j = i + 1; j < question.choices.length; j++) {
if (question.choices[i].label.trim() === question.choices[j].label.trim()) {
return question.choices[i].label.trim(); // Return the duplicate label
}
}
}
return null;
};
const findEmptyLabel = () => {
for (let i = 0; i < question.choices.length; i++) {
if (question.choices[i].label.trim() === "") return true;
}
return false;
};
const addChoice = (choiceIdx?: number) => {
setIsNew(false); // This question is no longer new.
let newChoices = !question.choices ? [] : question.choices;
@@ -112,6 +131,9 @@ export default function MultipleChoiceMultiForm({
const newChoices = !question.choices ? [] : question.choices.filter((_, idx) => idx !== choiceIdx);
const choiceValue = question.choices[choiceIdx].label;
if (isInvalidValue === choiceValue) {
setIsInvalidValue(null);
}
let newLogic: any[] = [];
question.logic?.forEach((logic) => {
let newL: string | string[] | undefined = logic.value;
@@ -198,7 +220,20 @@ export default function MultipleChoiceMultiForm({
className={cn(choice.id === "other" && "border-dashed")}
placeholder={choice.id === "other" ? "Other" : `Option ${choiceIdx + 1}`}
onChange={(e) => updateChoice(choiceIdx, { label: e.target.value })}
isInvalid={isInValid && choice.label.trim() === ""}
onBlur={() => {
const duplicateLabel = findDuplicateLabel();
if (duplicateLabel) {
setIsInvalidValue(duplicateLabel);
} else if (findEmptyLabel()) {
setIsInvalidValue("");
} else {
setIsInvalidValue(null);
}
}}
isInvalid={
(isInvalidValue === "" && choice.label.trim() === "") ||
(isInvalidValue !== null && choice.label.trim() === isInvalidValue.trim())
}
/>
{question.choices && question.choices.length > 2 && (
<TrashIcon

View File

@@ -32,6 +32,7 @@ export default function MultipleChoiceSingleForm({
const lastChoiceRef = useRef<HTMLInputElement>(null);
const [isNew, setIsNew] = useState(true);
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const [isInvalidValue, setIsInvalidValue] = useState<string | null>(null);
const questionRef = useRef<HTMLInputElement>(null);
const shuffleOptionsTypes = {
@@ -52,6 +53,24 @@ export default function MultipleChoiceSingleForm({
},
};
const findDuplicateLabel = () => {
for (let i = 0; i < question.choices.length; i++) {
for (let j = i + 1; j < question.choices.length; j++) {
if (question.choices[i].label.trim() === question.choices[j].label.trim()) {
return question.choices[i].label.trim(); // Return the duplicate label
}
}
}
return null;
};
const findEmptyLabel = () => {
for (let i = 0; i < question.choices.length; i++) {
if (question.choices[i].label.trim() === "") return true;
}
return false;
};
const updateChoice = (choiceIdx: number, updatedAttributes: { label: string }) => {
const newLabel = updatedAttributes.label;
const oldLabel = question.choices[choiceIdx].label;
@@ -112,6 +131,9 @@ export default function MultipleChoiceSingleForm({
const newChoices = !question.choices ? [] : question.choices.filter((_, idx) => idx !== choiceIdx);
const choiceValue = question.choices[choiceIdx].label;
if (isInvalidValue === choiceValue) {
setIsInvalidValue(null);
}
let newLogic: any[] = [];
question.logic?.forEach((logic) => {
let newL: string | string[] | undefined = logic.value;
@@ -197,8 +219,21 @@ export default function MultipleChoiceSingleForm({
value={choice.label}
className={cn(choice.id === "other" && "border-dashed")}
placeholder={choice.id === "other" ? "Other" : `Option ${choiceIdx + 1}`}
onBlur={() => {
const duplicateLabel = findDuplicateLabel();
if (duplicateLabel) {
setIsInvalidValue(duplicateLabel);
} else if (findEmptyLabel()) {
setIsInvalidValue("");
} else {
setIsInvalidValue(null);
}
}}
onChange={(e) => updateChoice(choiceIdx, { label: e.target.value })}
isInvalid={isInValid && choice.label.trim() === ""}
isInvalid={
(isInvalidValue === "" && choice.label.trim() === "") ||
(isInvalidValue !== null && choice.label.trim() === isInvalidValue.trim())
}
/>
{question.choices && question.choices.length > 2 && (
<TrashIcon

View File

@@ -42,7 +42,15 @@ interface QuestionCardProps {
isInValid: boolean;
}
export function BackButtonInput({ value, onChange }) {
export function BackButtonInput({
value,
onChange,
className,
}: {
value: string | undefined;
onChange: (e: any) => void;
className?: string;
}) {
return (
<div className="w-full">
<Label htmlFor="backButtonLabel">&quot;Back&quot; Button Label</Label>
@@ -53,6 +61,7 @@ export function BackButtonInput({ value, onChange }) {
value={value}
placeholder="Back"
onChange={onChange}
className={className}
/>
</div>
</div>
@@ -235,9 +244,24 @@ export default function QuestionCard({
<Input
id="buttonLabel"
name="buttonLabel"
className={cn(
isInValid &&
question.backButtonLabel?.trim() === "" &&
"border border-red-600 focus:border-red-600"
)}
value={question.buttonLabel}
placeholder={lastQuestion ? "Finish" : "Next"}
onChange={(e) => updateQuestion(questionIdx, { buttonLabel: e.target.value })}
onChange={(e) => {
const trimmedValue = e.target.value.trim(); // Remove spaces from the start and end
const hasInternalSpaces = /\S\s\S/.test(trimmedValue); // Test if there are spaces between words
if (
!trimmedValue.includes(" ") &&
(trimmedValue === "" || hasInternalSpaces || !/\s/.test(trimmedValue))
) {
updateQuestion(questionIdx, { backButtonLabel: trimmedValue });
}
}}
/>
</div>
</div>
@@ -245,6 +269,11 @@ export default function QuestionCard({
<BackButtonInput
value={question.backButtonLabel}
onChange={(e) => updateQuestion(questionIdx, { backButtonLabel: e.target.value })}
className={cn(
isInValid &&
question.backButtonLabel?.trim() === "" &&
"border border-red-600 focus:border-red-600"
)}
/>
)}
</div>
@@ -255,6 +284,11 @@ export default function QuestionCard({
<BackButtonInput
value={question.backButtonLabel}
onChange={(e) => updateQuestion(questionIdx, { backButtonLabel: e.target.value })}
className={cn(
isInValid &&
question.backButtonLabel?.trim() === "" &&
"border border-red-600 focus:border-red-600"
)}
/>
</div>
)}

View File

@@ -3,6 +3,7 @@
import AlertDialog from "@/components/shared/AlertDialog";
import DeleteDialog from "@/components/shared/DeleteDialog";
import SurveyStatusDropdown from "@/components/shared/SurveyStatusDropdown";
import { QuestionType } from "@formbricks/types/questions";
import type { Survey } from "@formbricks/types/surveys";
import { TEnvironment } from "@formbricks/types/v1/environment";
import { TProduct } from "@formbricks/types/v1/product";
@@ -97,6 +98,14 @@ export default function SurveyMenuBar({
};
const validateSurvey = (survey) => {
const existingLogicConditions = new Set();
const existingQuestionIds = new Set();
if (survey.questions.length === 0) {
toast.error("Please add at least one question");
return;
}
faultyQuestions = [];
for (let index = 0; index < survey.questions.length; index++) {
const question = survey.questions[index];
@@ -109,7 +118,67 @@ export default function SurveyMenuBar({
// if there are any faulty questions, the user won't be allowed to save the survey
if (faultyQuestions.length > 0) {
setInvalidQuestions(faultyQuestions);
toast.error("Please fill required fields");
toast.error("Please fill all required fields.");
return false;
}
for (const question of survey.questions) {
if (existingQuestionIds.has(question.id)) {
toast.error("There are 2 identical question IDs. Please update one.");
return false;
}
existingQuestionIds.add(question.id);
if (
question.type === QuestionType.MultipleChoiceSingle ||
question.type === QuestionType.MultipleChoiceMulti
) {
const haveSameChoices =
question.choices.some((element) => element.label.trim() === "") ||
question.choices.some((element, index) =>
question.choices
.slice(index + 1)
.some((nextElement) => nextElement.label.trim() === element.label.trim())
);
if (haveSameChoices) {
toast.error("You have two identical choices.");
return false;
}
}
for (const logic of question.logic || []) {
const validFields = ["condition", "destination", "value"].filter(
(field) => logic[field] !== undefined
).length;
if (validFields < 2) {
setInvalidQuestions([question.id]);
toast.error("Incomplete logic jumps detected: Please fill or delete them.");
return false;
}
if (question.required && logic.condition === "skipped") {
toast.error("You have a missing logic condition. Please update or delete it.");
return false;
}
const thisLogic = `${logic.condition}-${logic.value}`;
if (existingLogicConditions.has(thisLogic)) {
setInvalidQuestions([question.id]);
toast.error("You have 2 competing logic conditons. Please update or delete one.");
return false;
}
existingLogicConditions.add(thisLogic);
}
}
if (
survey.redirectUrl &&
!survey.redirectUrl.includes("https://") &&
!survey.redirectUrl.includes("http://")
) {
toast.error("Please enter a valid URL for redirecting respondents.");
return false;
}
@@ -128,6 +197,10 @@ export default function SurveyMenuBar({
};
const saveSurveyAction = async (shouldNavigateBack = false) => {
if (localSurvey.questions.length === 0) {
toast.error("Please add at least one question.");
return;
}
setIsMutatingSurvey(true);
// Create a copy of localSurvey with isDraft removed from every question
const strippedSurvey: TSurvey = {
@@ -139,6 +212,7 @@ export default function SurveyMenuBar({
};
if (!validateSurvey(localSurvey)) {
setIsMutatingSurvey(false);
return;
}
@@ -240,6 +314,7 @@ export default function SurveyMenuBar({
onClick={async () => {
setIsMutatingSurvey(true);
if (!validateSurvey(localSurvey)) {
setIsMutatingSurvey(false);
return;
}
await updateSurveyAction({ ...localSurvey, status: "inProgress" });

View File

@@ -7,6 +7,9 @@ import toast from "react-hot-toast";
export default function UpdateQuestionId({ localSurvey, question, questionIdx, updateQuestion }) {
const [currentValue, setCurrentValue] = useState(question.id);
const [prevValue, setPrevValue] = useState(question.id);
const [isInputInvalid, setIsInputInvalid] = useState(
currentValue.trim() === "" || currentValue.includes(" ")
);
const saveAction = () => {
// return early if the input value was not changed
@@ -14,28 +17,22 @@ export default function UpdateQuestionId({ localSurvey, question, questionIdx, u
return;
}
// check if id is unique
const questionIds = localSurvey.questions.map((q) => q.id);
if (questionIds.includes(currentValue)) {
setIsInputInvalid(true);
toast.error("IDs have to be unique per survey.");
setCurrentValue(question.id);
return;
}
// check if id contains any spaces
if (currentValue.trim() === "" || currentValue.includes(" ")) {
toast.error("ID should not contain space.");
setCurrentValue(question.id);
return;
} else if (currentValue.trim() === "" || currentValue.includes(" ")) {
setIsInputInvalid(true);
toast.error("ID should not be empty.");
} else {
setIsInputInvalid(false);
toast.success("Question ID updated.");
}
updateQuestion(questionIdx, { id: currentValue });
toast.success("Question ID updated.");
setPrevValue(currentValue); // after successful update, set current value as previous value
};
const isInputInvalid = currentValue.trim() === "" || currentValue.includes(" ");
return (
<div>
<Label htmlFor="questionId">Question ID</Label>

View File

@@ -1,6 +1,7 @@
// extend this object in order to add more validation rules
import {
TSurveyConsentQuestion,
TSurveyMultipleChoiceMultiQuestion,
TSurveyMultipleChoiceSingleQuestion,
TSurveyQuestion,
@@ -13,8 +14,16 @@ const validationRules = {
multipleChoiceSingle: (question: TSurveyMultipleChoiceSingleQuestion) => {
return !question.choices.some((element) => element.label.trim() === "");
},
consent: (question: TSurveyConsentQuestion) => {
return question.label.trim() !== "";
},
defaultValidation: (question: TSurveyQuestion) => {
return question.headline.trim() !== "";
console.log(question);
return (
question.headline.trim() !== "" &&
question.buttonLabel?.trim() !== "" &&
question.backButtonLabel?.trim() !== ""
);
},
};

View File

@@ -6,7 +6,7 @@ import { getSurveyWithAnalytics } from "@formbricks/lib/survey/service";
import { getProductByEnvironmentId } from "@formbricks/lib/services/product";
import { getEnvironment } from "@formbricks/lib/services/environment";
import { getActionClasses } from "@formbricks/lib/actionClass/service";
import { getAttributeClasses } from "@formbricks/lib/services/attributeClass";
import { getAttributeClasses } from "@formbricks/lib/attributeClass/service";
import { ErrorComponent } from "@formbricks/ui";
export default async function SurveysEditPage({ params }) {

View File

@@ -4,7 +4,7 @@ import { updateEnvironmentAction } from "@/app/(app)/environments/[environmentId
import ContentWrapper from "@/components/shared/ContentWrapper";
import WidgetStatusIndicator from "@/components/shared/WidgetStatusIndicator";
import { REVALIDATION_INTERVAL } from "@formbricks/lib/constants";
import { getActionsByEnvironmentId } from "@formbricks/lib/services/actions";
import { getActionsByEnvironmentId } from "@formbricks/lib/action/service";
import { getEnvironment } from "@formbricks/lib/services/environment";
import { Metadata } from "next";
import SurveysList from "./SurveyList";

View File

@@ -1,5 +1,5 @@
import { responses } from "@/lib/api/response";
import { markDisplayResponded } from "@formbricks/lib/services/displays";
import { markDisplayResponded } from "@formbricks/lib/display/service";
import { NextResponse } from "next/server";
export async function OPTIONS(): Promise<NextResponse> {

View File

@@ -2,7 +2,7 @@ import { responses } from "@/lib/api/response";
import { transformErrorToDetails } from "@/lib/api/validator";
import { InvalidInputError } from "@formbricks/types/v1/errors";
import { capturePosthogEvent } from "@formbricks/lib/posthogServer";
import { createDisplay } from "@formbricks/lib/services/displays";
import { createDisplay } from "@formbricks/lib/display/service";
import { getSurvey } from "@formbricks/lib/survey/service";
import { getTeamDetails } from "@formbricks/lib/services/teamDetails";
import { TDisplay, ZDisplayInput } from "@formbricks/types/v1/displays";

View File

@@ -1,6 +1,6 @@
import { responses } from "@/lib/api/response";
import { transformErrorToDetails } from "@/lib/api/validator";
import { createAction } from "@formbricks/lib/services/actions";
import { createAction } from "@formbricks/lib/action/service";
import { ZJsActionInput } from "@formbricks/types/v1/js";
import { NextResponse } from "next/server";

View File

@@ -1,7 +1,7 @@
import { getUpdatedState } from "@/app/api/v1/js/sync/lib/sync";
import { responses } from "@/lib/api/response";
import { transformErrorToDetails } from "@/lib/api/validator";
import { createAttributeClass, getAttributeClassByNameCached } from "@formbricks/lib/services/attributeClass";
import { createAttributeClass, getAttributeClassByNameCached } from "@formbricks/lib/attributeClass/service";
import { getPersonCached, updatePersonAttribute } from "@formbricks/lib/services/person";
import { ZJsPeopleAttributeInput } from "@formbricks/types/v1/js";
import { NextResponse } from "next/server";

View File

@@ -5,7 +5,7 @@ import {
deleteAttributeClass,
getAttributeClass,
updatetAttributeClass,
} from "@formbricks/lib/services/attributeClass";
} from "@formbricks/lib/attributeClass/service";
import { TAttributeClass, ZAttributeClassUpdateInput } from "@formbricks/types/v1/attributeClasses";
import { transformErrorToDetails } from "@/lib/api/validator";
import { authenticateRequest } from "@/app/api/v1/auth";

View File

@@ -4,7 +4,7 @@ import { authenticateRequest } from "@/app/api/v1/auth";
import { NextResponse } from "next/server";
import { transformErrorToDetails } from "@/lib/api/validator";
import { TAttributeClass, ZAttributeClassInput } from "@formbricks/types/v1/attributeClasses";
import { createAttributeClass, getAttributeClasses } from "@formbricks/lib/services/attributeClass";
import { createAttributeClass, getAttributeClasses } from "@formbricks/lib/attributeClass/service";
export async function GET(request: Request) {
try {

View File

@@ -36,7 +36,7 @@
"prisma": "^5.3.1",
"prisma-dbml-generator": "^0.10.0",
"prisma-json-types-generator": "^3.0.1",
"zod": "^3.22.2",
"zod": "^3.22.3",
"zod-prisma": "^0.5.4"
}
}

View File

@@ -2,7 +2,7 @@ import "server-only";
import z from "zod";
import { prisma } from "@formbricks/database";
import { DatabaseError } from "@formbricks/types/v1/errors";
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/v1/errors";
import { TAction } from "@formbricks/types/v1/actions";
import { ZId } from "@formbricks/types/v1/environment";
import { Prisma } from "@prisma/client";
@@ -65,7 +65,7 @@ export const createAction = async (data: TJsActionInput) => {
const session = await getSessionCached(sessionId);
if (!session) {
throw new Error("Session not found");
throw new ResourceNotFoundError("Session", sessionId);
}
const actionClass = await getActionClassCached(name, environmentId);

View File

@@ -13,7 +13,7 @@ import { Prisma } from "@prisma/client";
import { revalidateTag } from "next/cache";
import { cache } from "react";
import { validateInputs } from "../utils/validate";
import { transformPrismaPerson } from "./person";
import { transformPrismaPerson } from "../services/person";
const selectDisplay = {
id: true,

View File

@@ -5,6 +5,7 @@ import { TActivityFeedItem } from "@formbricks/types/v1/activity";
import { validateInputs } from "../utils/validate";
import { ZId } from "@formbricks/types/v1/environment";
import { cache } from "react";
import { ResourceNotFoundError } from "@formbricks/types/v1/errors";
export const getActivityTimeline = cache(async (personId: string): Promise<TActivityFeedItem[]> => {
validateInputs([personId, ZId]);
@@ -34,8 +35,9 @@ export const getActivityTimeline = cache(async (personId: string): Promise<TActi
},
},
});
if (!person) {
throw new Error("No such person found");
throw new ResourceNotFoundError("Person", personId);
}
const { attributes, displays, sessions } = person;

View File

@@ -2,7 +2,7 @@ import "server-only";
import { prisma } from "@formbricks/database";
import { Prisma } from "@prisma/client";
import { DatabaseError } from "@formbricks/types/v1/errors";
import { DatabaseError, UnknownError } from "@formbricks/types/v1/errors";
import { cache } from "react";
import {
TGoogleCredential,
@@ -89,8 +89,7 @@ export async function writeData(credentials: TGoogleCredential, spreadsheetId: s
},
(err: Error) => {
if (err) {
throw new Error(`Error while appending data: ${err.message}`);
} else {
throw new UnknownError(`Error while appending data: ${err.message}`);
}
}
);
@@ -104,8 +103,7 @@ export async function writeData(credentials: TGoogleCredential, spreadsheetId: s
},
(err: Error) => {
if (err) {
throw new Error(`Error while appending data: ${err.message}`);
} else {
throw new UnknownError(`Error while appending data: ${err.message}`);
}
}
);

View File

@@ -1,7 +1,7 @@
import "server-only";
import { prisma } from "@formbricks/database";
import { ResourceNotFoundError } from "@formbricks/types/v1/errors";
import { ResourceNotFoundError, DatabaseError, UnknownError } from "@formbricks/types/v1/errors";
import { TMember, TMembership, TMembershipUpdateInput } from "@formbricks/types/v1/memberships";
import { Prisma } from "@prisma/client";
import { cache } from "react";
@@ -102,9 +102,9 @@ export const updateMembership = async (
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2016") {
throw new ResourceNotFoundError("Membership", `userId: ${userId}, teamId: ${teamId}`);
} else {
throw error; // Re-throw any other errors
}
throw error;
}
};
@@ -148,6 +148,11 @@ export const transferOwnership = async (currentOwnerId: string, newOwnerId: stri
}),
]);
} catch (error) {
throw new Error("Something went wrong");
if (error instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseError("Database operation failed");
}
const message = error instanceof Error ? error.message : "";
throw new UnknownError(`Error while transfering ownership: ${message}`);
}
};

View File

@@ -2,14 +2,14 @@ import "server-only";
import { prisma } from "@formbricks/database";
import { ZId } from "@formbricks/types/v1/environment";
import { DatabaseError } from "@formbricks/types/v1/errors";
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/v1/errors";
import { TPerson, TPersonUpdateInput } from "@formbricks/types/v1/people";
import { Prisma } from "@prisma/client";
import { revalidateTag, unstable_cache } from "next/cache";
import { cache } from "react";
import { PEOPLE_PER_PAGE } from "../constants";
import { validateInputs } from "../utils/validate";
import { getAttributeClassByName } from "./attributeClass";
import { getAttributeClassByName } from "../attributeClass/service";
import { SERVICES_REVALIDATION_INTERVAL } from "../constants";
export const selectPerson = {
@@ -250,7 +250,7 @@ export const getOrCreatePersonByUserId = async (userId: string, environmentId: s
const userIdAttributeClass = await getAttributeClassByName(environmentId, "userId");
if (!userIdAttributeClass) {
throw new Error("Attribute class not found for the given environmentId");
throw new ResourceNotFoundError("Attribute class not found for the given environment", environmentId);
}
const personPrisma = await prisma.person.create({

View File

@@ -2,7 +2,7 @@ import "server-only";
import { prisma } from "@formbricks/database";
import { ZId } from "@formbricks/types/v1/environment";
import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/v1/errors";
import { DatabaseError, ResourceNotFoundError, ValidationError } from "@formbricks/types/v1/errors";
import { TTeam, TTeamUpdateInput } from "@formbricks/types/v1/teams";
import { createId } from "@paralleldrive/cuid2";
import { Prisma } from "@prisma/client";
@@ -245,7 +245,7 @@ export const createDemoProduct = async (teamId: string) => {
// check if updatedEnvironment exists and it has attributeClasses
if (!updatedEnvironment || !updatedEnvironment.attributeClasses) {
throw new Error("Attribute classes could not be created");
throw new ValidationError("Attribute classes could not be created");
}
const attributeClasses = updatedEnvironment.attributeClasses;
@@ -332,8 +332,12 @@ export const createDemoProduct = async (teamId: string) => {
})),
}),
]);
} catch (err: any) {
throw new Error(err);
} catch (error: any) {
if (error instanceof Prisma.PrismaClientKnownRequestError) {
throw new DatabaseError("Database operation failed");
}
throw error;
}
// Create a function that creates a survey

View File

@@ -15,7 +15,7 @@ import { revalidateTag, unstable_cache } from "next/cache";
import { z } from "zod";
import { captureTelemetry } from "../telemetry";
import { validateInputs } from "../utils/validate";
import { getDisplaysCacheTag } from "../services/displays";
import { getDisplaysCacheTag } from "../display/service";
import { getResponsesCacheTag } from "../response/service";
// surveys cache key and tags

View File

@@ -20,7 +20,7 @@
"@preact/preset-vite": "^2.5.0",
"autoprefixer": "^10.4.16",
"eslint-config-formbricks": "workspace:*",
"postcss": "^8.4.30",
"postcss": "^8.4.31",
"preact": "^10.17.1",
"tailwindcss": "^3.3.3",
"terser": "^5.20.0",

View File

@@ -10,7 +10,7 @@
"@tailwindcss/forms": "^0.5.6",
"@tailwindcss/typography": "^0.5.10",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.30",
"postcss": "^8.4.31",
"tailwindcss": "^3.3.3"
}
}

View File

@@ -11,6 +11,6 @@
"@formbricks/tsconfig": "workspace:*"
},
"dependencies": {
"zod": "^3.22.2"
"zod": "^3.22.3"
}
}

View File

@@ -22,6 +22,14 @@ class ValidationError extends Error {
}
}
class UnknownError extends Error {
statusCode = 500;
constructor(message: string) {
super(message);
this.name = "DatabaseError";
}
}
class DatabaseError extends Error {
statusCode = 500;
constructor(message: string) {
@@ -83,6 +91,7 @@ export {
ValidationError,
DatabaseError,
UniqueConstraintError,
UnknownError,
ForeignKeyConstraintError,
OperationNotAllowedError,
AuthenticationError,

View File

@@ -16,7 +16,7 @@
"@formbricks/tsconfig": "workspace:*",
"concurrently": "^8.2.1",
"eslint-config-formbricks": "workspace:*",
"postcss": "^8.4.30",
"postcss": "^8.4.31",
"react": "18.2.0"
},
"dependencies": {

315
pnpm-lock.yaml generated
View File

@@ -119,7 +119,7 @@ importers:
version: 8.10.0
autoprefixer:
specifier: ^10.4.15
version: 10.4.16(postcss@8.4.30)
version: 10.4.16(postcss@8.4.31)
clsx:
specifier: ^2.0.0
version: 2.0.0
@@ -273,7 +273,7 @@ importers:
version: 7.72.0(encoding@0.1.13)(next@13.5.3)(react@18.2.0)
'@t3-oss/env-nextjs':
specifier: ^0.6.1
version: 0.6.1(typescript@5.2.2)(zod@3.22.2)
version: 0.6.1(typescript@5.2.2)(zod@3.22.3)
bcryptjs:
specifier: ^2.4.3
version: 2.4.3
@@ -409,11 +409,11 @@ importers:
specifier: ^3.0.1
version: 3.0.1(prisma@5.3.1)(typescript@5.2.2)
zod:
specifier: ^3.22.2
version: 3.22.2
specifier: ^3.22.3
version: 3.22.3
zod-prisma:
specifier: ^0.5.4
version: 0.5.4(prisma@5.3.1)(zod@3.22.2)
version: 0.5.4(prisma@5.3.1)(zod@3.22.3)
packages/ee:
dependencies:
@@ -622,13 +622,13 @@ importers:
version: 2.5.0(@babel/core@7.23.0)(preact@10.17.1)(vite@4.4.9)
autoprefixer:
specifier: ^10.4.16
version: 10.4.16(postcss@8.4.30)
version: 10.4.16(postcss@8.4.31)
eslint-config-formbricks:
specifier: workspace:*
version: link:../eslint-config-formbricks
postcss:
specifier: ^8.4.30
version: 8.4.30
specifier: ^8.4.31
version: 8.4.31
preact:
specifier: ^10.17.1
version: 10.17.1
@@ -655,10 +655,10 @@ importers:
version: 0.5.10(tailwindcss@3.3.3)
autoprefixer:
specifier: ^10.4.16
version: 10.4.16(postcss@8.4.30)
version: 10.4.16(postcss@8.4.31)
postcss:
specifier: ^8.4.30
version: 8.4.30
specifier: ^8.4.31
version: 8.4.31
tailwindcss:
specifier: ^3.3.3
version: 3.3.3
@@ -681,8 +681,8 @@ importers:
packages/types:
dependencies:
zod:
specifier: ^3.22.2
version: 3.22.2
specifier: ^3.22.3
version: 3.22.3
devDependencies:
'@formbricks/tsconfig':
specifier: workspace:*
@@ -794,8 +794,8 @@ importers:
specifier: workspace:*
version: link:../eslint-config-formbricks
postcss:
specifier: ^8.4.30
version: 8.4.30
specifier: ^8.4.31
version: 8.4.31
react:
specifier: 18.2.0
version: 18.2.0
@@ -6251,25 +6251,25 @@ packages:
dependencies:
defer-to-connect: 1.1.3
/@t3-oss/env-core@0.6.1(typescript@5.2.2)(zod@3.22.2):
/@t3-oss/env-core@0.6.1(typescript@5.2.2)(zod@3.22.3):
resolution: {integrity: sha512-KQD7qEDJtkWIWWmTVjNvk0wnHpkvAQ6CRbUxbWMFNG/fiosBQDQvtRpBNu6USxBscJCoC4z6y7P9MN52/mLOzw==}
peerDependencies:
typescript: '>=4.7.2'
zod: ^3.0.0
dependencies:
typescript: 5.2.2
zod: 3.22.2
zod: 3.22.3
dev: false
/@t3-oss/env-nextjs@0.6.1(typescript@5.2.2)(zod@3.22.2):
/@t3-oss/env-nextjs@0.6.1(typescript@5.2.2)(zod@3.22.3):
resolution: {integrity: sha512-z1dIC++Vxj9kmzX5nSPfcrCSkszy3dTEPC4Ssx7Ap5AqR3c2Qa7S0xf8axn6coy7D/vCXDAAnHYnCMDhtcY3SQ==}
peerDependencies:
typescript: '>=4.7.2'
zod: ^3.0.0
dependencies:
'@t3-oss/env-core': 0.6.1(typescript@5.2.2)(zod@3.22.2)
'@t3-oss/env-core': 0.6.1(typescript@5.2.2)(zod@3.22.3)
typescript: 5.2.2
zod: 3.22.2
zod: 3.22.3
dev: false
/@tailwindcss/forms@0.5.6(tailwindcss@3.3.3):
@@ -8047,7 +8047,7 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/autoprefixer@10.4.16(postcss@8.4.30):
/autoprefixer@10.4.16(postcss@8.4.31):
resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==}
engines: {node: ^10 || ^12 || >=14}
hasBin: true
@@ -8059,7 +8059,7 @@ packages:
fraction.js: 4.3.6
normalize-range: 0.1.2
picocolors: 1.0.0
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
/available-typed-arrays@1.0.5:
@@ -9896,13 +9896,13 @@ packages:
postcss: 8.4.24
dev: true
/css-declaration-sorter@6.3.1(postcss@8.4.30):
/css-declaration-sorter@6.3.1(postcss@8.4.31):
resolution: {integrity: sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==}
engines: {node: ^10 || ^12 || >=14}
peerDependencies:
postcss: ^8.0.9
dependencies:
postcss: 8.4.30
postcss: 8.4.31
dev: true
/css-in-js-utils@3.1.0:
@@ -9917,13 +9917,13 @@ packages:
peerDependencies:
webpack: ^4.27.0 || ^5.0.0
dependencies:
icss-utils: 5.1.0(postcss@8.4.30)
icss-utils: 5.1.0(postcss@8.4.31)
loader-utils: 2.0.4
postcss: 8.4.30
postcss-modules-extract-imports: 3.0.0(postcss@8.4.30)
postcss-modules-local-by-default: 4.0.0(postcss@8.4.30)
postcss-modules-scope: 3.0.0(postcss@8.4.30)
postcss-modules-values: 4.0.0(postcss@8.4.30)
postcss: 8.4.31
postcss-modules-extract-imports: 3.0.0(postcss@8.4.31)
postcss-modules-local-by-default: 4.0.0(postcss@8.4.31)
postcss-modules-scope: 3.0.0(postcss@8.4.31)
postcss-modules-values: 4.0.0(postcss@8.4.31)
postcss-value-parser: 4.2.0
schema-utils: 3.1.1
semver: 7.5.4
@@ -10066,42 +10066,42 @@ packages:
postcss-unique-selectors: 5.1.1(postcss@8.4.24)
dev: true
/cssnano-preset-default@5.2.13(postcss@8.4.30):
/cssnano-preset-default@5.2.13(postcss@8.4.31):
resolution: {integrity: sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
css-declaration-sorter: 6.3.1(postcss@8.4.30)
cssnano-utils: 3.1.0(postcss@8.4.30)
postcss: 8.4.30
postcss-calc: 8.2.4(postcss@8.4.30)
postcss-colormin: 5.3.0(postcss@8.4.30)
postcss-convert-values: 5.1.3(postcss@8.4.30)
postcss-discard-comments: 5.1.2(postcss@8.4.30)
postcss-discard-duplicates: 5.1.0(postcss@8.4.30)
postcss-discard-empty: 5.1.1(postcss@8.4.30)
postcss-discard-overridden: 5.1.0(postcss@8.4.30)
postcss-merge-longhand: 5.1.7(postcss@8.4.30)
postcss-merge-rules: 5.1.3(postcss@8.4.30)
postcss-minify-font-values: 5.1.0(postcss@8.4.30)
postcss-minify-gradients: 5.1.1(postcss@8.4.30)
postcss-minify-params: 5.1.4(postcss@8.4.30)
postcss-minify-selectors: 5.2.1(postcss@8.4.30)
postcss-normalize-charset: 5.1.0(postcss@8.4.30)
postcss-normalize-display-values: 5.1.0(postcss@8.4.30)
postcss-normalize-positions: 5.1.1(postcss@8.4.30)
postcss-normalize-repeat-style: 5.1.1(postcss@8.4.30)
postcss-normalize-string: 5.1.0(postcss@8.4.30)
postcss-normalize-timing-functions: 5.1.0(postcss@8.4.30)
postcss-normalize-unicode: 5.1.1(postcss@8.4.30)
postcss-normalize-url: 5.1.0(postcss@8.4.30)
postcss-normalize-whitespace: 5.1.1(postcss@8.4.30)
postcss-ordered-values: 5.1.3(postcss@8.4.30)
postcss-reduce-initial: 5.1.1(postcss@8.4.30)
postcss-reduce-transforms: 5.1.0(postcss@8.4.30)
postcss-svgo: 5.1.0(postcss@8.4.30)
postcss-unique-selectors: 5.1.1(postcss@8.4.30)
css-declaration-sorter: 6.3.1(postcss@8.4.31)
cssnano-utils: 3.1.0(postcss@8.4.31)
postcss: 8.4.31
postcss-calc: 8.2.4(postcss@8.4.31)
postcss-colormin: 5.3.0(postcss@8.4.31)
postcss-convert-values: 5.1.3(postcss@8.4.31)
postcss-discard-comments: 5.1.2(postcss@8.4.31)
postcss-discard-duplicates: 5.1.0(postcss@8.4.31)
postcss-discard-empty: 5.1.1(postcss@8.4.31)
postcss-discard-overridden: 5.1.0(postcss@8.4.31)
postcss-merge-longhand: 5.1.7(postcss@8.4.31)
postcss-merge-rules: 5.1.3(postcss@8.4.31)
postcss-minify-font-values: 5.1.0(postcss@8.4.31)
postcss-minify-gradients: 5.1.1(postcss@8.4.31)
postcss-minify-params: 5.1.4(postcss@8.4.31)
postcss-minify-selectors: 5.2.1(postcss@8.4.31)
postcss-normalize-charset: 5.1.0(postcss@8.4.31)
postcss-normalize-display-values: 5.1.0(postcss@8.4.31)
postcss-normalize-positions: 5.1.1(postcss@8.4.31)
postcss-normalize-repeat-style: 5.1.1(postcss@8.4.31)
postcss-normalize-string: 5.1.0(postcss@8.4.31)
postcss-normalize-timing-functions: 5.1.0(postcss@8.4.31)
postcss-normalize-unicode: 5.1.1(postcss@8.4.31)
postcss-normalize-url: 5.1.0(postcss@8.4.31)
postcss-normalize-whitespace: 5.1.1(postcss@8.4.31)
postcss-ordered-values: 5.1.3(postcss@8.4.31)
postcss-reduce-initial: 5.1.1(postcss@8.4.31)
postcss-reduce-transforms: 5.1.0(postcss@8.4.31)
postcss-svgo: 5.1.0(postcss@8.4.31)
postcss-unique-selectors: 5.1.1(postcss@8.4.31)
dev: true
/cssnano-util-get-arguments@4.0.0:
@@ -10135,13 +10135,13 @@ packages:
postcss: 8.4.24
dev: true
/cssnano-utils@3.1.0(postcss@8.4.30):
/cssnano-utils@3.1.0(postcss@8.4.31):
resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
dev: true
/cssnano@4.1.11:
@@ -10166,15 +10166,15 @@ packages:
yaml: 1.10.2
dev: true
/cssnano@5.1.14(postcss@8.4.30):
/cssnano@5.1.14(postcss@8.4.31):
resolution: {integrity: sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
cssnano-preset-default: 5.2.13(postcss@8.4.30)
cssnano-preset-default: 5.2.13(postcss@8.4.31)
lilconfig: 2.1.0
postcss: 8.4.30
postcss: 8.4.31
yaml: 1.10.2
dev: true
@@ -13747,13 +13747,13 @@ packages:
postcss: 8.4.24
dev: true
/icss-utils@5.1.0(postcss@8.4.30):
/icss-utils@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==}
engines: {node: ^10 || ^12 || >= 14}
peerDependencies:
postcss: ^8.1.0
dependencies:
postcss: 8.4.30
postcss: 8.4.31
dev: true
/idb@7.1.1:
@@ -17827,9 +17827,9 @@ packages:
peerDependencies:
webpack: ^4.0.0
dependencies:
cssnano: 5.1.14(postcss@8.4.30)
cssnano: 5.1.14(postcss@8.4.31)
last-call-webpack-plugin: 3.0.0
postcss: 8.4.30
postcss: 8.4.31
webpack: 4.46.0
dev: true
@@ -18400,12 +18400,12 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-calc@8.2.4(postcss@8.4.30):
/postcss-calc@8.2.4(postcss@8.4.31):
resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==}
peerDependencies:
postcss: ^8.2.2
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-selector-parser: 6.0.11
postcss-value-parser: 4.2.0
dev: true
@@ -18434,7 +18434,7 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-colormin@5.3.0(postcss@8.4.30):
/postcss-colormin@5.3.0(postcss@8.4.31):
resolution: {integrity: sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
@@ -18443,7 +18443,7 @@ packages:
browserslist: 4.21.10
caniuse-api: 3.0.0
colord: 2.9.3
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -18466,14 +18466,14 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-convert-values@5.1.3(postcss@8.4.30):
/postcss-convert-values@5.1.3(postcss@8.4.31):
resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
browserslist: 4.21.10
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -18504,13 +18504,13 @@ packages:
postcss: 8.4.24
dev: true
/postcss-discard-comments@5.1.2(postcss@8.4.30):
/postcss-discard-comments@5.1.2(postcss@8.4.31):
resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
dev: true
/postcss-discard-duplicates@4.0.2:
@@ -18529,13 +18529,13 @@ packages:
postcss: 8.4.24
dev: true
/postcss-discard-duplicates@5.1.0(postcss@8.4.30):
/postcss-discard-duplicates@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
dev: true
/postcss-discard-empty@4.0.1:
@@ -18554,13 +18554,13 @@ packages:
postcss: 8.4.24
dev: true
/postcss-discard-empty@5.1.1(postcss@8.4.30):
/postcss-discard-empty@5.1.1(postcss@8.4.31):
resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
dev: true
/postcss-discard-overridden@4.0.1:
@@ -18579,13 +18579,13 @@ packages:
postcss: 8.4.24
dev: true
/postcss-discard-overridden@5.1.0(postcss@8.4.30):
/postcss-discard-overridden@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
dev: true
/postcss-import@14.1.0(postcss@8.4.21):
@@ -18697,6 +18697,23 @@ packages:
postcss: 8.4.27
yaml: 2.3.1
/postcss-load-config@4.0.1(postcss@8.4.31):
resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==}
engines: {node: '>= 14'}
peerDependencies:
postcss: '>=8.0.9'
ts-node: '>=9.0.0'
peerDependenciesMeta:
postcss:
optional: true
ts-node:
optional: true
dependencies:
lilconfig: 2.1.0
postcss: 8.4.31
yaml: 2.3.1
dev: true
/postcss-loader@4.3.0(postcss@8.4.27)(webpack@4.46.0):
resolution: {integrity: sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==}
engines: {node: '>= 10.13.0'}
@@ -18734,15 +18751,15 @@ packages:
stylehacks: 5.1.1(postcss@8.4.24)
dev: true
/postcss-merge-longhand@5.1.7(postcss@8.4.30):
/postcss-merge-longhand@5.1.7(postcss@8.4.31):
resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
stylehacks: 5.1.1(postcss@8.4.30)
stylehacks: 5.1.1(postcss@8.4.31)
dev: true
/postcss-merge-rules@4.0.3:
@@ -18770,7 +18787,7 @@ packages:
postcss-selector-parser: 6.0.11
dev: true
/postcss-merge-rules@5.1.3(postcss@8.4.30):
/postcss-merge-rules@5.1.3(postcss@8.4.31):
resolution: {integrity: sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
@@ -18778,8 +18795,8 @@ packages:
dependencies:
browserslist: 4.21.10
caniuse-api: 3.0.0
cssnano-utils: 3.1.0(postcss@8.4.30)
postcss: 8.4.30
cssnano-utils: 3.1.0(postcss@8.4.31)
postcss: 8.4.31
postcss-selector-parser: 6.0.11
dev: true
@@ -18801,13 +18818,13 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-minify-font-values@5.1.0(postcss@8.4.30):
/postcss-minify-font-values@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -18833,15 +18850,15 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-minify-gradients@5.1.1(postcss@8.4.30):
/postcss-minify-gradients@5.1.1(postcss@8.4.31):
resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
colord: 2.9.3
cssnano-utils: 3.1.0(postcss@8.4.30)
postcss: 8.4.30
cssnano-utils: 3.1.0(postcss@8.4.31)
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -18869,15 +18886,15 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-minify-params@5.1.4(postcss@8.4.30):
/postcss-minify-params@5.1.4(postcss@8.4.31):
resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
browserslist: 4.21.10
cssnano-utils: 3.1.0(postcss@8.4.30)
postcss: 8.4.30
cssnano-utils: 3.1.0(postcss@8.4.31)
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -18901,13 +18918,13 @@ packages:
postcss-selector-parser: 6.0.11
dev: true
/postcss-minify-selectors@5.2.1(postcss@8.4.30):
/postcss-minify-selectors@5.2.1(postcss@8.4.31):
resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-selector-parser: 6.0.11
dev: true
@@ -18920,13 +18937,13 @@ packages:
postcss: 8.4.24
dev: true
/postcss-modules-extract-imports@3.0.0(postcss@8.4.30):
/postcss-modules-extract-imports@3.0.0(postcss@8.4.31):
resolution: {integrity: sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==}
engines: {node: ^10 || ^12 || >= 14}
peerDependencies:
postcss: ^8.1.0
dependencies:
postcss: 8.4.30
postcss: 8.4.31
dev: true
/postcss-modules-local-by-default@4.0.0(postcss@8.4.24):
@@ -18941,14 +18958,14 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-modules-local-by-default@4.0.0(postcss@8.4.30):
/postcss-modules-local-by-default@4.0.0(postcss@8.4.31):
resolution: {integrity: sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==}
engines: {node: ^10 || ^12 || >= 14}
peerDependencies:
postcss: ^8.1.0
dependencies:
icss-utils: 5.1.0(postcss@8.4.30)
postcss: 8.4.30
icss-utils: 5.1.0(postcss@8.4.31)
postcss: 8.4.31
postcss-selector-parser: 6.0.11
postcss-value-parser: 4.2.0
dev: true
@@ -18963,13 +18980,13 @@ packages:
postcss-selector-parser: 6.0.11
dev: true
/postcss-modules-scope@3.0.0(postcss@8.4.30):
/postcss-modules-scope@3.0.0(postcss@8.4.31):
resolution: {integrity: sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==}
engines: {node: ^10 || ^12 || >= 14}
peerDependencies:
postcss: ^8.1.0
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-selector-parser: 6.0.11
dev: true
@@ -18983,14 +19000,14 @@ packages:
postcss: 8.4.24
dev: true
/postcss-modules-values@4.0.0(postcss@8.4.30):
/postcss-modules-values@4.0.0(postcss@8.4.31):
resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==}
engines: {node: ^10 || ^12 || >= 14}
peerDependencies:
postcss: ^8.1.0
dependencies:
icss-utils: 5.1.0(postcss@8.4.30)
postcss: 8.4.30
icss-utils: 5.1.0(postcss@8.4.31)
postcss: 8.4.31
dev: true
/postcss-modules@4.3.1(postcss@8.4.24):
@@ -19044,13 +19061,13 @@ packages:
postcss: 8.4.24
dev: true
/postcss-normalize-charset@5.1.0(postcss@8.4.30):
/postcss-normalize-charset@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
dev: true
/postcss-normalize-display-values@4.0.2:
@@ -19072,13 +19089,13 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-normalize-display-values@5.1.0(postcss@8.4.30):
/postcss-normalize-display-values@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -19102,13 +19119,13 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-normalize-positions@5.1.1(postcss@8.4.30):
/postcss-normalize-positions@5.1.1(postcss@8.4.31):
resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -19132,13 +19149,13 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-normalize-repeat-style@5.1.1(postcss@8.4.30):
/postcss-normalize-repeat-style@5.1.1(postcss@8.4.31):
resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -19161,13 +19178,13 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-normalize-string@5.1.0(postcss@8.4.30):
/postcss-normalize-string@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -19190,13 +19207,13 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-normalize-timing-functions@5.1.0(postcss@8.4.30):
/postcss-normalize-timing-functions@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -19220,14 +19237,14 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-normalize-unicode@5.1.1(postcss@8.4.30):
/postcss-normalize-unicode@5.1.1(postcss@8.4.31):
resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
browserslist: 4.21.10
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -19252,14 +19269,14 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-normalize-url@5.1.0(postcss@8.4.30):
/postcss-normalize-url@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
normalize-url: 6.1.0
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -19281,13 +19298,13 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-normalize-whitespace@5.1.1(postcss@8.4.30):
/postcss-normalize-whitespace@5.1.1(postcss@8.4.31):
resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -19311,14 +19328,14 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-ordered-values@5.1.3(postcss@8.4.30):
/postcss-ordered-values@5.1.3(postcss@8.4.31):
resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
cssnano-utils: 3.1.0(postcss@8.4.30)
postcss: 8.4.30
cssnano-utils: 3.1.0(postcss@8.4.31)
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -19343,7 +19360,7 @@ packages:
postcss: 8.4.24
dev: true
/postcss-reduce-initial@5.1.1(postcss@8.4.30):
/postcss-reduce-initial@5.1.1(postcss@8.4.31):
resolution: {integrity: sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
@@ -19351,7 +19368,7 @@ packages:
dependencies:
browserslist: 4.21.10
caniuse-api: 3.0.0
postcss: 8.4.30
postcss: 8.4.31
dev: true
/postcss-reduce-transforms@4.0.2:
@@ -19374,13 +19391,13 @@ packages:
postcss-value-parser: 4.2.0
dev: true
/postcss-reduce-transforms@5.1.0(postcss@8.4.30):
/postcss-reduce-transforms@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
dev: true
@@ -19427,13 +19444,13 @@ packages:
svgo: 2.8.0
dev: true
/postcss-svgo@5.1.0(postcss@8.4.30):
/postcss-svgo@5.1.0(postcss@8.4.31):
resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-value-parser: 4.2.0
svgo: 2.8.0
dev: true
@@ -19457,13 +19474,13 @@ packages:
postcss-selector-parser: 6.0.11
dev: true
/postcss-unique-selectors@5.1.1(postcss@8.4.30):
/postcss-unique-selectors@5.1.1(postcss@8.4.31):
resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
postcss: 8.4.30
postcss: 8.4.31
postcss-selector-parser: 6.0.11
dev: true
@@ -19517,8 +19534,8 @@ packages:
picocolors: 1.0.0
source-map-js: 1.0.2
/postcss@8.4.30:
resolution: {integrity: sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==}
/postcss@8.4.31:
resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
engines: {node: ^10 || ^12 || >=14}
dependencies:
nanoid: 3.3.6
@@ -22394,14 +22411,14 @@ packages:
postcss-selector-parser: 6.0.11
dev: true
/stylehacks@5.1.1(postcss@8.4.30):
/stylehacks@5.1.1(postcss@8.4.31):
resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==}
engines: {node: ^10 || ^12 || >=14.0}
peerDependencies:
postcss: ^8.2.15
dependencies:
browserslist: 4.21.10
postcss: 8.4.30
postcss: 8.4.31
postcss-selector-parser: 6.0.11
dev: true
@@ -23141,7 +23158,7 @@ packages:
execa: 5.1.1
globby: 11.1.0
joycon: 3.1.1
postcss-load-config: 4.0.1(postcss@8.4.27)
postcss-load-config: 4.0.1(postcss@8.4.31)
resolve-from: 5.0.0
rollup: 3.5.1
source-map: 0.8.0-beta.0
@@ -24154,7 +24171,7 @@ packages:
optional: true
dependencies:
esbuild: 0.18.10
postcss: 8.4.30
postcss: 8.4.31
rollup: 3.28.1
terser: 5.20.0
optionalDependencies:
@@ -25121,7 +25138,7 @@ packages:
readable-stream: 3.6.0
dev: true
/zod-prisma@0.5.4(prisma@5.3.1)(zod@3.22.2):
/zod-prisma@0.5.4(prisma@5.3.1)(zod@3.22.3):
resolution: {integrity: sha512-5Ca4Qd1a1jy1T/NqCEpbr0c+EsbjJfJ/7euEHob3zDvtUK2rTuD1Rc/vfzH8q8PtaR2TZbysD88NHmrLwpv3Xg==}
engines: {node: '>=14'}
hasBin: true
@@ -25137,15 +25154,15 @@ packages:
parenthesis: 3.1.8
prisma: 5.3.1
ts-morph: 13.0.3
zod: 3.22.2
zod: 3.22.3
dev: true
/zod@3.21.4:
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
dev: false
/zod@3.22.2:
resolution: {integrity: sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg==}
/zod@3.22.3:
resolution: {integrity: sha512-EjIevzuJRiRPbVH4mGc8nApb/lVLKVpmUhAaR5R5doKGfAnGJ6Gr3CViAVjP+4FWSxCsybeWQdcgCtbX+7oZug==}
/zustand@4.4.1(@types/react@18.2.23)(react@18.2.0):
resolution: {integrity: sha512-QCPfstAS4EBiTQzlaGP1gmorkh/UL1Leaj2tdj+zZCZ/9bm0WS7sI2wnfD5lpOszFqWJ1DcPnGoY8RDL61uokw==}