Skip to content

Prefix for private env variables #9776

@coryvirok

Description

@coryvirok

Describe the problem

I like to consolidate all of my environment variable usage, (imports) in as few as places as possible and I like to provide validation of the env vars using something like Zod. This means I usually create 2 files: $lib/server/env.ts and $lib/client/env.ts.

The issue is that when I import the private env vars using import * as staticServerEnv from "$env/static/private" Kit will include a const SOME_VAR = <value at compile time> for every env var in the environment. This results in many unrelated private env vars being included in the generated code.

E.g.

// $lib/server/env.ts
import z from 'zod'

import { env as dynamicClientEnv } from '$env/dynamic/public'
import * as staticClientEnv from '$env/static/public'
import { env as dynamicServerEnv } from '$env/dynamic/private'
import * as staticServerEnv from '$env/static/private'   // <------------ PROBLEM

import { Env as ClientEnv } from '../client/env'

const Env = ClientEnv.extend({
  ENV: z.enum(['prod', 'dev']).default('dev'),
  AUTH_COOKIE_NAME: z.string().default('auth'),
  ENCRYPTION_KEY: z.string().length(32),
})

const combinedEnv = {
  ...staticClientEnv,
  ...dynamicClientEnv,
  ...staticServerEnv,
  ...dynamicServerEnv,
}

const env = Env.parse(combinedEnv)
export default env as z.infer<typeof Env>

Is compiled into something like the following:

import z from "zod";
import { p as public_env, b as private_env } from "./shared-server.js";
import { E as Env$1, s as staticClientEnv } from "./env2.js";
const npm_package_devDependencies__tailwindcss_typography = "^0.5.9";
const STARSHIP_SHELL = "zsh";
const MANPATH = "/opt/homebrew/share/man:/usr/share/man:/usr/local/share/man:/opt/homebrew/share/man::";
const LDFLAGS = " -L/opt/homebrew/opt/mysql-client/lib -L/opt/homebrew/opt/mysql-client/lib";
const TERM_PROGRAM = "vscode";
const ENCRYPTION_KEY = "******************************";
const AUTH_JWT_SECRET = "*******************************";
const NODE = "/opt/homebrew/Cellar/node@18/18.16.0/bin/node";
const npm_package_devDependencies__iconify_json_heroicons = "^1.1.10";
const INIT_CWD = "/Users/*********/Development/**************";
const npm_package_devDependencies_typescript = "^5.0.0";
const TERM = "xterm-256color";
const SHELL = "/bin/zsh";
const HOST = "localhost";
// ...

Describe the proposed solution

I propose that a new, optional configuration item be added that would control the prefix for private env vars included in the bundle. E.g. privatePrefix?: string; that would default to the empty string. This should make it backward compatible with current behavior.

Then, some code will need to be added to the compiler to filter the process.env vars using the prefix before writing them out to the server bundle.

This would provide a couple of benefits:

  1. Would provide added assurance that no unintentional environment variables make their way into the server bundle.
  2. Would provide a solution to the foot-gun of import * as env from "$env/static/private" for those who read the docs.

Alternatives considered

Obviously, I can do something like, import { var1, var2, var3, ...} from "$env/static/private" but that leads to duplicated code and doesn't provide the benefit of a solution like a privatePrefix would for making sure no unintentional environment vars are added to server bundles.

Importance

would make my life easier

Additional Information

As always, thanks for SvelteKit and all the great work you folks do!

Metadata

Metadata

Labels

$envBugs related to the `$env` family of modulesfeature / enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions