vite-plugin-validate-env icon indicating copy to clipboard operation
vite-plugin-validate-env copied to clipboard

Should error whenever an unvalidated env variable is used

Open BrunnerLivio opened this issue 1 year ago • 1 comments

I am looking for a way to ONLY allow using env variables that are defined in my env.ts schema.

As an example:

env.ts

import {defineConfig} from '@julr/vite-plugin-validate-env'
import {z} from 'zod'

export default defineConfig({
  validator: 'zod',
  schema: {
    VITE_LANGUAGE: z.string(),
  },
})

In the application code, the following should occur (desired behavior)

src/app.ts

// ✅ TypeScript: type "string", all good!
import.meta.env.VITE_LANGUAGE

// ❌ TypeScript: Key "VITE_WHATEVER" does not exist
import.meta.env.VITE_WHATEVER

BrunnerLivio avatar May 16 '24 16:05 BrunnerLivio

I am aware this is not directly related to this library but rather to Vite's typing of ImportMetaEnv (see below). Feel free to close if you think this should not be discussed as part of this project. However I think it would be worth adding a documentation entry in this project's README if we'd find a solution for this - hence why I created an issue here.

node_modules/vite/types/importMeta.d.ts

interface ImportMetaEnv {
  [key: string]: any
  BASE_URL: string
  MODE: string
  DEV: boolean
  PROD: boolean
  SSR: boolean
}

Vite seems to add [key: string]: any as a default. I wonder whether there is a way we could overwrite that. Since we have to use an interface to augment ImportMetaEnv and to make the module augmentation work I am not too sure how though.

I've already tried the following without avail:

env.d.ts

type ImportMetaEnvAugmented =
  import('@julr/vite-plugin-validate-env').ImportMetaEnvAugmented<
    typeof import('./src/env').default
  >

interface ImportMetaEnv extends ImportMetaEnvAugmented {
  [key: string]: never
}

BrunnerLivio avatar May 16 '24 16:05 BrunnerLivio

Unfortunately, this is a limitation of typescript and module augmentation: you can't modify a previous declaration.

The only alternative I see would be to do this:

// lib/env.ts
type ImportMetaEnvAugmented =
  import("@julr/vite-plugin-validate-env").ImportMetaEnvAugmented<
    typeof import("../env").default
  >;

export const env: ImportMetaEnvAugmented = import.meta.env

And use only this env variable to access environment variables

Julien-R44 avatar Nov 29 '24 10:11 Julien-R44