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 can write a typed client to lib/vaultlier/vaultlier.ts with your project id and a type parameter derived from your schema. Import and call it:
import { vault } from "./lib/vaultlier/vaultlier";
const config = await vault({ environment: "prod" });
config.DATABASE_URL; // typedUse vaultlier init --client=<path> to choose a different generated file, or vaultlier init --no-client to skip generation and use createClient directly.
createClient
You can also construct a client directly with your own type:
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)
| Option | Type | Description |
|---|---|---|
projectId | string | The public project id (prj_…). Required. |
baseUrl | string | Override the portal API base URL (defaults to the hosted API). Primarily for self-hosting and tests. |
vault(options)
| Option | Type | Description |
|---|---|---|
environment | string | Which environment to resolve, e.g. "dev" | "staging" | "prod". Required. |
apiKey | string | Explicit API key. Takes precedence over the environment variable. |
cache | "memory" | "none" | Defaults to "memory" - caches per process, environment, and API key. |
cacheTtlMs | number | Memory-cache lifetime. Defaults to 60000 (one minute). |
timeoutMs | number | Request timeout. Defaults to 10000. |
API key resolution
The runtime resolves the API key in this order:
- The explicit
apiKeypassed to the call. VAULTLIER_API_KEYin the hosting/CI environment.- The local credential cache created by
vaultlier init(development only).
Never commit your API key
SetVAULTLIER_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 and API key fetches the config and keeps it in process memory for one minute. Concurrent first calls share one request. The cache never writes values to disk, browser storage, a CDN, or a shared data store.
// Export one module-level client and reuse it throughout the process.
const config = await vault({ environment: "prod" });
// Use a shorter revocation/freshness window for sensitive workloads.
const strict = await vault({ environment: "prod", cacheTtlMs: 15_000 });
// Bypass the memory cache completely.
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.
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.
Storage backends
The SDK call is identical no matter where a project's secrets are stored. If a project uses a bring-your-own backend (S3 or Postgres), Vaultlier reads from it and falls back to its own encrypted copy if that store is briefly unreachable, so vault() stays resilient through a backend outage. See Storage backends.
