From 18eca7cd8c82cb67e5867979180ec4357b5a195b Mon Sep 17 00:00:00 2001 From: Luke Vella Date: Mon, 27 Feb 2023 15:08:59 +0000 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Update=20trpcs=20routes=20?= =?UTF-8?q?(#531)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 8 +- prisma/middlewares/softDeleteMiddleware.ts | 5 +- src/components/admin-control.tsx | 8 +- src/components/auth/login-form.tsx | 10 +- src/components/create-poll.tsx | 2 +- src/components/discussion/discussion.tsx | 17 +-- src/components/participants-provider.tsx | 5 +- src/components/poll-context.tsx | 8 +- src/components/poll/manage-poll.tsx | 4 +- .../poll/manage-poll/delete-poll-form.tsx | 2 +- src/components/poll/mutations.ts | 30 ++--- .../poll/unverified-poll-notice.tsx | 5 +- src/components/poll/use-touch-beacon.ts | 2 +- src/components/profile.tsx | 2 +- src/components/profile/user-details.tsx | 2 +- src/components/user-provider.tsx | 8 +- src/pages/_app.tsx | 4 +- src/pages/admin/[urlId].tsx | 6 +- src/pages/demo.tsx | 2 +- src/pages/p/[urlId].tsx | 6 +- src/server/createRouter.ts | 8 -- src/server/routers/_app.ts | 13 +-- src/server/routers/login.ts | 57 +++++----- src/server/routers/polls.ts | 105 +++++++++--------- src/server/routers/polls/comments.ts | 52 +++++---- src/server/routers/polls/demo.ts | 8 +- src/server/routers/polls/participants.ts | 89 ++++++++------- src/server/routers/polls/verification.ts | 37 +++--- src/server/routers/user.ts | 74 ++++++------ src/utils/trpc.ts | 5 +- src/utils/trpc/types.ts | 1 + yarn.lock | 32 +++--- 32 files changed, 300 insertions(+), 317 deletions(-) delete mode 100644 src/server/createRouter.ts diff --git a/package.json b/package.json index 6f7d49d2c..5ca0a4ebf 100644 --- a/package.json +++ b/package.json @@ -27,10 +27,10 @@ "@svgr/webpack": "^6.5.1", "@tailwindcss/typography": "^0.5.9", "@tanstack/react-query": "^4.22.0", - "@trpc/client": "^10.0.0-rc.8", - "@trpc/next": "^10.0.0-rc.8", - "@trpc/react-query": "^10.0.0-rc.8", - "@trpc/server": "^10.0.0-rc.8", + "@trpc/client": "^10.13.0", + "@trpc/next": "^10.13.0", + "@trpc/react-query": "^10.13.0", + "@trpc/server": "^10.13.0", "@vercel/analytics": "^0.1.8", "accept-language-parser": "^1.5.0", "autoprefixer": "^10.4.13", diff --git a/prisma/middlewares/softDeleteMiddleware.ts b/prisma/middlewares/softDeleteMiddleware.ts index aafe6e194..85341fc48 100644 --- a/prisma/middlewares/softDeleteMiddleware.ts +++ b/prisma/middlewares/softDeleteMiddleware.ts @@ -23,10 +23,7 @@ export const softDeleteMiddleware = ( params.args["data"] = { deleted: true, deletedAt: new Date() }; } } - if (params.action === "findUnique" || params.action === "findFirst") { - // Change to findFirst - you cannot filter - // by anything except ID / unique with findUnique - params.action = "findFirst"; + if (params.action === "findFirst") { // Add 'deleted' filter // ID filter maintained params.args.where["deleted"] = params.args.where["deleted"] || false; diff --git a/src/components/admin-control.tsx b/src/components/admin-control.tsx index 434759ec5..7e3eb3df3 100644 --- a/src/components/admin-control.tsx +++ b/src/components/admin-control.tsx @@ -9,7 +9,7 @@ import { useMount } from "react-use"; import { Button } from "@/components/button"; import Share from "@/components/icons/share.svg"; -import { trpc, trpcNext } from "../utils/trpc"; +import { trpc } from "../utils/trpc"; import { useParticipants } from "./participants-provider"; import ManagePoll from "./poll/manage-poll"; import { useUpdatePollMutation } from "./poll/mutations"; @@ -25,7 +25,7 @@ export const AdminControls = (props: { children?: React.ReactNode }) => { const router = useRouter(); - const queryClient = trpcNext.useContext(); + const queryClient = trpc.useContext(); const session = useUser(); @@ -48,10 +48,10 @@ export const AdminControls = (props: { children?: React.ReactNode }) => { } }, [urlId, router, updatePollMutation, t]); - const verifyEmail = trpc.useMutation(["polls.verification.verify"], { + const verifyEmail = trpc.polls.verification.verify.useMutation({ onSuccess: () => { toast.success(t("pollHasBeenVerified")); - queryClient.poll.invalidate(); + queryClient.polls.invalidate(); session.refresh(); posthog.capture("verified email"); }, diff --git a/src/components/auth/login-form.tsx b/src/components/auth/login-form.tsx index 187febb44..96bfa3873 100644 --- a/src/components/auth/login-form.tsx +++ b/src/components/auth/login-form.tsx @@ -5,7 +5,7 @@ import React from "react"; import { useForm } from "react-hook-form"; import { requiredString, validEmail } from "../../utils/form-validation"; -import { trpcNext } from "../../utils/trpc"; +import { trpc } from "../../utils/trpc"; import { Button } from "../button"; import { TextInput } from "../text-input"; @@ -133,9 +133,9 @@ export const RegisterForm: React.VoidFunctionComponent<{ useForm({ defaultValues, }); - const requestRegistration = trpcNext.auth.requestRegistration.useMutation(); + const requestRegistration = trpc.auth.requestRegistration.useMutation(); const authenticateRegistration = - trpcNext.auth.authenticateRegistration.useMutation(); + trpc.auth.authenticateRegistration.useMutation(); const [token, setToken] = React.useState(); if (token) { @@ -273,8 +273,8 @@ export const LoginForm: React.VoidFunctionComponent<{ const { t } = useTranslation("app"); const { register, handleSubmit, getValues, formState, setError } = useForm<{ email: string }>(); - const requestLogin = trpcNext.auth.requestLogin.useMutation(); - const authenticateLogin = trpcNext.auth.authenticateLogin.useMutation(); + const requestLogin = trpc.auth.requestLogin.useMutation(); + const authenticateLogin = trpc.auth.authenticateLogin.useMutation(); const [token, setToken] = React.useState(); diff --git a/src/components/create-poll.tsx b/src/components/create-poll.tsx index a1ad739e5..62e6b3cce 100644 --- a/src/components/create-poll.tsx +++ b/src/components/create-poll.tsx @@ -90,7 +90,7 @@ const Page: NextPage = ({ const [isRedirecting, setIsRedirecting] = React.useState(false); - const createPoll = trpc.useMutation(["polls.create"], { + const createPoll = trpc.polls.create.useMutation({ onSuccess: (res) => { setIsRedirecting(true); posthog.capture("created poll", { diff --git a/src/components/discussion/discussion.tsx b/src/components/discussion/discussion.tsx index 787514670..b31ed4b43 100644 --- a/src/components/discussion/discussion.tsx +++ b/src/components/discussion/discussion.tsx @@ -31,19 +31,20 @@ const Discussion: React.VoidFunctionComponent = () => { const pollId = poll.id; - const { data: comments } = trpc.useQuery( - ["polls.comments.list", { pollId }], + const { data: comments } = trpc.polls.comments.list.useQuery( + { pollId }, { refetchInterval: 10000, // refetch every 10 seconds + trpc: {}, }, ); - const addComment = trpc.useMutation("polls.comments.add", { + const addComment = trpc.polls.comments.add.useMutation({ onSuccess: (newComment) => { posthog.capture("created comment"); - queryClient.setQueryData( - ["polls.comments.list", { pollId }], + queryClient.polls.comments.list.setData( + { pollId }, (existingComments = []) => { return [...existingComments, newComment]; }, @@ -51,10 +52,10 @@ const Discussion: React.VoidFunctionComponent = () => { }, }); - const deleteComment = trpc.useMutation("polls.comments.delete", { + const deleteComment = trpc.polls.comments.delete.useMutation({ onMutate: ({ commentId }) => { - queryClient.setQueryData( - ["polls.comments.list", { pollId }], + queryClient.polls.comments.list.setData( + { pollId }, (existingComments = []) => { return [...existingComments].filter(({ id }) => id !== commentId); }, diff --git a/src/components/participants-provider.tsx b/src/components/participants-provider.tsx index aa6cfbda7..e4cb54e67 100644 --- a/src/components/participants-provider.tsx +++ b/src/components/participants-provider.tsx @@ -22,10 +22,7 @@ export const ParticipantsProvider: React.VoidFunctionComponent<{ }> = ({ children, pollId }) => { const { t } = useTranslation("app"); - const { data: participants } = trpc.useQuery([ - "polls.participants.list", - { pollId }, - ]); + const { data: participants } = trpc.polls.participants.list.useQuery({ pollId }); const getParticipants = ( optionId: string, diff --git a/src/components/poll-context.tsx b/src/components/poll-context.tsx index a829e8422..9ad182f33 100644 --- a/src/components/poll-context.tsx +++ b/src/components/poll-context.tsx @@ -28,8 +28,6 @@ type PollContextValue = { setTargetTimeZone: (timeZone: string) => void; pollType: "date" | "timeSlot"; highScore: number; - isDeleted: boolean; - setDeleted: React.Dispatch>; optionIds: string[]; // TODO (Luke Vella) [2022-05-18]: Move this stuff to participants provider getParticipantsWhoVotedForOption: (optionId: string) => Participant[]; // maybe just attach votes to parsed options @@ -60,7 +58,6 @@ export const PollContextProvider: React.VoidFunctionComponent<{ }> = ({ poll, urlId, admin, children }) => { const { t } = useTranslation("app"); const { participants } = useParticipants(); - const [isDeleted, setDeleted] = React.useState(false); const { user } = useUser(); const [targetTimeZone, setTargetTimeZone] = React.useState(getBrowserTimeZone); @@ -159,13 +156,10 @@ export const PollContextProvider: React.VoidFunctionComponent<{ ...parsedOptions, targetTimeZone, setTargetTimeZone, - isDeleted, - setDeleted, }; }, [ admin, getScore, - isDeleted, participants, poll, targetTimeZone, @@ -174,7 +168,7 @@ export const PollContextProvider: React.VoidFunctionComponent<{ user, ]); - if (isDeleted) { + if (poll.deleted) { return ( = ({ placement }) => { const { t } = useTranslation("app"); - const { poll, getParticipantsWhoVotedForOption, setDeleted, urlId } = - usePoll(); + const { poll, getParticipantsWhoVotedForOption, urlId } = usePoll(); const { exportToCsv } = useCsvExporter(); @@ -218,7 +217,6 @@ const ManagePoll: React.VoidFunctionComponent<{ { close(); - setDeleted(true); }} onCancel={close} urlId={urlId} diff --git a/src/components/poll/manage-poll/delete-poll-form.tsx b/src/components/poll/manage-poll/delete-poll-form.tsx index 8402a8538..760d3ac53 100644 --- a/src/components/poll/manage-poll/delete-poll-form.tsx +++ b/src/components/poll/manage-poll/delete-poll-form.tsx @@ -21,7 +21,7 @@ export const DeletePollForm: React.VoidFunctionComponent<{ const confirmationText = watch("confirmation"); const canDelete = confirmationText === confirmText; - const deletePoll = trpc.useMutation("polls.delete", { + const deletePoll = trpc.polls.delete.useMutation({ onSuccess: () => { posthog.capture("deleted poll"); }, diff --git a/src/components/poll/mutations.ts b/src/components/poll/mutations.ts index 771d4e7b4..1f9a36a2a 100644 --- a/src/components/poll/mutations.ts +++ b/src/components/poll/mutations.ts @@ -1,6 +1,6 @@ import posthog from "posthog-js"; -import { trpc, trpcNext } from "../../utils/trpc"; +import { trpc } from "../../utils/trpc"; import { ParticipantForm } from "./types"; export const normalizeVotes = ( @@ -14,32 +14,24 @@ export const normalizeVotes = ( }; export const useAddParticipantMutation = () => { - const queryClient = trpc.useContext(); - - return trpc.useMutation(["polls.participants.add"], { + return trpc.polls.participants.add.useMutation({ onSuccess: (participant) => { posthog.capture("add participant", { name: participant.name, }); - queryClient.setQueryData( - ["polls.participants.list", { pollId: participant.pollId }], - (existingParticipants = []) => { - return [participant, ...existingParticipants]; - }, - ); }, }); }; export const useUpdateParticipantMutation = () => { const queryClient = trpc.useContext(); - return trpc.useMutation("polls.participants.update", { + return trpc.polls.participants.update.useMutation({ onSuccess: (participant) => { posthog.capture("update participant", { name: participant.name, }); - queryClient.setQueryData( - ["polls.participants.list", { pollId: participant.pollId }], + queryClient.polls.participants.list.setData( + { pollId: participant.pollId }, (existingParticipants = []) => { const newParticipants = [...existingParticipants]; @@ -60,10 +52,10 @@ export const useUpdateParticipantMutation = () => { export const useDeleteParticipantMutation = () => { const queryClient = trpc.useContext(); - return trpc.useMutation("polls.participants.delete", { + return trpc.polls.participants.delete.useMutation({ onMutate: ({ participantId, pollId }) => { - queryClient.setQueryData( - ["polls.participants.list", { pollId: pollId }], + queryClient.polls.participants.list.setData( + { pollId: pollId }, (existingParticipants = []) => { return existingParticipants.filter(({ id }) => id !== participantId); }, @@ -78,10 +70,10 @@ export const useDeleteParticipantMutation = () => { }; export const useUpdatePollMutation = () => { - const queryClient = trpcNext.useContext(); - return trpc.useMutation(["polls.update"], { + const queryClient = trpc.useContext(); + return trpc.polls.update.useMutation({ onSuccess: (data) => { - queryClient.poll.invalidate(); + queryClient.polls.invalidate(); posthog.capture("updated poll", { id: data.id, }); diff --git a/src/components/poll/unverified-poll-notice.tsx b/src/components/poll/unverified-poll-notice.tsx index fff62d30d..09742e171 100644 --- a/src/components/poll/unverified-poll-notice.tsx +++ b/src/components/poll/unverified-poll-notice.tsx @@ -7,9 +7,8 @@ import { usePoll } from "../poll-context"; export const UnverifiedPollNotice = () => { const { t } = useTranslation("app"); const { poll } = usePoll(); - const requestVerificationEmail = trpc.useMutation( - "polls.verification.request", - ); + const requestVerificationEmail = trpc.polls.verification.request.useMutation( +); return (
diff --git a/src/components/poll/use-touch-beacon.ts b/src/components/poll/use-touch-beacon.ts index 98718ae87..00f190488 100644 --- a/src/components/poll/use-touch-beacon.ts +++ b/src/components/poll/use-touch-beacon.ts @@ -7,7 +7,7 @@ import { trpc } from "../../utils/trpc"; * find polls that haven't been accessed for some time so that they can be deleted by house keeping. */ export const useTouchBeacon = (pollId: string) => { - const touchMutation = trpc.useMutation(["polls.touch"]); + const touchMutation = trpc.polls.touch.useMutation(); useMount(() => { touchMutation.mutate({ pollId }); diff --git a/src/components/profile.tsx b/src/components/profile.tsx index 15484b9df..1a4ae29ae 100644 --- a/src/components/profile.tsx +++ b/src/components/profile.tsx @@ -19,7 +19,7 @@ export const Profile: React.VoidFunctionComponent = () => { const { dayjs } = useDayjs(); const { t } = useTranslation("app"); - const { data: userPolls } = trpc.useQuery(["user.getPolls"]); + const { data: userPolls } = trpc.user.getPolls.useQuery(); const createdPolls = userPolls?.polls; const router = useRouter(); diff --git a/src/components/profile/user-details.tsx b/src/components/profile/user-details.tsx index 5c27ced18..f8b71160a 100644 --- a/src/components/profile/user-details.tsx +++ b/src/components/profile/user-details.tsx @@ -33,7 +33,7 @@ export const UserDetails: React.VoidFunctionComponent = ({ const { refresh } = useUser(); - const changeName = trpc.useMutation("user.changeName", { + const changeName = trpc.user.changeName.useMutation({ onSuccess: (_, { name }) => { posthog.people.set({ name }); refresh(); diff --git a/src/components/user-provider.tsx b/src/components/user-provider.tsx index 3644bf1e8..af60aac36 100644 --- a/src/components/user-provider.tsx +++ b/src/components/user-provider.tsx @@ -5,7 +5,7 @@ import { useMount } from "react-use"; import { UserSession } from "@/utils/auth"; -import { trpcNext } from "../utils/trpc"; +import { trpc } from "../utils/trpc"; import { useRequiredContext } from "./use-required-context"; export const UserContext = @@ -51,12 +51,12 @@ export const IfGuest = (props: { children?: React.ReactNode }) => { export const UserProvider = (props: { children?: React.ReactNode }) => { const { t } = useTranslation("app"); - const queryClient = trpcNext.useContext(); - const { data: user } = trpcNext.whoami.get.useQuery(); + const queryClient = trpc.useContext(); + const { data: user } = trpc.whoami.get.useQuery(); const [isUpdating, setIsUpdating] = React.useState(false); - const logout = trpcNext.whoami.destroy.useMutation({ + const logout = trpc.whoami.destroy.useMutation({ onSuccess: async () => { setIsUpdating(true); await queryClient.whoami.invalidate(); diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 4b0ad69e0..269a52a44 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -18,7 +18,7 @@ import { useCrispChat } from "../components/crisp-chat"; import { NextPageWithLayout } from "../types"; import { absoluteUrl } from "../utils/absolute-url"; import { UserSession } from "../utils/auth"; -import { trpcNext } from "../utils/trpc"; +import { trpc } from "../utils/trpc"; const inter = Inter({ subsets: ["latin"], @@ -93,4 +93,4 @@ const MyApp: NextPage = ({ Component, pageProps }) => { ); }; -export default trpcNext.withTRPC(appWithTranslation(MyApp)); +export default trpc.withTRPC(appWithTranslation(MyApp)); diff --git a/src/pages/admin/[urlId].tsx b/src/pages/admin/[urlId].tsx index b4456fb31..b387450f0 100644 --- a/src/pages/admin/[urlId].tsx +++ b/src/pages/admin/[urlId].tsx @@ -8,7 +8,7 @@ import { ParticipantsProvider } from "@/components/participants-provider"; import { Poll } from "@/components/poll"; import { PollContextProvider } from "@/components/poll-context"; import { withSessionSsr } from "@/utils/auth"; -import { trpcNext } from "@/utils/trpc"; +import { trpc } from "@/utils/trpc"; import { withPageTranslations } from "@/utils/with-page-translations"; import { AdminControls } from "../../components/admin-control"; @@ -18,7 +18,7 @@ import { NextPageWithLayout } from "../../types"; const Page: NextPageWithLayout<{ urlId: string }> = ({ urlId }) => { const { t } = useTranslation("app"); - const pollQuery = trpcNext.poll.getByAdminUrlId.useQuery({ urlId }); + const pollQuery = trpc.polls.getByAdminUrlId.useQuery({ urlId }); const poll = pollQuery.data; @@ -62,7 +62,7 @@ export const getServerSideProps: GetServerSideProps = withSessionSsr( ], { onPrefetch: async (ssg, ctx) => { - await ssg.poll.getByAdminUrlId.fetch({ + await ssg.polls.getByAdminUrlId.fetch({ urlId: ctx.params?.urlId as string, }); }, diff --git a/src/pages/demo.tsx b/src/pages/demo.tsx index e1f84d94c..f9e4c3a32 100644 --- a/src/pages/demo.tsx +++ b/src/pages/demo.tsx @@ -15,7 +15,7 @@ const Demo: NextPage = () => { const { t } = useTranslation("app"); const router = useRouter(); - const createDemo = trpc.useMutation(["polls.demo.create"]); + const createDemo = trpc.polls.demo.create.useMutation(); useMount(async () => { const urlId = await createDemo.mutateAsync(); diff --git a/src/pages/p/[urlId].tsx b/src/pages/p/[urlId].tsx index e516bd275..150af281c 100644 --- a/src/pages/p/[urlId].tsx +++ b/src/pages/p/[urlId].tsx @@ -8,7 +8,7 @@ import { Poll } from "@/components/poll"; import { PollContextProvider } from "@/components/poll-context"; import { useUser } from "@/components/user-provider"; import { withSessionSsr } from "@/utils/auth"; -import { trpcNext } from "@/utils/trpc"; +import { trpc } from "@/utils/trpc"; import { withPageTranslations } from "@/utils/with-page-translations"; import StandardLayout from "../../components/layouts/standard-layout"; @@ -16,7 +16,7 @@ import ModalProvider from "../../components/modal/modal-provider"; import { NextPageWithLayout } from "../../types"; const Page: NextPageWithLayout<{ urlId: string }> = ({ urlId }) => { - const pollQuery = trpcNext.poll.getByParticipantUrlId.useQuery({ urlId }); + const pollQuery = trpc.polls.getByParticipantUrlId.useQuery({ urlId }); const { user } = useUser(); const poll = pollQuery.data; @@ -70,7 +70,7 @@ export const getServerSideProps: GetServerSideProps = withSessionSsr( ], { onPrefetch: async (ssg, ctx) => { - await ssg.poll.getByParticipantUrlId.fetch({ + await ssg.polls.getByParticipantUrlId.fetch({ urlId: ctx.params?.urlId as string, }); }, diff --git a/src/server/createRouter.ts b/src/server/createRouter.ts deleted file mode 100644 index 2e406e42e..000000000 --- a/src/server/createRouter.ts +++ /dev/null @@ -1,8 +0,0 @@ -import * as trpc from "@trpc/server"; - -import { Context } from "./context"; - -// Helper function to create a router with your app's context -export function createRouter() { - return trpc.router(); -} diff --git a/src/server/routers/_app.ts b/src/server/routers/_app.ts index 6299d62aa..a9a8df6c0 100644 --- a/src/server/routers/_app.ts +++ b/src/server/routers/_app.ts @@ -1,22 +1,17 @@ -import { createRouter } from "../createRouter"; import { mergeRouters, router } from "../trpc"; import { auth } from "./auth"; import { login } from "./login"; -import { legacyPolls, poll } from "./polls"; +import { polls } from "./polls"; import { user } from "./user"; import { whoami } from "./whoami"; -const legacyRouter = createRouter() - .merge("user.", user) - .merge(login) - .merge("polls.", legacyPolls); - export const appRouter = mergeRouters( - legacyRouter.interop(), router({ whoami, auth, - poll, + polls, + user, + login, }), ); diff --git a/src/server/routers/login.ts b/src/server/routers/login.ts index f9381097e..6424e6085 100644 --- a/src/server/routers/login.ts +++ b/src/server/routers/login.ts @@ -5,35 +5,38 @@ import loginTemplate from "~/templates/login"; import { absoluteUrl } from "../../utils/absolute-url"; import { sendEmailTemplate } from "../../utils/api-utils"; import { createToken } from "../../utils/auth"; -import { createRouter } from "../createRouter"; +import { publicProcedure, router } from "../trpc"; -export const login = createRouter().mutation("login", { - input: z.object({ - email: z.string(), - path: z.string(), - }), - resolve: async ({ ctx, input }) => { - const { email, path } = input; - const homePageUrl = absoluteUrl(); - const user = ctx.session.user; +export const login = router({ + login: publicProcedure + .input( + z.object({ + email: z.string(), + path: z.string(), + }), + ) + .mutation(async ({ ctx, input }) => { + const { email, path } = input; + const homePageUrl = absoluteUrl(); + const user = ctx.session.user; - const token = await createToken({ - email, - guestId: user.id, - path, - }); + const token = await createToken({ + email, + guestId: user.id, + path, + }); - const loginUrl = `${homePageUrl}/login?code=${token}`; + const loginUrl = `${homePageUrl}/login?code=${token}`; - await sendEmailTemplate({ - templateString: loginTemplate, - to: email, - subject: "Rallly - Login", - templateVars: { - loginUrl, - homePageUrl, - supportEmail: process.env.SUPPORT_EMAIL, - }, - }); - }, + await sendEmailTemplate({ + templateString: loginTemplate, + to: email, + subject: "Rallly - Login", + templateVars: { + loginUrl, + homePageUrl, + supportEmail: process.env.SUPPORT_EMAIL, + }, + }); + }), }); diff --git a/src/server/routers/polls.ts b/src/server/routers/polls.ts index 0908481bc..7bc9215ac 100644 --- a/src/server/routers/polls.ts +++ b/src/server/routers/polls.ts @@ -10,7 +10,6 @@ import { sendEmailTemplate } from "../../utils/api-utils"; import { createToken } from "../../utils/auth"; import { nanoid } from "../../utils/nanoid"; import { GetPollApiResponse } from "../../utils/trpc/types"; -import { createRouter } from "../createRouter"; import { publicProcedure, router } from "../trpc"; import { comments } from "./polls/comments"; import { demo } from "./polls/demo"; @@ -38,6 +37,7 @@ const defaultSelectFields: { }; }; user: true; + deleted: true; } = { id: true, timeZone: true, @@ -59,6 +59,7 @@ const defaultSelectFields: { }, }, user: true, + deleted: true, }; const getPollIdFromAdminUrlId = async (urlId: string) => { @@ -77,26 +78,25 @@ const getPollIdFromAdminUrlId = async (urlId: string) => { return res.id; }; -export const legacyPolls = createRouter() - .merge("demo.", demo) - .merge("participants.", participants) - .merge("comments.", comments) - .merge("verification.", verification) - .mutation("create", { - input: z.object({ - title: z.string(), - type: z.literal("date"), - timeZone: z.string().optional(), - location: z.string().optional(), - description: z.string().optional(), - user: z.object({ - name: z.string(), - email: z.string(), +export const polls = router({ + // START LEGACY ROUTES + create: publicProcedure + .input( + z.object({ + title: z.string(), + type: z.literal("date"), + timeZone: z.string().optional(), + location: z.string().optional(), + description: z.string().optional(), + user: z.object({ + name: z.string(), + email: z.string(), + }), + options: z.string().array(), + demo: z.boolean().optional(), }), - options: z.string().array(), - demo: z.boolean().optional(), - }), - resolve: async ({ ctx, input }): Promise<{ urlId: string }> => { + ) + .mutation(async ({ ctx, input }): Promise<{ urlId: string }> => { const adminUrlId = await nanoid(); let verified = false; @@ -188,21 +188,22 @@ export const legacyPolls = createRouter() } return { urlId: adminUrlId }; - }, - }) - .mutation("update", { - input: z.object({ - urlId: z.string(), - title: z.string().optional(), - timeZone: z.string().optional(), - location: z.string().optional(), - description: z.string().optional(), - optionsToDelete: z.string().array().optional(), - optionsToAdd: z.string().array().optional(), - notifications: z.boolean().optional(), - closed: z.boolean().optional(), }), - resolve: async ({ input }): Promise => { + update: publicProcedure + .input( + z.object({ + urlId: z.string(), + title: z.string().optional(), + timeZone: z.string().optional(), + location: z.string().optional(), + description: z.string().optional(), + optionsToDelete: z.string().array().optional(), + optionsToAdd: z.string().array().optional(), + notifications: z.boolean().optional(), + closed: z.boolean().optional(), + }), + ) + .mutation(async ({ input }): Promise => { const pollId = await getPollIdFromAdminUrlId(input.urlId); if (input.optionsToDelete && input.optionsToDelete.length > 0) { @@ -241,22 +242,24 @@ export const legacyPolls = createRouter() }); return { ...poll }; - }, - }) - .mutation("delete", { - input: z.object({ - urlId: z.string(), }), - resolve: async ({ input: { urlId } }) => { + delete: publicProcedure + .input( + z.object({ + urlId: z.string(), + }), + ) + .mutation(async ({ input: { urlId } }) => { const pollId = await getPollIdFromAdminUrlId(urlId); await prisma.poll.delete({ where: { id: pollId } }); - }, - }) - .mutation("touch", { - input: z.object({ - pollId: z.string(), }), - resolve: async ({ input: { pollId } }) => { + touch: publicProcedure + .input( + z.object({ + pollId: z.string(), + }), + ) + .mutation(async ({ input: { pollId } }) => { await prisma.poll.update({ where: { id: pollId, @@ -265,10 +268,12 @@ export const legacyPolls = createRouter() touchedAt: new Date(), }, }); - }, - }); - -export const poll = router({ + }), + demo, + participants, + comments, + verification, + // END LEGACY ROUTES getByAdminUrlId: publicProcedure .input( z.object({ diff --git a/src/server/routers/polls/comments.ts b/src/server/routers/polls/comments.ts index e8827b2e7..a6332b522 100644 --- a/src/server/routers/polls/comments.ts +++ b/src/server/routers/polls/comments.ts @@ -3,14 +3,16 @@ import { z } from "zod"; import { prisma } from "~/prisma/db"; import { sendNotification } from "../../../utils/api-utils"; -import { createRouter } from "../../createRouter"; +import { publicProcedure, router } from "../../trpc"; -export const comments = createRouter() - .query("list", { - input: z.object({ - pollId: z.string(), - }), - resolve: async ({ input: { pollId } }) => { +export const comments = router({ + list: publicProcedure + .input( + z.object({ + pollId: z.string(), + }), + ) + .query(async ({ input: { pollId } }) => { return await prisma.comment.findMany({ where: { pollId }, orderBy: [ @@ -19,15 +21,16 @@ export const comments = createRouter() }, ], }); - }, - }) - .mutation("add", { - input: z.object({ - pollId: z.string(), - authorName: z.string(), - content: z.string(), }), - resolve: async ({ ctx, input: { pollId, authorName, content } }) => { + add: publicProcedure + .input( + z.object({ + pollId: z.string(), + authorName: z.string(), + content: z.string(), + }), + ) + .mutation(async ({ ctx, input: { pollId, authorName, content } }) => { const user = ctx.session.user; const newComment = await prisma.comment.create({ @@ -45,14 +48,15 @@ export const comments = createRouter() }); return newComment; - }, - }) - .mutation("delete", { - input: z.object({ - pollId: z.string(), - commentId: z.string(), }), - resolve: async ({ input: { pollId, commentId } }) => { + delete: publicProcedure + .input( + z.object({ + pollId: z.string(), + commentId: z.string(), + }), + ) + .mutation(async ({ input: { pollId, commentId } }) => { await prisma.comment.delete({ where: { id_pollId: { @@ -61,5 +65,5 @@ export const comments = createRouter() }, }, }); - }, - }); + }), +}); diff --git a/src/server/routers/polls/demo.ts b/src/server/routers/polls/demo.ts index 864e29d3c..ac29e5741 100644 --- a/src/server/routers/polls/demo.ts +++ b/src/server/routers/polls/demo.ts @@ -4,7 +4,7 @@ import dayjs from "dayjs"; import { prisma } from "~/prisma/db"; import { nanoid } from "../../../utils/nanoid"; -import { createRouter } from "../../createRouter"; +import { publicProcedure, router } from "../../trpc"; const participantData: Array<{ name: string; votes: VoteType[] }> = [ { @@ -27,8 +27,8 @@ const participantData: Array<{ name: string; votes: VoteType[] }> = [ const optionValues = ["2022-12-14", "2022-12-15", "2022-12-16", "2022-12-17"]; -export const demo = createRouter().mutation("create", { - resolve: async () => { +export const demo = router({ + create: publicProcedure.mutation(async () => { const adminUrlId = await nanoid(); const demoUser = { name: "John Example", email: "noreply@rallly.co" }; @@ -111,5 +111,5 @@ export const demo = createRouter().mutation("create", { }); return adminUrlId; - }, + }), }); diff --git a/src/server/routers/polls/participants.ts b/src/server/routers/polls/participants.ts index 629ac2a24..17b3da99c 100644 --- a/src/server/routers/polls/participants.ts +++ b/src/server/routers/polls/participants.ts @@ -3,14 +3,16 @@ import { z } from "zod"; import { prisma } from "~/prisma/db"; import { sendNotification } from "../../../utils/api-utils"; -import { createRouter } from "../../createRouter"; +import { publicProcedure, router } from "../../trpc"; -export const participants = createRouter() - .query("list", { - input: z.object({ - pollId: z.string(), - }), - resolve: async ({ input: { pollId } }) => { +export const participants = router({ + list: publicProcedure + .input( + z.object({ + pollId: z.string(), + }), + ) + .query(async ({ input: { pollId } }) => { const participants = await prisma.participant.findMany({ where: { pollId, @@ -26,33 +28,35 @@ export const participants = createRouter() ], }); return participants; - }, - }) - .mutation("delete", { - input: z.object({ - pollId: z.string(), - participantId: z.string(), }), - resolve: async ({ input: { participantId } }) => { + delete: publicProcedure + .input( + z.object({ + pollId: z.string(), + participantId: z.string(), + }), + ) + .mutation(async ({ input: { participantId } }) => { await prisma.participant.delete({ where: { id: participantId, }, }); - }, - }) - .mutation("add", { - input: z.object({ - pollId: z.string(), - name: z.string().nonempty("Participant name is required"), - votes: z - .object({ - optionId: z.string(), - type: z.enum(["yes", "no", "ifNeedBe"]), - }) - .array(), }), - resolve: async ({ ctx, input: { pollId, votes, name } }) => { + add: publicProcedure + .input( + z.object({ + pollId: z.string(), + name: z.string().nonempty("Participant name is required"), + votes: z + .object({ + optionId: z.string(), + type: z.enum(["yes", "no", "ifNeedBe"]), + }) + .array(), + }), + ) + .mutation(async ({ ctx, input: { pollId, votes, name } }) => { const user = ctx.session.user; const participant = await prisma.participant.create({ data: { @@ -80,20 +84,21 @@ export const participants = createRouter() }); return participant; - }, - }) - .mutation("update", { - input: z.object({ - pollId: z.string(), - participantId: z.string(), - votes: z - .object({ - optionId: z.string(), - type: z.enum(["yes", "no", "ifNeedBe"]), - }) - .array(), }), - resolve: async ({ input: { pollId, participantId, votes } }) => { + update: publicProcedure + .input( + z.object({ + pollId: z.string(), + participantId: z.string(), + votes: z + .object({ + optionId: z.string(), + type: z.enum(["yes", "no", "ifNeedBe"]), + }) + .array(), + }), + ) + .mutation(async ({ input: { pollId, participantId, votes } }) => { const participant = await prisma.participant.update({ where: { id: participantId, @@ -118,5 +123,5 @@ export const participants = createRouter() }); return participant; - }, - }); + }), +}); diff --git a/src/server/routers/polls/verification.ts b/src/server/routers/polls/verification.ts index 636eebeb8..99fb6a176 100644 --- a/src/server/routers/polls/verification.ts +++ b/src/server/routers/polls/verification.ts @@ -11,15 +11,17 @@ import { decryptToken, mergeGuestsIntoUser, } from "../../../utils/auth"; -import { createRouter } from "../../createRouter"; +import { publicProcedure, router } from "../../trpc"; -export const verification = createRouter() - .mutation("verify", { - input: z.object({ - pollId: z.string(), - code: z.string(), - }), - resolve: async ({ ctx, input }) => { +export const verification = router({ + verify: publicProcedure + .input( + z.object({ + pollId: z.string(), + code: z.string(), + }), + ) + .mutation(async ({ ctx, input }) => { const { pollId } = await decryptToken<{ pollId: string; }>(input.code); @@ -52,14 +54,15 @@ export const verification = createRouter() isGuest: false, }; await ctx.session.save(); - }, - }) - .mutation("request", { - input: z.object({ - pollId: z.string(), - adminUrlId: z.string(), }), - resolve: async ({ input: { pollId, adminUrlId } }) => { + request: publicProcedure + .input( + z.object({ + pollId: z.string(), + adminUrlId: z.string(), + }), + ) + .mutation(async ({ input: { pollId, adminUrlId } }) => { const poll = await prisma.poll.findUnique({ where: { id: pollId, @@ -96,5 +99,5 @@ export const verification = createRouter() supportEmail: process.env.SUPPORT_EMAIL, }, }); - }, - }); + }), +}); diff --git a/src/server/routers/user.ts b/src/server/routers/user.ts index c0fbd6da3..2c0b96f44 100644 --- a/src/server/routers/user.ts +++ b/src/server/routers/user.ts @@ -4,7 +4,7 @@ import { z } from "zod"; import { prisma } from "~/prisma/db"; -import { createRouter } from "../createRouter"; +import { publicProcedure, router } from "../trpc"; const requireUser = (user: IronSessionData["user"]) => { if (!user) { @@ -16,42 +16,42 @@ const requireUser = (user: IronSessionData["user"]) => { return user; }; -export const user = createRouter() - .query("getPolls", { - resolve: async ({ ctx }) => { - const user = requireUser(ctx.session.user); - const userPolls = await prisma.user.findUnique({ - where: { - id: user.id, - }, - select: { - polls: { - where: { - deleted: false, - }, - select: { - title: true, - closed: true, - verified: true, - createdAt: true, - adminUrlId: true, - }, - take: 10, - orderBy: { - createdAt: "desc", - }, +export const user = router({ + getPolls: publicProcedure.query(async ({ ctx }) => { + const user = requireUser(ctx.session.user); + const userPolls = await prisma.user.findUnique({ + where: { + id: user.id, + }, + select: { + polls: { + where: { + deleted: false, + }, + select: { + title: true, + closed: true, + verified: true, + createdAt: true, + adminUrlId: true, + }, + take: 10, + orderBy: { + createdAt: "desc", }, }, - }); - return userPolls; - }, - }) - .mutation("changeName", { - input: z.object({ - userId: z.string(), - name: z.string().min(1).max(100), - }), - resolve: async ({ input }) => { + }, + }); + return userPolls; + }), + changeName: publicProcedure + .input( + z.object({ + userId: z.string(), + name: z.string().min(1).max(100), + }), + ) + .mutation(async ({ input }) => { await prisma.user.update({ where: { id: input.userId, @@ -60,5 +60,5 @@ export const user = createRouter() name: input.name, }, }); - }, - }); + }), +}); diff --git a/src/utils/trpc.ts b/src/utils/trpc.ts index d9e035ece..ad5c2397d 100644 --- a/src/utils/trpc.ts +++ b/src/utils/trpc.ts @@ -1,15 +1,12 @@ import { MutationCache } from "@tanstack/react-query"; import { httpBatchLink } from "@trpc/client"; import { createTRPCNext } from "@trpc/next"; -import { createReactQueryHooks } from "@trpc/react-query"; import toast from "react-hot-toast"; import superjson from "superjson"; import { AppRouter } from "../server/routers/_app"; -export const trpc = createReactQueryHooks(); - -export const trpcNext = createTRPCNext({ +export const trpc = createTRPCNext({ unstable_overrides: { useMutation: { async onSuccess(opts) { diff --git a/src/utils/trpc/types.ts b/src/utils/trpc/types.ts index 36906c3e6..1d2b8feaf 100644 --- a/src/utils/trpc/types.ts +++ b/src/utils/trpc/types.ts @@ -17,4 +17,5 @@ export type GetPollApiResponse = { demo: boolean; notifications: boolean; createdAt: Date; + deleted: boolean; }; diff --git a/yarn.lock b/yarn.lock index d70b1d0be..e9310ca96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2028,27 +2028,27 @@ "@tanstack/query-core" "4.24.4" use-sync-external-store "^1.2.0" -"@trpc/client@^10.0.0-rc.8": - version "10.0.0-rc.8" - resolved "https://registry.yarnpkg.com/@trpc/client/-/client-10.0.0-rc.8.tgz#2b6b0db8ec41e4403b72d25d37a2cd9d6c6c1257" - integrity sha512-NuQl7g1tkfFYn6P6dZJJkVsxnxutYpaxmpG/w5ZKW3QVu6cY1joUOrWakunKrghh3HS+svgLaPz0Xl0PlmdSlw== +"@trpc/client@^10.13.0": + version "10.13.0" + resolved "https://registry.yarnpkg.com/@trpc/client/-/client-10.13.0.tgz#8999a7ba068a684629071b77a07c00a141585eca" + integrity sha512-r4KuN0os2J194lxg5jn4+o3uNlqunLFYptwTHcVW4Q0XGO0ZoTKLHuxT7c9IeDivkAs6G5oVEPiKhptkag36dQ== -"@trpc/next@^10.0.0-rc.8": - version "10.0.0-rc.8" - resolved "https://registry.yarnpkg.com/@trpc/next/-/next-10.0.0-rc.8.tgz#78a4acc4404c3a8295f0b0a8da4e2c89b21e1366" - integrity sha512-l2TZF22virmC3RROD7qu0dnc3sdYfVvkOhAu1qP5+8fRgs4cgHKBFdalQ+SKBnU0RNuVLYVw0CkyvU+gHo5u2w== +"@trpc/next@^10.13.0": + version "10.13.0" + resolved "https://registry.yarnpkg.com/@trpc/next/-/next-10.13.0.tgz#64393f0d8dbfae7d87e54260dea532702bd1ecdf" + integrity sha512-Q4rnuuiSUXDYv34f8FNUKhEMQFgLJTTJean78YjhG3Aaci+r4sew4hPmRvDRut8fBpa+EtExq+dv1EUbzlXgJg== dependencies: react-ssr-prepass "^1.5.0" -"@trpc/react-query@^10.0.0-rc.8": - version "10.0.0-rc.8" - resolved "https://registry.yarnpkg.com/@trpc/react-query/-/react-query-10.0.0-rc.8.tgz#68957743cd99e9c97fb167fb955b00bd1f9010e2" - integrity sha512-LKL29llvGtwYmfKGuCYSgNNChOL8/6PInY90i+ZgI8TLO6ZCJaVrPBSvqtxKj3MSezbK3kOxWIviKVFwV35L0A== +"@trpc/react-query@^10.13.0": + version "10.13.0" + resolved "https://registry.yarnpkg.com/@trpc/react-query/-/react-query-10.13.0.tgz#ca5a1da0ea126976d7435775f2ba1846cb7fad59" + integrity sha512-y4jbojrDFdEl1KBejBoMWIofcUXDHQA8wf01eKMEDV7Jwc7lhq6R1dxYtKzeF+s5wqfnPWFOGZDmB3flzv07Dw== -"@trpc/server@^10.0.0-rc.8": - version "10.0.0-rc.8" - resolved "https://registry.yarnpkg.com/@trpc/server/-/server-10.0.0-rc.8.tgz#941cb4b06a2d59419bdbcc61241f1e8946b67a1e" - integrity sha512-+NsQqaJGHTiiBcOesH1bIictnnSO+SXaCOy5pM/324QBnJRt9VOO8oYDLcHSwAbJpAbOA+vl6YHs8OoykW6D2g== +"@trpc/server@^10.13.0": + version "10.13.0" + resolved "https://registry.yarnpkg.com/@trpc/server/-/server-10.13.0.tgz#0945b5210a18934c2284c8679cb6692ecb5b054c" + integrity sha512-d/bu6utCC4ALxhTJkolEPAHMOSuCAu3mG79TZswa6wD2ob0/Z3AIvBF/meeSTqDxe4tvXY78lQqOkQI81dgi/g== "@trysound/sax@0.2.0": version "0.2.0"