Environment variables

Every function laranja deploys receives environment variables through process.env exactly as it would locally — a Lambda's environment on AWS, the Function App's application settings on Azure. Declare them either as static values in your config or in code with env(), and give each stage its own values.

Static values in config

Put plain, commit-safe values in the env map in your config. They're injected into every function (HTTP proxy, cron, and queue consumers):

// laranja.config.ts
const config: LaranjaConfig = {
  name: "my-api",
  env: {
    LOG_LEVEL: "info",
    API_BASE_URL: "https://api.example.com",
  },
};
// anywhere in your app
const level = process.env.LOG_LEVEL; // "info"

Use this for non-sensitive configuration that's the same everywhere: log levels, public URLs, feature flags.

Values from your environment — env()

When a value should come from your shell or CI instead of your repo, wrap the variable name with the env() helper where you read it:

import { env } from "@alzulejos/laranja-decorators";

const dbUrl = env("DATABASE_URL"); // same as process.env.DATABASE_URL at runtime

laranja finds every env("…") in your code and makes sure that variable is set on every deployed function — no more filling them in by hand in the cloud console. At deploy time it reads each value from your own environment and sends it straight to the function; the value is never written into your repo.

The name must be a string literalenv("DATABASE_URL"), not env(someVariable) — so laranja can discover it just by reading your code.

Supplying the values

Set the variables in the shell or CI job you deploy from:

DATABASE_URL=postgres://… laranja deploy --stage prod
  • Missing a value? By default laranja deploys anyway and warns you which ones were empty — a typo never blocks a deploy. Pass --strict to fail the deploy instead.
  • Re-deploying without re-supplying a value? The previously deployed value is kept, so you don't have to pass every variable on every deploy.

The STAGE variable

laranja always injects STAGE on every provider, set to the active stage ("dev" by default, or whatever --stage resolved to). You don't declare it:

app.get("/", (_req, res) => res.json({ stage: process.env.STAGE }));

If you also define STAGE in env, your value wins.

Per-stage values

Because --stage selects the environment at deploy time, the common pattern is one pipeline per stage, each supplying its own values:

  • Shared, non-sensitive defaults → the env map in config.
  • Per-environment values → declare them with env() and provide them from each pipeline's environment.
# dev pipeline
LOG_LEVEL=debug laranja deploy --stage dev
# prod pipeline
LOG_LEVEL=warn  laranja deploy --stage prod

Secrets

env() keeps values out of your repo, but the values still land in the function's plain environment — a Lambda's environment variables, or an Azure Function App's application settings — readable by anyone with access to the function's configuration. For true secrets (API keys, DB passwords), that's not enough. First-class secrets support is on the roadmap; until then, read them at runtime from a secret store inside your handler (AWS SSM Parameter Store / Secrets Manager, or Azure Key Vault).