@otterlyspace/env
v1.0.1
Published
> [!WARNING] > This project is in early development. The API may change significantly before reaching a stable release and has not yet been extensively tested in production environments. > Use at your own risk. Please provide feedback and report issues to
Readme
@otterlyspace/env
[!WARNING] This project is in early development. The API may change significantly before reaching a stable release and has not yet been extensively tested in production environments. Use at your own risk. Please provide feedback and report issues to help us improve the library!
A type-safe environment variable manager for monorepos, heavily inspired by t3-env, built with Standard Schema support.
Features
- 🛡️ Validator Agnostic: Works with Zod, Valibot, Arktype, or any library supporting Standard Schema.
- 📦 Monorepo Ready: Share environment validation across packages with
isGlobalInstanceanduseGlobalInstance. - 🔒 Security: Prevents accidental exposure of server-side variables to the client.
- 🌐 Universal: Supports multiple client prefixes (e.g.,
VITE_,EXPO_). - 🧩 Presets: Extend configurations easily.
Installation
yarn add @otterlyspace/env
# Install your preferred Standard Schema-compatible validator (e.g., zod, valibot, arktype)
yarn add zodUsage
1. Define your environment (Main App)
In your main application (e.g., apps/web/src/env.ts), create the global environment instance.
import { createEnv } from "@otterlyspace/env";
import { z } from "zod";
export const env = createEnv({
server: {
DATABASE_URL: z.string().url(),
API_SECRET: z.string().min(1),
},
client: {
VITE_PUBLIC_API_URL: z.string().url(),
},
// Variables starting with these prefixes are allowed on the client
clientPrefix: "VITE_",
runtimeEnv: process.env,
// Registers this as the source of truth for the monorepo
isGlobalInstance: true,
});Advanced Options
skipValidation: Useful for CI/Docker builds where env vars might not be present.emptyStringAsUndefined: Treats empty strings asundefined.onValidationError: Custom error handler.
const env = createEnv({
// ...
skipValidation: !!process.env.SKIP_ENV_VALIDATION,
emptyStringAsUndefined: true,
onValidationError: (error) => {
console.error("❌ Invalid environment variables:", error.message);
throw error;
},
});2. Use in Internal Packages
In your internal packages (e.g., packages/ui/src/env.ts), reuse the global instance.
import { createEnv } from "@otterlyspace/env";
import { z } from "zod";
export const env = createEnv({
// Define the subset of variables this package needs for type safety
client: {
VITE_PUBLIC_API_URL: z.string().url(),
},
clientPrefix: "VITE_",
runtimeEnv: process.env,
// Tries to use the already validated global instance
useGlobalInstance: true,
});3. Access Variables
import { env } from "./env";
console.log(env.VITE_PUBLIC_API_URL); // Type-safe accessDevelopment
Setup
yarn installTesting
yarn testBuilding
yarn buildLicense
MIT
