Vaultlier

SDK

A tiny, edge-safe runtime client that resolves typed configuration for one environment. No Node-only imports, no third-party dependencies.

Generated client

vaultlier init writes a typed client to lib/vaultlier.ts with your project id and a type parameter derived from your schema. Import and call it:

TypeScript
import { vault } from "./lib/vaultlier";

const config = await vault({ environment: "prod" });
config.DATABASE_URL; // typed

createClient

You can also construct a client directly with your own type:

TypeScript
import { createClient } from "vaultlier";

export const vault = createClient<{
  DATABASE_URL: string;
  STRIPE_SECRET: string;
  FEATURE_NEW_FLOW: boolean;
}>({ projectId: "prj_checkout_api" });

const config = await vault({ environment: "prod" });

Client options

createClient(config)

OptionTypeDescription
projectIdstringThe public project id (prj_…). Required.
baseUrlstringOverride the portal API base URL (defaults to the hosted API). Primarily for self-hosting and tests.

vault(options)

OptionTypeDescription
environmentstringWhich environment to resolve, e.g. "dev" | "staging" | "prod". Required.
apiKeystringExplicit API key. Takes precedence over the environment variable.
cache"memory" | "none"Defaults to "memory" — caches the resolved config for the client's lifetime.
timeoutMsnumberRequest timeout. Defaults to 10000.

API key resolution

The runtime resolves the API key in this order:

  1. The explicit apiKey passed to the call.
  2. VAULTLIER_API_KEY in the hosting/CI environment.
  3. The local credential cache created by vaultlier init (development only).

Never commit your API key

Set VAULTLIER_API_KEYin your platform's secret store. It should never appear in source control or in the generated client — which contains metadata only.

Caching

With the default cache: "memory", the first call for an environment fetches and caches the result for the client's lifetime; subsequent calls return the cached value. Pass cache: "none" to always refetch.

TypeScript
// Cached for the life of the module — resolve once at startup.
const config = await vault({ environment: "prod" });

// Force a fresh fetch (e.g. after a rotation).
const fresh = await vault({ environment: "prod", cache: "none" });

Error handling

Failures throw a VaultlierRuntimeError carrying a stable code, a safe message, and an optional requestId. It never includes the API key, headers, or decrypted values, and its toJSON only serializes those safe fields.

TypeScript
import { VaultlierRuntimeError } from "vaultlier";

try {
  const config = await vault({ environment: "prod" });
} catch (err) {
  if (err instanceof VaultlierRuntimeError) {
    console.error(err.code, err.requestId); // e.g. "http/401"
  }
  throw err;
}

Common codes:

  • auth/missing_api_key — no key found in any resolution source.
  • auth/invalid_api_key — the key is malformed (rejected locally before any request).
  • http/<status> — the portal rejected the request.
  • network/timeout / network/error — transport failures.
Resolve configuration once during boot and fail fast on errors, rather than per request — see the Quickstart.