KevinEdry / nestjs-trpc

Providing native support for decorators and implement an opinionated approach that aligns with NestJS conventions.
https://NestJS-tRPC.io
MIT License
70 stars 6 forks source link

trpc `Unsupported POST-request to query procedure` when using `mutation` #6

Closed Mnigos closed 1 month ago

Mnigos commented 1 month ago

I got trpc error when trying to use trpc.thought.create.mutate

Error: Unsupported POST-request to query procedure at path "thought.create"

thought.router

@Router({ alias: 'thought' })
export class ThoughtRouter {
  constructor(private readonly prisma: PrismaService) {}

  @Mutation({ input: createThoughtSchema, output: thoughtSchema })
  async create(
    @Input('content') content: Thought['content'],
    @Input('authorId') authorId: Thought['authorId']
  ) {
    const { id } = await this.prisma.thought.create({
      data: {
        content,
        authorId,
      },
    })

    return this.prisma.thought.findUnique({
      where: {
        id,
      },
      select: {
        id: true,
        content: true,
        author: true,
        createdAt: true,
      },
    })
  }
}

server.ts

import { initTRPC } from "@trpc/server";
import { z } from "zod";

const t = initTRPC.create();
const publicProcedure = t.procedure;

const appRouter = t.router({
  thought: t.router({
    create: publicProcedure.input(thoughtSchema
      .pick({
        content: true,
      })
      .extend({
        authorId: z.string(),
      })).output(z.object({
        id: z.string(),
        content: z.string(),
        author: userSchema,
        createdAt: z.date(),
      })).mutation(async () => "PLACEHOLDER_DO_NOT_REMOVE" as any)
  })
});

export type AppRouter = typeof appRouter;

And usage inside nextjs app

trpc.ts

import { createTRPCClient, httpBatchLink } from '@trpc/client'

import type { AppRouter } from '../../api'

import { env } from './env'

export const trpc = createTRPCClient<AppRouter>({
  links: [
    httpBatchLink({
      url: `${env.API_URL}/trpc`,
    }),
  ],
})

page.tsx

export default async function ThoughtsPage() {
  async function handleSubmit(formData: FormData) {
    'use server'

    const content = formData.get('content')?.toString()
    const authorId = cookies().get('username')?.value

    if (!content || !authorId) return

    const newThought = await trpc.thought.create.mutate({
      content,
      authorId,
    })

    revalidateTag('thoughts')
  }

  return (
    <div className="p-4">
      <div className="mx-auto max-w-[1100px]">
        <form className="flex flex-col gap-2" action={handleSubmit}>
          <Textarea placeholder="Write your thought..." name="content" />

          <div className="flex justify-end">
            <Button type="submit">Submit</Button>
          </div>
        </form>
      </div>
    </div>
  )
}
KevinEdry commented 1 month ago

Which trpc version are you running?

Mnigos commented 1 month ago

nestjs app:

    "@trpc/server": "^11.0.0-rc.532",

nextjs app:

    "@trpc/client": "^11.0.0-rc.532",
KevinEdry commented 1 month ago

This library supports trpc 10, since 11 was still in preview when I stated development, and it seems like you are using a RC version which is never recommended for any production application. CleanShot 2024-09-28 at 08 11 36

Also the vast majority of trpc users uses the 10 version as of this moment.

Since TRPC 11 has some breaking changes between the two, specifically how you merge routers, I can't change the code to accommodate both, are you able to downgrade?

Mnigos commented 1 month ago

This library supports trpc 10, since 11 was still in preview when I stated development, and it seems like you are using a RC version which is never recommended for any production application. CleanShot 2024-09-28 at 08 11 36

Also the vast majority of trpc users uses the 10 version as of this moment.

Since TRPC 11 has some breaking changes between the two, specifically how you merge routers, I can't change the code to accommodate both, are you able to downgrade?

Sure, I will try to downgrade and let you know if it resolves my issue.

Mnigos commented 1 month ago

Similar error, but different message.

Error: No "mutation"-procedure on path "thought.create"

trpc.ts

import { createTRPCProxyClient, httpBatchLink } from '@trpc/client'

import type { AppRouter } from '../../api'

import { env } from './env'

export const trpc = createTRPCProxyClient<AppRouter>({
  links: [
    httpBatchLink({
      url: `${env.API_URL}/trpc`,
    }),
  ],
})

actions.ts


export async function createThought(content: string) {
  const { id: authorId } = await getCurrentUser()

  const newThought = await trpc.thought.create.mutate({
    content,
    authorId,
  })

  revalidateTag('thoughts')

  return newThought
}

thought.router.ts

@Router({ alias: 'thought' })
export class ThoughtRouter {
  constructor(private readonly prisma: PrismaService) {}

  @Mutation({ input: createThoughtSchema, output: thoughtSchema })
  async create(
    @Input('content') content: Thought['content'],
    @Input('authorId') authorId: Thought['authorId']
  ) {
    const { id } = await this.prisma.thought.create({
      data: {
        content,
        author: {
          connect: {
            id: authorId,
          },
        },
      },
    })

    return this.prisma.thought.findUnique({
      where: {
        id,
      },
      select: {
        id: true,
        content: true,
        author: true,
        createdAt: true,
      },
    })
  }
}

server.ts

import { initTRPC } from "@trpc/server";
import { z } from "zod";

const t = initTRPC.create();
const publicProcedure = t.procedure;

const appRouter = t.router({
  thought: t.router({
    create: publicProcedure.input(thoughtSchema
      .pick({
        content: true,
      })
      .extend({
        authorId: z.string(),
      })).output(z.object({
        id: z.string(),
        content: z.string(),
        author: userSchema,
        createdAt: z.date(),
      })).mutation(async () => "PLACEHOLDER_DO_NOT_REMOVE" as any),
});
export type AppRouter = typeof appRouter;

trpc@10.45.2

KevinEdry commented 1 month ago

Found the issue, a PR is up, will be fixed once it's merged.

Mnigos commented 1 month ago

And now it works even with trpc v11.