t3-oss / create-t3-turbo

Clean and simple starter repo using the T3 Stack along with Expo React Native
https://turbo.t3.gg
MIT License
4.5k stars 375 forks source link

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

Closed dBianchii closed 8 months ago

dBianchii commented 8 months ago

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";


2. 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")
```ts
//...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,

juliusmarminge commented 8 months ago

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

dBianchii commented 8 months ago

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

juliusmarminge commented 8 months ago

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..

dBianchii commented 8 months ago

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