The environment object provides access to environment variables in your Zuplo
API gateway. It returns a record of environment variable names to their values.
Access environment variables using the environment object:
import { environment, ZuploContext, ZuploRequest } from "@zuplo/runtime";export default async function handler( request: ZuploRequest, context: ZuploContext,) { // Access environment variables const apiKey = environment.API_KEY; const apiUrl = environment.API_BASE_URL; if (!apiKey) { throw new Error("API_KEY environment variable is not set"); } const response = await fetch(`${apiUrl}/data`, { headers: { Authorization: `Bearer ${apiKey}`, }, }); return response;}
ts
Type Safety
Since environment variables might not be defined, they return
string | undefined:
import { environment } from "@zuplo/runtime";// TypeScript knows this could be undefinedconst value = environment.MY_VAR; // string | undefined// Always check before usingif (value) { // value is string here console.log(value.toUpperCase());}// Or provide a defaultconst port = environment.PORT || "3000";
ts
Common Patterns
Required Environment Variables
Create a helper to validate required variables:
import { environment, ConfigurationError } from "@zuplo/runtime";function getRequiredEnv(name: string): string { const value = environment[name]; if (!value) { throw new ConfigurationError( `Required environment variable '${name}' is not set`, ); } return value;}// Usageexport default async function handler( request: ZuploRequest, context: ZuploContext,) { const apiKey = getRequiredEnv("API_KEY"); const apiUrl = getRequiredEnv("API_BASE_URL"); // Both are guaranteed to be strings return fetch(`${apiUrl}/endpoint`, { headers: { "X-API-Key": apiKey }, });}
ts
Configuration Object
Create a configuration object from environment variables:
To handle environment-specific logic, use environment variables that you define:
import { environment } from "@zuplo/runtime";// Define your own environment variable to identify the environmentconst isProduction = environment.ENVIRONMENT === "production";const isStaging = environment.ENVIRONMENT === "staging";const isDevelopment = environment.ENVIRONMENT === "development";export default async function handler( request: ZuploRequest, context: ZuploContext,) { // Use different endpoints based on environment const apiUrl = isProduction ? "https://api.example.com" : isStaging ? "https://staging-api.example.com" : "https://dev-api.example.com"; // Enable debug logging in non-production if (!isProduction) { context.log.debug("Incoming request", { headers: Object.fromEntries(request.headers), url: request.url, }); } // Use stricter security in production const headers: HeadersInit = { "Content-Type": "application/json", }; if (isProduction) { headers["Strict-Transport-Security"] = "max-age=31536000"; } return new Response("OK", { headers });}
ts
Secret Management
import { environment } from "@zuplo/runtime";// Group related secretsconst secrets = { database: { host: environment.DB_HOST || "localhost", port: environment.DB_PORT || "5432", user: environment.DB_USER, password: environment.DB_PASSWORD, name: environment.DB_NAME || "myapp", }, redis: { url: environment.REDIS_URL || "redis://localhost:6379", }, external: { stripeKey: environment.STRIPE_SECRET_KEY, sendgridKey: environment.SENDGRID_API_KEY, },};// Validate all required secrets on startupfunction validateSecrets() { const missing: string[] = []; if (!secrets.database.user) missing.push("DB_USER"); if (!secrets.database.password) missing.push("DB_PASSWORD"); if (!secrets.external.stripeKey) missing.push("STRIPE_SECRET_KEY"); if (missing.length > 0) { throw new ConfigurationError( `Missing required secrets: ${missing.join(", ")}`, ); }}// Run validationvalidateSecrets();
ts
Environment Detection
Zuplo does not provide a built-in NODE_ENV variable since it runs on a custom
V8 runtime, not Node.js. To implement environment-specific logic, define your
own environment variables (e.g., ENVIRONMENT, STAGE, or ENV_TYPE) and set
them appropriately for each environment in your project settings.
Best Practices
1. Use Descriptive Names
// Goodenvironment.STRIPE_WEBHOOK_SECRET;environment.DATABASE_CONNECTION_STRING;environment.SLACK_WEBHOOK_URL;// Less clearenvironment.KEY;environment.URL;environment.SECRET;
// Validate at module load time, not request timeconst apiKey = environment.API_KEY;if (!apiKey) { throw new ConfigurationError("API_KEY must be set");}export default async function handler( request: ZuploRequest, context: ZuploContext,) { // apiKey is guaranteed to exist here return fetch("https://api.example.com", { headers: { "X-API-Key": apiKey }, });}
ts
4. Don't Log Secrets
// DON'T do thiscontext.log.info("Config loaded", { apiKey: environment.API_KEY,});// DO this insteadcontext.log.info("Config loaded", { apiKeyPresent: !!environment.API_KEY, apiKeyLength: environment.API_KEY?.length,});
ts
Setting Environment Variables
Environment variables are set in the Zuplo Portal:
Navigate to your project
Go to Settings → Environment Variables
Add variables for each environment (production, preview, development)
Variables are encrypted at rest and in transit
Beta Status
The environment object is currently in beta and the API may change in future
releases.