@bella-baxter/sdk
v0.1.1-preview.128
Published
TypeScript client for the Bella Baxter API — wraps Kiota-generated client with auth + E2EE
Maintainers
Readme
@bella-baxter/sdk
Core TypeScript SDK for Bella Baxter — a secure secret management gateway. Provides live-reloading secrets for Node.js apps, HMAC-signed API auth, and optional Zero-Knowledge Encryption (ZKE).
Installation
npm install @bella-baxter/sdk
# or
pnpm add @bella-baxter/sdkQuick start
import { createBellaConfig } from '@bella-baxter/sdk';
const bella = await createBellaConfig({
baxterUrl: process.env.BELLA_BAXTER_URL!,
apiKey: process.env.BELLA_BAXTER_API_KEY!,
projectSlug: 'my-app', // or set BELLA_BAXTER_PROJECT env var
environmentSlug: 'production', // or set BELLA_BAXTER_ENV env var
});
// Access secrets
const dbUrl = bella.get('DATABASE_URL'); // string | undefined
const port = bella.getOrThrow('PORT'); // string — throws if missing
const all = bella.getAll(); // Record<string, string>
// Write all secrets into process.env (for legacy integrations)
bella.intoProcessEnv();
// Stop background polling when shutting down
bella.destroy();Environment variables
| Variable | Description |
|----------|-------------|
| BELLA_BAXTER_URL | Base URL of the Bella Baxter API |
| BELLA_BAXTER_API_KEY | API key (bax-...), obtained from the WebApp or CLI |
| BELLA_BAXTER_PROJECT | Project slug (fallback for projectSlug option) |
| BELLA_BAXTER_ENV | Environment slug (fallback for environmentSlug option) |
| BELLA_BAXTER_PRIVATE_KEY | PKCS#8 PEM private key for ZKE (optional) |
Typed secrets
Run the CLI to generate a typed declaration file:
bella secrets generate typescript --declarationThis generates bella-secrets.d.ts (ambient) and bella-coercions.ts (runtime). Pass coercions to get typed, coerced values:
import { BELLA_COERCIONS } from './bella-coercions.js';
const bella = await createBellaConfig({ coercions: BELLA_COERCIONS });
bella.PORT // number — not string
bella.DATABASE_URL // stringZero-Knowledge Encryption (ZKE)
When BELLA_BAXTER_PRIVATE_KEY is set (or privateKey option), secrets are end-to-end encrypted. The server never sees plaintext values.
const bella = await createBellaConfig({
baxterUrl: '...',
apiKey: '...',
privateKey: process.env.BELLA_BAXTER_PRIVATE_KEY,
});The client always presents an E2EE public key when reading secrets (the device key above, or an ephemeral
one), so the answer must be an encrypted envelope that opens with that key. Anything else is refused
with an E2EEResponseError, never returned as plaintext:
| err.code | Meaning |
|---|---|
| e2ee-plaintext-response | The server (or something between you and it) answered with unencrypted secrets |
| e2ee-decryption-failed | The envelope was tampered with, malformed, or encrypted to a different key |
The key is presented on every read that carries secret values, not only getAllSecrets. For those
without a typed method (a single secret, its versions, a provider's secrets, the exports, global secrets),
client.request(path) GETs any API path through the same authentication and E2EE pipeline and returns
the decrypted JSON:
const client = await createBaxterClient({});
const item = await client.request<{ key: string; value: string }>(
'/api/v1/projects/my-app/environments/prod/providers/vault/secrets/DB_PASSWORD',
);An export read this way answers a { key: value } object, whatever format asks for: a file is only
served to a caller that presents no key.
Framework integrations
| Framework | Package |
|-----------|---------|
| Express | @bella-baxter/express |
| Fastify | @bella-baxter/fastify |
| NestJS | @bella-baxter/nestjs |
| Next.js | @bella-baxter/next |
| AdonisJS | @bella-baxter/adonis |
| React Native | @bella-baxter/react-native |
