Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for ZodObject to be passed directly to client/server keys instead of an object of ZodTypes #169

Open
kpervin opened this issue Jan 23, 2024 · 7 comments
Labels
PRs Accepted Feel free to pick this up and make a PR

Comments

@kpervin
Copy link

kpervin commented Jan 23, 2024

Currently in @t3-oss/env-nextjs you are meant to define your env as follows:

const env = createEnv({
  server: {
    FOO: z.string().required()
  },
  client: {
    BAR: z.string().required()
  }
});

However, there are times where you might want to define these ZodObjects outside of your env.mjs file and simply pass them:

/* External file*/
export const ServerSchema = z.object({
  FOO: z.string().required()
});
export const ClientSchema = z.object({
  BAR: z.string().required()
});


/* env.mjs */
const env = create schema({
  server: ServerSchema,
  client: ClientSchema
});

This however does not work and the resulting env has type Record<string, {}> because it wasn't expecting a ZodObject. It would be nice if we could pass pre-defined ZodObjects to these keys and retain type safety.

@kpervin
Copy link
Author

kpervin commented Jan 23, 2024

Closing as you can just use Schema.shape, however it would be good to include that in the docs.

/* External file*/
export const ServerSchema = z.object({
  FOO: z.string().required()
});
export const ClientSchema = z.object({
  BAR: z.string().required()
});


/* env.mjs */
const env = create schema({
  server: ServerSchema.shape,
  client: ClientSchema.shape
});

@kpervin kpervin closed this as completed Jan 23, 2024
@shkreios
Copy link

I believe there's significant value in considering the capability to pass a complete Zod schema, as opposed to merely an object structure, in our configuration. This feature would offer greater flexibility, particularly in complex scenarios where multiple conditional validations are necessary.

Example

Take, for instance, an app that allows a different set of authentication providers. In such cases, it's crucial to ensure that correlated environment variables are collectively defined. For example, if GOOGLE_CLIENT_ID is provided, it's imperative that GOOGLE_CLIENT_SECRET is also present, and not just marked as optional.

Example schema

const GoogleAuthSchema = z.object({
  GOOGLE_CLIENT_ID: z.string(),
  GOOGLE_CLIENT_SECRET: z.string(),
});

const ResendSchema = z.object({
  RESEND_API_KEY: z.string(),
});

const ServerSchema = z
  .object({
    NODE_ENV: z.enum(["development", "test", "production"]).default("development"),
    NEXTAUTH_SECRET: process.env.NODE_ENV === "production" ? z.string() : z.string().optional(),
  })
  .and(z.union([GoogleAuthSchema, ResendSchema]));

Resulting env type

type ServerSchemaType = {
  NODE_ENV: "development" | "test" | "production";
  NEXTAUTH_SECRET?: string | undefined;
} & (
  | {
      GOOGLE_CLIENT_ID: string;
      GOOGLE_CLIENT_SECRET: string;
    }
  | {
      RESEND_API_KEY: string;
    }
);

@shkreios
Copy link

I opened a new issue #176

@kpervin
Copy link
Author

kpervin commented Jan 29, 2024

@shkreios I could simply reopen this one, if you'd like

@shkreios
Copy link

@shkreios I could simply reopen this one, if you'd like

If thats possible, yes feel free to, maybe you can copy the new issue text into an updated request section or so

@kpervin kpervin reopened this Jan 30, 2024
@wfl-junior
Copy link

Any updates here? I would appreciate this feature, as I want to utilize super refine to validate some variables to be required only if another one is a certain value.

@juliusmarminge
Copy link
Member

juliusmarminge commented Feb 7, 2024

feel free to open a PR - iirc the reason why i did an object was cause inferring the shape didn't work properly with z.object() .

Don't try to make it backwards compat, lib is still on 0.x so we can make a breaking change that requries everyone to use z.object()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PRs Accepted Feel free to pick this up and make a PR
Projects
None yet
Development

No branches or pull requests

4 participants