End-to-end typesafe APIs with tRPC.io in Nuxt applications.

Related tags

Vue.js vue nuxt trpc
Overview

tRPC-Nuxt

Version

End-to-end typesafe APIs with tRPC.io in Nuxt applications.

Demo

The client above is not importing any code from the server, only its type declarations.

Install

npm i trpc-nuxt
// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'

export default defineNuxtConfig({
  modules: ['trpc-nuxt'],
  trpc: {
    baseURL: 'http://localhost:3000', // defaults to http://localhost:3000
    trpcURL: '/api/trpc', // defaults to /api/trpc
  },
  typescript: {
    strict: true // set this to true to make input/output types work
  }
})

Usage

Expose your tRPC routes under ~/server/trpc/index.ts:

// ~/server/trpc/index.ts
import type { inferAsyncReturnType } from '@trpc/server'
import * as trpc from '@trpc/server'
import { z } from 'zod' //  yup/superstruct/zod/myzod/custom

export const router = trpc.router()
  // queries and mutations...
  .query('getUsers', {
    async resolve(req) {
      // use your ORM of choice
      return await UserModel.all()
    },
  })
  .mutation('createUser', {
    // validate input with Zod
    input: z.object({ name: z.string().min(5) }),
    async resolve(req) {
      // use your ORM of choice
      return await UserModel.create({
        data: req.input,
      })
    },
  })

Use the client like so:

const client = useClient() // auto-imported

const users = await client.query('getUsers')

const newUser = await client.mutation('createUser', {
  name: 'wagmi'
})

useAsyncQuery

A thin wrapper around useAsyncData and client.query().

The first argument is a [path, input]-tuple - if the input is optional, you can omit the, input-part.

You'll notice that you get autocompletion on the path and automatic typesafety on the input.

const {
  data,
  pending,
  error,
  refresh
} = await useAsyncQuery(['getUser', { id: 69 }], {
  // pass useAsyncData options here
  lazy: false
})

Options

trpc-nuxt accepts the following options exposed under ~/server/trpc/index.ts:

import * as trpc from '@trpc/server'
import type { inferAsyncReturnType } from '@trpc/server'
import type { CompatibilityEvent } from 'h3'
import type { OnErrorPayload } from 'trpc-nuxt/api'

export const router = trpc.router<inferAsyncReturnType<typeof createContext>>()

// Optional
// https://trpc.io/docs/context
export const createContext = (event: CompatibilityEvent) => {
  // ...
  return {
    /** context data */
  }
}

// Optional
// https://trpc.io/docs/caching#using-responsemeta--to-cache-responses
export const responseMeta = () => {
  // ...
  return {
    // { headers: ... }
  }
}

// Optional
// https://trpc.io/docs/error-handling#handling-errors
export const onError = (payload: OnErrorPayload<typeof router>) => {
  // Do whatever here like send to bug reporting and stuff
}

Recipes

Learn more about tRPC.io here.

Recommended IDE Setup

License

MIT

