middleware icon indicating copy to clipboard operation
middleware copied to clipboard

It would be nice to have a schema validator for the Hono adapter environment variables

Open gunta opened this issue 2 years ago • 2 comments

Something like

gunta avatar Nov 20 '23 20:11 gunta

Sounds nice.

Also @sergiodxa implements "Typed Envs": https://github.com/sergiodxa/remix-hono#typed-envs-with-zod

yusukebe avatar Nov 27 '23 06:11 yusukebe

I'm currently using zod for everything and it just works!

We use config.ts but you can call whatever you prefer

// src/config.ts 
import { z } from 'zod'

const configSchema = z.object({
  NODE_ENV: z.string().optional().default("development"),
  DATABASE_URL: z.string().url(),
  JWT_SECRET: z.string(),
  SENTRY_DSN: z.string().optional(),
})

export const config = configSchema.parse(process.env)

And later you can use it as simple as:

// src/lib/db.ts
import { Pool } from 'pg'
import { config } from '@/config'

export const db = new Pool({ connectionString: config.DATABASE_URL })
// src/lib/sentry.ts
import * as Sentry from '@sentry/node'
import { config } from '@/config'

export function captureException(err: any) {
  if (config.SENTRY_DSN) {
    Sentry.captureException(err);
  }
}

export function captureMessage(message: string) {
  if (config.SENTRY_DSN) {
    Sentry.captureMessage(message);
  }
}

rafaell-lycan avatar Jan 29 '24 12:01 rafaell-lycan

Here's how I got typesafe env for hono using t3. Create a new file, env.ts.

// env.ts

import { createEnv } from "@t3-oss/env-core";
import type { Context } from "hono";
import { env } from "hono/adapter";
import { z } from "zod";

export const getEnv = (c: Context) =>
  createEnv({
    server: {
      API_KEY: z.string(),
    },
    clientPrefix: "PUBLIC_",
    client: {},
    runtimeEnv: env(c),
    emptyStringAsUndefined: true,
  });

Usage:

import { getEnv } from './env'

app.get('/env', (c) => {
	const { API_KEY } = getEnv(c)
	...
})

Notes:

  • There are multiple ways to access env in hono. You could do c.env in Cloudflare workers, but the env() function is a more flexible method that supports multiple runtimes and is accessed with env(c). Hence, for runtimeEnv, we pass in env(c)
  • The one downside of this approach is that we're validating environment variables for every request rather than runtime. There might be a way to do this just once on build time, which would be preferred

braden-w avatar Oct 13 '24 18:10 braden-w