How are they defined separately?
I am using monorepo for my project design and I want to separate the definition of trpc completely independently.
I have @app/api to take care of implementing the trpc api definitions in @app/api-define.
I want to define all trpc api content ( type define ) in @app/api-define as a separate package.
Then I just need to use @app/api-define in @api/next-app.
As a standalone package, I can even use it in a different project, or convert it to an rpc specification that other languages will recognize.
21 Replies
tRPC doesn’t really work that way, the types come from the implementation, as opposed to OO-land where the implementation is often built on predesigned interfaces
It’s not an anti-pattern here to just “import type from” the api directly from the client, you won’t bundle the entire API into your frontend if you do it right
import type from
is also an imported type, why can't it be alone?Not sure I understand what you mean
import type from somebody
Import types only, and will not contain codeYes, the client only needs the types from the API
So, can I declare my own AppRouter for trpc?
Do not use
export type AppRouter = typeof appRouter;
You might want to take a look at the example projects and see how the maintainers structure this stuff, the recommended patterns are quite consistent
I have to import type from my backend code, and I can't distribute GraphQL Schema files like GraphQ L does.
Yes, that’s correct. You could publish the typescript types as a npm package but the batteries aren’t included there. trpc is designed for co-located client/server code first
So I'm looking for a solution, if the client of trpc only needs one type file, can I define it manually?
hey, don't completely understand the goal of what you're trying to do - have you checked out https://github.com/t3-oss/create-t3-turbo ?
GitHub
GitHub - t3-oss/create-t3-turbo: Clean and simple starter repo usin...
Clean and simple starter repo using the T3 Stack along with Expo React Native - GitHub - t3-oss/create-t3-turbo: Clean and simple starter repo using the T3 Stack along with Expo React Native
there, we have our api package which exports the router and it's type: https://github.com/t3-oss/create-t3-turbo/blob/main/packages/api/index.ts
and the nextjs api handler can import the router: https://github.com/t3-oss/create-t3-turbo/blob/main/apps/nextjs/src/pages/api/trpc/%5Btrpc%5D.ts
and to create the hooks, we just need the types: https://github.com/t3-oss/create-t3-turbo/blob/29d207dc197454dd0a5b8b18287f9594e2cdfa53/apps/nextjs/src/utils/api.ts#L5
and then for apps which aren't serving the router but just consuming the api, they also just need the types: https://github.com/t3-oss/create-t3-turbo/blob/597ec9861a3da0ac9e631b9a240420b62e89253b/apps/testy/client.ts#L2
but i dont understand why you want the type in a separate package?
I checked the code inside, not what I want
I need trpc to be split into type definition and implementation, not merged together.
It is still together in t3, it is difficult for me to encapsulate the framework belonging to our company based on trpc.
In the way of importing types (
import type from tsrpc_api
), once some other code on the server is imported in my code, it will be packaged into the front-end project. I even need to write some tools for security inspections.I generally use https://nx.dev for project design. I write an API it should be an app rather than library.
Nx
Nx: Smart, Fast and Extensible Build System
Nx is a smart, fast and extensible build system which comes with first class monorepo support and powerful integrations.
It won’t be packaged into the project, I also use Nx and importing by type will not cause your whole backend to be bundled
This was the second thing I said
Types are stripped at compile time and all imports via type imports will get dropped and tree-shaken
but in nx, api should be an application, and the application does not import aliases
It can be set manually but I prefer to separate them.
One of our projects has a lot of developers involved and I need to write some checks to make sure all are obeying using type imports, which can be a disaster if someone forgets.
my doubt is that for trpc, only the type definition is required when creating the client. Why is this type definition forced to be written together with the server instead of separate?
Nx can ban imports of projects via eslint, in-fact you would have to disable this in order to import the api because it’s an application. So you can just disable for the one line in your client which is allowed to import it, then re-export and force everyone else to import from that file
Ultimately if you don’t trust this stuff then you probably chose the wrong solution for your backend.
If someone imports appRouter instead of type AppRouter your app will blow up and not run - since you’d be importing server code on the client - you would get errors which is quite easy to test against.
Alternatively you can restrict imports with lint rules as Nick suggests
im also using nx as a monorepo workspace. what u need to do i create a node library wheren ur trpc definitions and routes go. in your next app, the trpc utils for batching and stuff like that go in the uitls folder at the same level as your next app
it took me a while to figure this out. trpc is not a stand alone app. in NX apps cant share types/code but libs can
this my nx graph
business-data-access and shared-data-access are both node libraries
business-data-access implements a node library which has all the routes for the nextjs business app. shared-data-access exports shared code for all applications. such a context. but also auth. since this workspace will have two applications and both will have the same logic
also important to note is, smart components need to live in your next app. and dumb components that do not have access to data can be exported from a library
the reason for this is that the trpc utils folders lives inside your nextjs src folder. and sadly apps cant share code