KeyEnvKeyEnv
SDKs & Integrations

Bun

Using KeyEnv with Bun applications.

Bun Integration

Load KeyEnv secrets in your Bun applications using the CLI or the Node.js SDK.

The simplest way to use KeyEnv with Bun is via the CLI's run command.

Install the CLI

curl -fsSL https://keyenv.dev/install.sh | bash

Configure package.json

{
  "scripts": {
    "dev": "keyenv run -p YOUR_PROJECT_ID -e development -- bun run src/index.ts",
    "start": "keyenv run -p YOUR_PROJECT_ID -e production -- bun run src/index.ts"
  }
}

Run with Secrets

# Set your token
export KEYENV_TOKEN=your-service-token

# Run with secrets injected
bun run dev

Using the Node.js SDK

Bun is Node.js-compatible, so you can use the official KeyEnv Node.js SDK.

Install

bun add @keyenv/node

Basic Usage

import { KeyEnv } from '@keyenv/node';

const client = new KeyEnv({
  token: process.env.KEYENV_TOKEN!,
});

// Load secrets into process.env
await client.loadEnv('your-project-id', 'production');

console.log(process.env.DATABASE_URL);

Full Example

// src/index.ts
import { KeyEnv } from '@keyenv/node';

const client = new KeyEnv({
  token: process.env.KEYENV_TOKEN!,
});

// Load secrets before starting server
await client.loadEnv(process.env.KEYENV_PROJECT!, 'production');

const server = Bun.serve({
  port: process.env.PORT || 3000,
  fetch(req) {
    return new Response('OK');
  },
});

console.log(`Server running at http://localhost:${server.port}`);

Using Bun's Built-in fetch

You can also call the KeyEnv API directly:

const KEYENV_TOKEN = process.env.KEYENV_TOKEN;
const PROJECT_ID = 'your-project-id';
const ENVIRONMENT = 'production';

async function loadSecrets() {
  const response = await fetch(
    `https://api.keyenv.dev/api/v1/projects/${PROJECT_ID}/environments/${ENVIRONMENT}/secrets/export`,
    {
      headers: {
        'Authorization': `Bearer ${KEYENV_TOKEN}`,
      },
    }
  );

  if (!response.ok) {
    throw new Error(`Failed to fetch secrets: ${response.status}`);
  }

  const { data: secrets } = await response.json();

  for (const secret of secrets) {
    process.env[secret.key] = secret.value;
  }

  console.log(`Loaded ${secrets.length} secrets`);
}

await loadSecrets();

Elysia Framework

For Elysia applications:

import { Elysia } from 'elysia';
import { KeyEnv } from '@keyenv/node';

const client = new KeyEnv({
  token: process.env.KEYENV_TOKEN!,
});

// Load secrets before creating app
await client.loadEnv(process.env.KEYENV_PROJECT!, 'production');

const app = new Elysia()
  .get('/', () => 'Hello World')
  .get('/config', () => ({
    apiUrl: process.env.API_URL,
  }))
  .listen(3000);

console.log(`Elysia running at http://${app.server?.hostname}:${app.server?.port}`);

Hono Framework

For Hono applications running on Bun:

import { Hono } from 'hono';
import { KeyEnv } from '@keyenv/node';

const client = new KeyEnv({
  token: process.env.KEYENV_TOKEN!,
});

await client.loadEnv(process.env.KEYENV_PROJECT!, 'production');

const app = new Hono();

app.get('/', (c) => c.text('Hello World'));

export default {
  port: process.env.PORT || 3000,
  fetch: app.fetch,
};

Scripts and One-off Commands

For scripts that need secrets:

// scripts/migrate.ts
import { KeyEnv } from '@keyenv/node';

const client = new KeyEnv({
  token: process.env.KEYENV_TOKEN!,
});

// Load production secrets for migration
await client.loadEnv(process.env.KEYENV_PROJECT!, 'production');

// Now run your migration
const databaseUrl = process.env.DATABASE_URL;
console.log('Running migrations...');
// ... migration code

Run with:

KEYENV_TOKEN=xxx KEYENV_PROJECT=xxx bun run scripts/migrate.ts

Or using the CLI:

keyenv run -p PROJECT -e production -- bun run scripts/migrate.ts

Testing

Load test secrets in your test setup:

// test/setup.ts
import { KeyEnv } from '@keyenv/node';
import { beforeAll } from 'bun:test';

beforeAll(async () => {
  const client = new KeyEnv({
    token: process.env.KEYENV_TOKEN!,
  });

  await client.loadEnv(process.env.KEYENV_PROJECT!, 'test');
});

Configure in bunfig.toml:

[test]
preload = ["./test/setup.ts"]

Best Practices

  1. Load secrets once at startup - Don't fetch on every request:

    // Good - load once
    await client.loadEnv(projectId, 'production');
    const server = Bun.serve({ ... });
    
    // Bad - fetching on every request
    app.get('/', async () => {
      await client.loadEnv(projectId, 'production'); // Don't do this!
    });
  2. Use environment-specific configs:

    const env = process.env.NODE_ENV || 'development';
    await client.loadEnv(projectId, env);
  3. Handle errors at startup:

    try {
      await client.loadEnv(projectId, 'production');
    } catch (error) {
      console.error('Failed to load secrets:', error);
      process.exit(1);
    }
  4. Use caching in serverless - Enable cache TTL for warm function reuse:

    const client = new KeyEnv({
      token: process.env.KEYENV_TOKEN!,
      cacheTtl: 300, // 5 minutes
    });

On this page