-
I have a single page app which i wrote with three main repos (plus some other private dependencies):
I would like to try trpc to be able to secure my api on the type front (i'm currently not enforcing api typing with a single definition but would like to do so). |
Beta Was this translation helpful? Give feedback.
Replies: 15 comments 20 replies
-
Either you do monorepo or you do some other ways of sharing types from the server like having an npm package for the server. I'm bullyish on monorepos in general so I can't give you much guidance |
Beta Was this translation helpful? Give feedback.
-
Just wonder for the use case of sharing types, will trpc have a way to build the types artifact that make this workflow easier to work with? I'm currently trying to explore this workflow and it's pretty hard trying to building types only packages out of the service especially when I'm using together with prisma generated types. On the side of generated types artifact, I can see https://rspc.dev/server/router#exporting-the-typescript-bindings, which is basically trpc for rust do it and it generate out a schema that allow for easier sharing
|
Beta Was this translation helpful? Give feedback.
-
@KATT Monorepos ofc agree, that is not always a reality for some. Which makes tRPC a no-brainer for new projects, but to allow adapting to a wider community of those of us where architectures don't support such an environment ;-). This could be implemented with a compiler transformer. Some things to solve ofc... but It is worth pointing out because I have actually built one for zod a couple years ago 🥇 . It was just a Proof of Concept for the zod community, but It would essentially transform a zod input validator into typescript types which could be easily communicated across repo-lines I would imagine. I can only imagine what capabilities a ts compiler plugin could do for tRPC where essentially every part of the request would be exposed to transform however needed.
@dohaicuong this would actually probably be similar to how Rust is doing it, as I am sure that does some sort of compiler extension to generate rust code from the AST. |
Beta Was this translation helpful? Give feedback.
-
I tried generating a TS declaration file to share TS types with other projects, and it seems to be working properly.
import { createTRPCProxyClient, httpBatchLink } from "@trpc/client";
import type { AppRouter } from "server";
const trpc = createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: "http://localhost:3000/trpc",
}),
],
}); I also think it'd be great if trpc implements a functionality for generating a type file, instead of having to do the above. |
Beta Was this translation helpful? Give feedback.
-
Quick note: Add |
Beta Was this translation helpful? Give feedback.
-
BTW, I have a folder that contains import type { AppRouter } from "server"; |
Beta Was this translation helpful? Give feedback.
-
Haven't tried this with trpc yet, but I've worked on a project where we use Prismic's Slicemachine schemas and types from an external repo as a git submodule, so all external files are synced in a folder in your local repo (like a monorepo). You could change trpc stuff on both repos if needed (to be honest you don't even need to touch the server repo directly). On the front-end repo git will only change the commit ref so it knows which version of the back-end repo you're working with. |
Beta Was this translation helpful? Give feedback.
-
@bradennapier Sorry I for the late rely, I've actually go down the same solution as @ShunyaWatanabe Yeah the problem is setup that is not a nice experience at the moment. |
Beta Was this translation helpful? Give feedback.
-
Even within a team or company, there are times when you want to hide the server implementation for security reasons. Therefore, the current trpc structure, which must operate within a single monorepo, seems to be a major obstacle to mass adoption. @KATT The method of building d.ts with tsc seems difficult to operate properly in a complex structure due to problems with typescript type inference and pnpm library hoisting recognition. @bradennapier @dohaicuong I think we can start by referring to rspc and zod-to-ts you guys mentioned. I've never done anything like this before, but it would be a great help if someone could implement it. |
Beta Was this translation helpful? Give feedback.
-
My solution for types sharing using
|
Beta Was this translation helpful? Give feedback.
-
In this use case, "ts-rest" may be a better match. |
Beta Was this translation helpful? Give feedback.
-
If somebody will find it useful I created example boilerplate on using tRPC with separate BE/FE repositories. |
Beta Was this translation helpful? Give feedback.
-
I wrote a blog about the best course of action if you want to have separate backend and frontend repos and still use tRPC. It is AWS Lambda based but can be applied to any tRPC implementation. There are also code repos. https://blog.cloudglance.dev/trpc-separate-backend-frontend-with-openapi-aws-lambda-cdk/index.html By design, tRPC is meant to be used in a mono repo project. This should always be your default for tRPC In this blog we:
GitHub repos used in this blog: |
Beta Was this translation helpful? Give feedback.
-
Expanding from an answer above, I have a separate Front End and Backend and solved this as follows: My directory structure
My AppRouter is in server/src/router.ts // in server/src/router.ts
export const appRouter = router({
/// procedures in here...
});
export type AppRouter = typeof appRouter; Then in server/package.json I have the following scripts added: {
"trpc-types": "npx tsc --declaration --strict --pretty src/router.ts --outDir temp --emitDeclarationOnly",
"move": "mv temp/router.d.ts ../client/src/config && rm -rf temp",
"types": "npm run trpc-types || true && npm run move"
}
From the terminal in the server folder I can run the command Then the tRPC setup on the Front End imports the types from the file I created: // in client/src/config/trpc.ts
import type { AppRouter } from "./router"; // <-- The type declaration file created
export const api = createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: `${serverURL}/trpc`,
}),
],
}); Whenever I make changes to the Back End I run Hope this helps someone! |
Beta Was this translation helpful? Give feedback.
-
I think that on the official website it should be stated in the headlines - monorepo only. Not to mention that server and client usage is quite often not mono-repository, meaning that this is not some rare case study - it's a reality of modern development. It's horrible |
Beta Was this translation helpful? Give feedback.
Either you do monorepo or you do some other ways of sharing types from the server like having an npm package for the server. I'm bullyish on monorepos in general so I can't give you much guidance