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.
Using the CLI (Recommended)
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 | bashConfigure 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 devUsing the Node.js SDK
Bun is Node.js-compatible, so you can use the official KeyEnv Node.js SDK.
Install
bun add @keyenv/nodeBasic 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 codeRun with:
KEYENV_TOKEN=xxx KEYENV_PROJECT=xxx bun run scripts/migrate.tsOr using the CLI:
keyenv run -p PROJECT -e production -- bun run scripts/migrate.tsTesting
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
-
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! }); -
Use environment-specific configs:
const env = process.env.NODE_ENV || 'development'; await client.loadEnv(projectId, env); -
Handle errors at startup:
try { await client.loadEnv(projectId, 'production'); } catch (error) { console.error('Failed to load secrets:', error); process.exit(1); } -
Use caching in serverless - Enable cache TTL for warm function reuse:
const client = new KeyEnv({ token: process.env.KEYENV_TOKEN!, cacheTtl: 300, // 5 minutes });