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

feat: Enable allowing @acme/api, @acme/auth, @acme/db to export resources to client components other than just types

dBianchii opened this issue · comments

Describe the feature you'd like to request

Currently with the default setup, you cannot export any resources from @acme/api, @acme/auth @acme/db to client components in the nextjs app. You can only export types. As soon as you try to export from index.ts any other thing, (for example a shared zod schema, the compiler will yell at you)

image

I suggest we prepare a way for this to be allowed naturally, so we can import any resource from @acme/api, @acme/auth or @acme/db

Describe the solution you'd like to see

I have one suggestion on how to do it, but to be honest, I don't know what is the best way to go about doing this. I'm just going to plop down what I did to make this work. I'd need some more fiddling to make this better/more organized and intuitive

Here's what I came up with:

  1. have index.ts for the packages have only server-side resources, and add import "server-only"; directive to it.
//...src/index.ts

import "server-only";

export { appRouter } from "./root";
export { createTRPCContext } from "./trpc";
  1. Move all other resources to a shared.ts (might as well move the types too, so you know you can import anywhere and not "only-servers")
//...src/shared.ts

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

import type { AppRouter } from "./root";

export type { AppRouter };

/**
 * Inference helpers for input types
 * @example type HelloInput = RouterInputs['example']['hello']
 **/
export type RouterInputs = inferRouterInputs<AppRouter>;

/**
 * Inference helpers for output types
 * @example type HelloOutput = RouterOutputs['example']['hello']
 **/
export type RouterOutputs = inferRouterOutputs<AppRouter>;

export const test =
  "this is a test. Imagine I am a zod schema being shared between client and server. Now I can be imported anywhere!";
  1. Make @acme/api package.json have the both exports:
"exports": {
   ".": [
     "./src/index.ts"
   ],
   "./shared": [
     "./src/shared.ts"
   ]
 },

Additional information

So, this example I have for the acme/api package is just to illustrate what I mean. Not necessarily the best way to do it. Don't know how packages normally export both client/server from a single file. I don't even think this is possible,

For your particular case of sharing zod schemas, I'd create a separate package for that. For example, React Native doesnt treeshake so you dont even want to have the api package as a production dependency there. So for it to be truly shareable I'd create @acme/validators

For your particular case of sharing zod schemas, I'd create a separate package for that. For example, React Native doesnt treeshake so you dont even want to have the api package as a production dependency there. So for it to be truly shareable I'd create @acme/validators

Thanks. I created a @acme/shared package for my use case. Maybe we can close this issue? Unless you have any other thoughts about resource sharing between packages

Maybe we can close this issue? Unless you have any other thoughts about resource sharing between packages

Yea, I'd like to see a concrete use case before adopting such pattern. Marking with server-only means we're locking it down to react RSC only, and as mentioned sharing from separate entrypoint still means you need to include the package with server stuff as a production dep whcih is cumbersome for frameworks not doing treeshaking properly...

I think most things are better shared in their separate pacakge, such as @acme/validators for validators, @acme/utils or similar for arbitrary functinos useful on both ends etc etc..

Maybe we can close this issue? Unless you have any other thoughts about resource sharing between packages

Yea, I'd like to see a concrete use case before adopting such pattern. Marking with server-only means we're locking it down to react RSC only, and as mentioned sharing from separate entrypoint still means you need to include the package with server stuff as a production dep whcih is cumbersome for frameworks not doing treeshaking properly...

I think most things are better shared in their separate pacakge, such as @acme/validators for validators, @acme/utils or similar for arbitrary functinos useful on both ends etc etc..

Totally agree. In case I find a reason to adopt this pattern I'll comment again on here. Thanks a lot julius