t3-oss / create-t3-turbo

Clean and simple starter repo using the T3 Stack along with Expo React Native

Home Page:https://turbo.t3.gg

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Extending TRPC Router from apps and accessing API from ui package

shayant98 opened this issue · comments

In the current implementation of the repo the server and react file are placed in the individual apps. The issue with this is that I need to access TRPC Router from the components. I moved the react and server trpc implementation to the api package and this works pretty well.

The issue is that I don't want to place all routers in the endpoins only the shared ones. I want to be able to extend the router implementation from the individual apps while being able to use it in my ui package

Some context:

  • I send data through props from the page.tsx, but offer refetch logic in the component(s)
  • 70% routes are shared, but need a few routers to be app specific.

Any input would be greatly appreciated. I'm quite new to monorepo.

If there's a better solution I'd love to hear it.

Sorry, trying to understand. What you mean is that you are trying to access tRPC endpoints from UI package?

The issue is that I don't want to place all routers in the endpoins only the shared ones. I want to be able to extend the router implementation from the individual apps while being able to use it in my ui package

i dont understand what this means. Can you provide an example?

to me a ui packages shouldnt fetch any data - that sounds more like an app concern.

I think, if you are using UI package to fetch data, this component you are creating should belong inside your app. UI should have only primitives (e.g. reusable buttons, forms, dialogs etc. (see shadcnUI))

yes reusable components are seperated into their own subfolder inside the ui package under "/ui". But for the 3 webapplications in my repo I have some purpose built components that are shared shared and show the exact same data(initial data is sent through props and revalidation is done inside the component). Rebuilding the components inside each application completely defeats the purpose of using a monorepo in the first place.

You could create a shared package ( e.g. @acme/shared ), which uses @acme/ui and @acme/api as dependency.
It also includes the trpc stuff from @acme/nextjs ( /apps/nextjs/src/trpc/ ).

INFO: The easiest way to generate a new package is to run pnpm gen from your project root.

Then you create your components with api calls and whatever you want.
Last step is to add the @acme/shared package as dependency in your app and import the needed components.

If I misunderstood and/or misformulared something, please let me know.


Not sure if it's good or bad idea to do this, but I don't think we should add this to the create-t3-turbo ( if this was the question behind this ticket ).

That is definitely a possibility since I've just added them to a subdirectory under the ui package.

But the main question was more about defining routes inside the app folders and extending the api router with app-specific endpoints.

  • api
    • route-1
    • route-2

App 1

  • route-3

App 2

  • no spec. Routes

I want to define a router in App 1 with route 3 as a route and extend the already existing trpc implention so that i can access

Route 1, 2 & 3 inside App 1
route 1 & 2 inside App 2 (since it doesn't need it).

This doesn't need to be added to t3-turbo. It's just a specific scenario I'm dealing with and since I'm new to monorepo's, I'm trying to make sure I do things property to prevent issues in the future.

@shayant98 , with routes, do you mean API routes?

For this project, we only serve one API route for tRPC, which is /api/trpc/[trpc]/route.ts.

Trying to understand what your needs are but it's not clear
EDIT: also, what kind of apps are you using? All of them are Next.JS apps?

@dBianchii, Sorry Route might have been the wrong word, but the procedures defined under a router.

All are NEXTJS APPS

Ok, so if I got this straight, you want to limit which routers (tRPC endpoints) your other apps have access to? But you still want all of your endpoints being hosted from App 1 ? Or are you needing/wanting to host other API routes on other apps?

Need/want to host other API Routes on other apps.

While STILL keeping the tRPC endpoints defined in @acme/api

You could duplicate the definitions inside packages/api/src/index.ts and packages/api/root.ts.

Here an example

// packages/api/src/index.ts

import type { inferRouterInputs, inferRouterOutputs } from "@trpc/server"

import type { App1Router, App2Router } from "./root"
import { app1Router, app2Router } from "./root"
import { createCallerFactory, createTRPCContext } from "./trpc"

const createCallerApp1 = createCallerFactory(app1Router)
const createCallerApp2 = createCallerFactory(app2Router)


type RouterInputsApp1 = inferRouterInputs<App1Router>
type RouterInputsApp2 = inferRouterInputs<App2Router>


type RouterOutputsApp1 = inferRouterOutputs<App1Router>
type RouterOutputsApp2 = inferRouterOutputs<App2Router>

export { createTRPCContext, app1Router, app2Router, createCallerApp1, createCallerApp2 }
export type { App1Router, RouterInputsApp1, RouterInputsApp2, RouterOutputsApp1, RouterOutputsApp2 }
// packages/api/src/root.ts

import { authRouter } from "./router/auth"
import { postRouter } from "./router/post"
import { userRouter } from "./router/user"
import { createTRPCRouter } from "./trpc"

export const app1Router = createTRPCRouter({
  auth: authRouter,
  user: userRouter,
})

export const app2Router = createTRPCRouter({
  auth: authRouter,
  post: postRouter,
})

export type App1Router = typeof app1Router
export type App2Router = typeof app2Router

Inside your app, you only have to update some imports - Example:

// apps/nextjs/src/trpc/react.tsx 

- import type { AppRouter } from "@acme/api"
+ import type { App1Router as AppRouter } from "@acme/api"
// apps/nextjs/src/trpc/server.ts

- import { createCaller, createTRPCContext } from "@acme/api"
+ import { createCallerApp1 as createCaller, createTRPCContext } from "@acme/api"
// apps/nextjs/src/app/api/trpc/[trpc]/route.ts

- import { appRouter, createTRPCContext } from "@acme/api"
+ import { app1Router as appRouter, createTRPCContext } from "@acme/api"

With this, you can reuse the route definitions inside the api package.
Maybe there is a more elegant solution for this, but as starting point to find a "good" solution, it should be good enough.

Going to close this as it's not sometihng we're going to add here