Comments
  • Cannot stringify arbitrary non-POJOs TRPCClientError

    Cannot stringify arbitrary non-POJOs TRPCClientError

    I always get this error: Cannot stringify arbitrary non-POJOs TRPCClientError

    Here are my files: ~/server/api/trpc/index.ts

    import type { inferAsyncReturnType } from '@trpc/server'
    import * as trpc from '@trpc/server'
    import * as  z  from 'zod'
    import type { OnErrorPayload } from 'trpc-nuxt/api'
    
    import * as PrismaPkg from '@prisma/client'
    const {PrismaClient} = PrismaPkg
    const client = new PrismaClient()
    
    
    export const router = trpc.router()
        // queries and mutations...
        .query('hello',{
        // validate input with Zod
            async resolve(req) {
            console.log(req)
            // use your ORM of choice
            return {
                message: `Hello`
            }
        },
    })
    
    

    ~/pages/index.vue

    <script setup lang="ts">
    import MyButton from '@/components/MyButton.vue'
    import {useAsyncQuery, useFetch} from "#imports";
    const router = useRouter()
    
    const {data} = await useAsyncQuery(["hello"]);
    </script>
    
    <template>
      <NuxtLayout name="home">
        <section class="flex flex-col h-max justify-center">
          <div class="bg-primary-600 rounded-lg p-10 text-white text-2xl" >{{data}}</div>
          [...]
        </section>
      <NuxtLayout name="home">
    </template>
    

    Looking at the error message, seems to be that my trpc endpoint is refusing connections.

    TRPCClientError: request to http://localhost:3000/trpc/hello?batch=1&input=%7B%7D failed, reason: connect ECONNREFUSED ::1:3000
        at Function.from (file:///Users/jean-emrickrioux/Dev/stakeFrites/_tools/trakmos-project/trakmos-nuxt/.nuxt/dist/server/server.mjs:33400:14)
        at file:///Users/jean-emrickrioux/Dev/stakeFrites/_tools/trakmos-project/trakmos-nuxt/.nuxt/dist/server/server.mjs:34021:42
        at processTicksAndRejections (node:internal/process/task_queues:96:5) {
      originalError: FetchError: request to http://localhost:3000/trpc/hello?batch=1&input=%7B%7D failed, reason: connect ECONNREFUSED ::1:3000
          at ClientRequest.<anonymous> (file:///Users/jean-emrickrioux/Dev/stakeFrites/_tools/trakmos-project/trakmos-nuxt/node_modules/node-fetch/src/index.js:108:11)
          at ClientRequest.emit (node:events:527:28)
          at Socket.socketErrorListener (node:_http_client:454:9)
          at Socket.emit (node:events:527:28)
          at emitErrorNT (node:internal/streams/destroy:164:8)
          at emitErrorCloseNT (node:internal/streams/destroy:129:3)
          at processTicksAndRejections (node:internal/process/task_queues:83:21) 
    

    Second try:

    Changed the trpc directory to ~/server/api/trpc

       [nuxt] [request error] Invalid lazy handler result. It should be a function:
      at ./node_modules/h3/dist/index.mjs:299:17  
      at processTicksAndRejections (node:internal/process/task_queues:96:5)  
      at async ./node_modules/h3/dist/index.mjs:420:19  
      at async Server.nodeHandler (./node_modules/h3/dist/index.mjs:370:7)
    
    

    My changed nuxt.config.ts looks like this:

    export default defineNuxtConfig({
    trpc: {
        baseURL: 'http://localhost:3000/api', // defaults to http://localhost:3000
        endpoint: '/trpc', // defaults to /trpc
      },
    }
    
    opened by jemrickrioux 17
  • V10 support

    V10 support

    With a trpc v10 stable release on the horizon I think we should be able to use v10 in our Nuxtjs projects. Possibly adding a next or v10 branch and adding another package to npmjs would be advisable.

    Regards, juls0730 [email protected]

    opened by juls0730 9
  • Not working on Cloudflare Workers

    Not working on Cloudflare Workers

    It's not possible to run this when deployed on Cloudflare Workers. I'm getting the error global is not defined. Might have something to do with how the fetch workers there. Maybe this two repos could be of help to solve the problem.

    https://github.com/esamattis/trpc-cloudflare-worker https://github.com/valu-digital/npm-packages/tree/master/packages/trpc-fetch-api-adapter

    opened by essarn 7
  • v0.1.22 input typing and useStorage error

    v0.1.22 input typing and useStorage error

    After updating to v0.1.22 (Thank you for the quick fix). Typings for useAsyncQuery and useClient are now back, but input params are somehow undefined as shown in picture 1.

    Picture 2 depicts useStorage error when running in dev though I'm not even using useRequestHeaders. This is now a breaking change and I have to revert trpc-nuxt back to the last version.

    Both errors persist after clean install of dependencies.

    image image

    opened by duykamke 6
  • Features/Milestones for trpc-nuxt v1.0.0

    Features/Milestones for trpc-nuxt v1.0.0

    Hey! I just have some questions about if there is a plan to integrate this as an official adapter package for nuxt e.g. @trpc/nuxt since I don't see any other similar open source projects that do the same thing. It's definitely very difficult to maintain these amazing projects, so I just wanted to set my expectations right since I'm only really just using it and trying things out and not working on it myself. I completely understand if there's no plans for anything at all.

    Anyways, TLDR: wanted to try and build a chat app for fun and found some lacking things/wishlist of some of the things/issues I was wondering if it would be implemented (again, I don't know how difficult these things would be, so it's just a daydream of mines if you can forgive me for saying):

    • Integration for using with dbs/Prisma? Trying this right now, though it doesn't seem to work, maybe I'm just dumb or I think this might require something from the plugin? (Edit: Prisma works, I was just being dumb with the integration)
    • Subscriptions/Websockets support? Definitely something on my wishlist if I'm planning on doing real-time things
    • Which leads to needing things like integrating packages like superjson for Dates etc from Prisma

    I can add more if I find any, but these were some of the things I found were a bit more important since I want to continue using trpc-nuxt, thanks for listening to my blabber tho!

    opened by Q16solver 5
  • client.mutation input is undefined

    client.mutation input is undefined

    • trpc-nuxt v0.1.23 - v0.2.0
    • npm latest

    When calling mutation using useClient from client-side/frontend part of a project with input, the input is somehow undefined on the server.

    Client: image If the object input is set to be required using zod, console.log above output:

    [
      {
        "code": "invalid_type",
        "expected": "object",
        "received": "undefined",
        "path": [],
        "message": "Required"
      }
    ]
    

    Server: image

    if the object input is set to be optional using zod, console.log above output undefined

    opened by duykamke 5
  • Have default query/mutate api match trpc behaviour

    Have default query/mutate api match trpc behaviour

    Hey! Congrats on the v0.4 release! I'm not sure if you had time to read out some of the issues I commented on the PR, so I'll raise it here for more visibility

    Hello! First of all, amazing work! I've been trying it out and testing it and rewriting all my api endpoints. I have a question about how the useAsyncData under the hood works. Since it's always async, that means that after querying/mutating, the data object that gets returned could be null and doesn't immediately get the result after awaiting? If I have an onClick that calls this, will it be able to actually get the data back instead of null (also doesn't this mean I have to always do null if checks).

    I think this is a little different from how the previous client.query in trpc-nuxt v0.3 worked, and if I called await on that, it would always return the exact type of the result, did that also useAsyncData under the hood? If not, perhaps we can have default behaviour being the same thing so it's simpler, and useAsyncData being a separate api to call if we need data, pending, error.. etc

    image image

    opened by Q16solver 3
  • feat: use globalThis.$fetch to call API handler directly on server-side

    feat: use globalThis.$fetch to call API handler directly on server-side

    Resolve #4 and #14.

    Theoretically, just by setting fetch as globalThis.$fetch.raw when invoking createTRPCClient method will do the trick.

    const client = trpc.createTRPCClient<AppRouter>({
      ...,
      fetch: globalThis.$fetch.raw,
    })
    

    However, ohmyfetch always try to parse response body before returning FetchResponse, which leads to error when trpc client calls response.json() since response body has already been used. So we provide a fake json method returning the parsed JSON.

    fetch: (input, options) => 
      globalThis.$fetch.raw(input.toString(), options).then(response => ({
        ...response,
        json: () => Promise.resolve(response._data),
      }))
    

    ohmyfetch behaves differently with Fetch API when server returns an error (like HTTP 401 and 500). Fetch API returns the response normally while ohmyfetch throws a custom error. Here we catch the FetchError thrown by ohmyfetch so that TRPC client can handle such errors as expected, like parsing the TRPC error shape.

    fetch: (input, options) => 
      globalThis.$fetch.raw(input.toString(), options)
        .catch((e) => {
          if (e instanceof FetchError && e.response)
            return e.response
    
            throw e
          })
    

    Nuxt uses the first letter (/) of request url to determine whether to perform a real fetch or just to call API handler directly. So it's necessary to set baseURL as empty string to make sure the request url starts with a '/' when fetching on server-side.

    opened by robinWongM 3
  • any Cannot find name 'useClient'. No typesaftey on requests either

    any Cannot find name 'useClient'. No typesaftey on requests either

    So I'm trying to use trpc in nuxt and I have been having problems with typesaftey, my package.json looks like this:

    {
      "private": true,
      "scripts": {
        "dev": "nuxi dev",
        "build": "nuxi build",
        "prepare": "nuxi prepare"
      },
      "devDependencies": {
        "@nuxtjs/tailwindcss": "^5.3.1",
        "@types/bcryptjs": "^2.4.2",
        "@types/jsonwebtoken": "^8.5.8",
        "autoprefixer": "^10.4.8",
        "nuxt": "^3.0.0-rc.5",
        "postcss": "^8.4.14",
        "prisma": "^4.1.1",
        "tailwindcss": "^3.1.7",
        "trpc-nuxt": "0.2.4",
        "zod": "3.17.10"
      },
      "dependencies": {
        "@nuxt/kit": "^3.0.0-rc.5",
        "@prisma/client": "4.1.1",
        "@trpc/client": "^9.27.0",
        "@trpc/server": "^9.27.0",
        "@vueuse/core": "^9.1.0",
        "@vueuse/nuxt": "^9.1.0",
        "bcryptjs": "^2.4.3",
        "dotenv": "^16.0.1",
        "jsonwebtoken": "^8.5.1"
      }
    }
    

    On my client useClient() or useAsyncQuery() are both undefined and whenever I get them there is zero typesaftey, no checking if the method exists and no checking if I send the correct input etc etc ect.

    opened by juls0730 3
  • trpc useAsyncQuery/Any query fails with Node.js 18

    trpc useAsyncQuery/Any query fails with Node.js 18

    Hey! This is a great library that I was trying out with nuxt.js and integrating it, but it was not working for me and after several hours of investigating, it seems like the reason is due to Node.js 18 which brought in the new fetch API, I checked that it's working in Node.js 16, though not sure what the problem is. Hope this can be fixed within this package and that it's not something inherently wrong with nodejs, otherwise please feel free to just close this issue. Here's the stack trace I had from doing client.query

    Stack Trace:

    TRPCClientError2: fetch failed at Function.from (file:///.../.output/server/chunks/app/server.mjs:5075:14) at file:///.../.output/server/chunks/app/server.mjs:5667:34 { originalError: TypeError: fetch failed at Object.processResponse (node:internal/deps/undici/undici:5555:34) at node:internal/deps/undici/undici:5877:42 at node:internal/process/task_queues:140:7 at AsyncResource.runInAsyncScope (node:async_hooks:203:9) at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8) { cause: InvalidArgumentError: invalid connection header at processHeader (node:internal/deps/undici/undici:2082:15) at new Request (node:internal/deps/undici/undici:1965:13) at [dispatch] (node:internal/deps/undici/undici:2891:25) at Client.dispatch (node:internal/deps/undici/undici:408:33) at [dispatch] (node:internal/deps/undici/undici:627:32) at Pool.dispatch (node:internal/deps/undici/undici:408:33) at [dispatch] (node:internal/deps/undici/undici:4174:27) at Agent.dispatch (node:internal/deps/undici/undici:408:33) at node:internal/deps/undici/undici:6255:83 at new Promise () { code: 'UND_ERR_INVALID_ARG' } }, shape: undefined, data: undefined, isDone: false, [cause]: TypeError: fetch failed at Object.processResponse (node:internal/deps/undici/undici:5555:34) at node:internal/deps/undici/undici:5877:42 at node:internal/process/task_queues:140:7 at AsyncResource.runInAsyncScope (node:async_hooks:203:9) at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8) { cause: InvalidArgumentError: invalid connection header at processHeader (node:internal/deps/undici/undici:2082:15) at new Request (node:internal/deps/undici/undici:1965:13) at [dispatch] (node:internal/deps/undici/undici:2891:25) at Client.dispatch (node:internal/deps/undici/undici:408:33) at [dispatch] (node:internal/deps/undici/undici:627:32) at Pool.dispatch (node:internal/deps/undici/undici:408:33) at [dispatch] (node:internal/deps/undici/undici:4174:27) at Agent.dispatch (node:internal/deps/undici/undici:408:33) at node:internal/deps/undici/undici:6255:83 at new Promise () { code: 'UND_ERR_INVALID_ARG' } } } [Vue warn]: Component is missing template or render function. [nuxt] [request error] fetch failed at Function.from (./server/chunks/app/server.mjs:5075:14)
    at ./server/chunks/app/server.mjs:5667:34

    opened by Q16solver 3
  • TRPC URL should be relative by default

    TRPC URL should be relative by default

    export default defineNuxtConfig({
      trpc: {
        baseURL: 'http://localhost:3000/', // <--
        trpcURL: '/api/trpc',
      },
    })
    

    This does not allow you to change the URI to the server depending on the environment.

    • Port 3000 may be busy and nuxt will start on port 3001, or 3002, or 3003 ...
    • You open dev server by IP
    • The application can be deployed on different servers for testing. It is not always known in advance on which host, port, protocol it will work.

    In all these cases, the use of the absolute URL http://localhost:3000/api/trpc as default leads to problems. The default URL must be relative /api/trpc to make calls to the current host, no matter what it is.

    opened by cawa-93 3
  • [Question]: Is it possible to have global error handling for redirecting unauthorised requests?

    [Question]: Is it possible to have global error handling for redirecting unauthorised requests?

    Hello!

    I wanted to do something similar to the pic below, but wasn't sure if that was currently possible since navigateTo doesn't exist inside the onError function. This should be something that's done like the axios interceptor where I check the code to see if it's 401 (unauthorised) or 403 (forbidden) then redirect user to login page. Was wondering if it's currently supported since I couldn't find any docs for nuxt api handler nor the links part and I think those are the only places where this seems reasonable. Other places like middleware don't seem to be the correct places to do this.

    image

    opened by Q16solver 1
  • Official recipe for websocket integration

    Official recipe for websocket integration

    Hello, I'm trying to figure out a very nice way of integrating websockets with trpc nuxt, and just looking through the docs of trpc, though it seems like it isn't as straightforward as I thought, and I'm not sure how to use it alongside with things like httpBatchLink and wsLink, the environment variables I need (seems like I need to split up with the WS base url, then the WS port so then I can pass it in http server) etc. Quite a little confused as to the proper way to set this up for production purposes and using it from client side so it would be quite helpful if we could get some help on that, much appreciated c:

    image

    opened by Q16solver 0
Releases(v0.4.4)
Owner
Robert Soriano
[object Object]
Robert Soriano
⚡️ Minimal GraphQL Client + Code Generation for Nuxt

nuxt-graphql-client ⚡️ Minimal GraphQL Client + Code Generation for Nuxt ⚡️ Minimal GraphQL Client + Code Generation for Nuxt Features Zero Configurat

Dizzy 245 Dec 27, 2022
Nuxt.js module to use Unleash toggle feature services

nuxt-unleash Nuxt.js module to use Unleash toggle feature services ?? Release Notes Features Use $unleash to access and handle your Unleash feature fl

Juanjo Conejero 15 Dec 3, 2022
Easy generation of OpenGraph & Twitter meta-tags in Nuxt 3 📋

nuxt-social-tags Easy generation of OpenGraph & Twitter meta-tags in Nuxt 3 ✨ Release Notes ?? Read the documentation Features Nuxt3 ready Composables

Conner 19 Dec 17, 2022
Easily connect your Nuxt 3 application with LogSnag 📰

Nuxt LogSnag ?? LogSnag integration for Nuxt 3 ✨ Release Notes Features Nuxt 3 ready Easy integration Handy composables TypeScript support Setup Insta

Conner 13 Apr 28, 2022
Nuxt 3 starter with Algolia, Storyblok, and Indexer

Nuxt 3 with Storyblok CMS and Algolia Search (incl. automatic indexing) This is a demo repository for an article in Dev.to. We recommend to look at th

Jakub Andrzejewski 5 May 24, 2022
A modern, zero-dependency uptime monitoring tool & status page based on GitHub Actions & Nuxt Content v2.

StatusBase Uptime monitoring tool & beautiful status pages Powered by Nuxt Content v2! Free • Open Source • Notification View Demo · Report Bug · Requ

zernonia 208 Dec 27, 2022
🔎 Algolia module for Nuxt

@nuxtjs/algolia Algolia module for Nuxt ✨ Release Notes ?? Read the documentation Features Nuxt 3 ready Easy integration with Algolia Handy composable

Nuxt Community 128 Jan 7, 2023
Nuxt 3 module for Kirby's Query Language API

nuxt-kql Kirby KQL module for Nuxt 3. This module provides a useKql composable, which under the hood uses useFetch. Thus, KQL query fetching in your N

Johann Schopplich 25 Dec 15, 2022
This repo contains a fully configured nuxt 3 instance supporting TypeScript and several considered as useful libraries, fully configured and ready to use in real world projects!

Nuxt 3 Starter This repo contains a fully configured nuxt 3 instance supporting TypeScript and several considered as useful libraries, fully configure

Ali Soueidan 26 Dec 27, 2022
Batteries-included, zero-config Ionic integration for Nuxt

Nuxt Ionic Ionic integration for Nuxt ✨ Changelog ?? Read the documentation ▶️ Online playground Features ⚠️ nuxt-ionic is currently a work in progres

Daniel Roe 211 Dec 28, 2022
Http-proxy middleware for Nuxt 3.

nuxt-proxy Http-proxy middleware for Nuxt 3. Installation npm install nuxt-proxy Usage export default defineNuxtConfig({ modules: ['nuxt-proxy'],

Robert Soriano 49 Dec 30, 2022
Nuxt 3 module for Web3.js

nuxt-web3.js Nuxt 3 module for Web3.js. Installation npm install nuxt-web3.js Usage export default defineNuxtConfig({ modules: ['nuxt-web3.js'], })

Robert Soriano 8 Dec 16, 2022
OpenID-Connect(OIDC) integration module for nuxt 3.0.

Nuxt OpenID-Connect OpenID-Connect(OIDC) integration module for nuxt 3.0. Features An Nuxt 3 module. OIDC integration ( implemetation base openid-clie

Aborn Jiang 10 Dec 24, 2022
🔎 Meilisearch module for Nuxt 3

nuxt-meilisearch Meilisearch module for Nuxt Features Nuxt 3 Easy integration with MeilisearchJS lib Support for Vue Algolia Vue 3 InstantSearch compo

Alex Duval 50 Dec 26, 2022
A modern, zero-dependency uptime monitoring tool & status page based on GitHub Actions & Nuxt Content v2.

StatusBase Uptime monitoring tool & beautiful status pages Powered by Nuxt Content v2! Free • Open Source • Notification View Demo · Report Bug · Requ

StatusBase 194 Jul 5, 2022
Nuxt eureka client

Nuxt eureka client

Kirill 5 May 30, 2022
✉️ Nuxt module for first class integration with popular newsletter providers

nuxt-newsletter Newsletter module for Nuxt 3 ✨ Release Notes ?? Read the documentation Features Nuxt 3 ready Easy integration with Mailchimp, Revue, B

Jakub Andrzejewski 39 Jan 5, 2023
🔎 Algolia module for Nuxt

@nuxtjs/algolia Algolia module for Nuxt ✨ Release Notes ?? Read the documentation Features Nuxt 3 ready Easy integration with Algolia Handy composable

Nuxt Community 91 Jul 28, 2022
⚡️ Integrate Nuxt with Twind, The smallest, fastest, most feature complete tailwind-in-js solution in existence!

Nuxt Twind Module Integrate Nuxt with Twind, The smallest, fastest, most feature complete tailwind-in-js solution in existence! Warning ?? This module

pooya parsa 38 Oct 18, 2022