@heizen-labs/secrets-sdk
v1.1.1
Published
TypeScript SDK for loading Heizen Project Studio secrets
Downloads
1,697
Readme
@heizen-labs/secrets-sdk
Lightweight SDK to fetch secrets from Heizen Studio and load them into your runtime environment.
Install
npm install @heizen-labs/secrets-sdk
# or
pnpm add @heizen-labs/secrets-sdk
# or
bun add @heizen-labs/secrets-sdkQuick Start
import { SecretsClient } from "@heizen-labs/secrets-sdk";
const client = new SecretsClient({
projectId: process.env.HEIZEN_STUDIO_PROJECT_ID,
environment: process.env.HEIZEN_STUDIO_ENVIRONMENT_NAME,
apiKey: process.env.HEIZEN_STUDIO_API_KEY,
});
await client.loadSecrets();
console.log(process.env.DATABASE_URL);CLI: run command with injected secrets
The package also provides a heizen-secrets CLI binary.
heizen-secrets run [<projectId> [environment]] [--api-key <key>] [--base-url <url>] [--override] -- <command> [args...]Example:
heizen-secrets run proj_11 development -- nest start --watchWith values from environment variables:
export HEIZEN_STUDIO_PROJECT_ID=proj_11
export HEIZEN_STUDIO_ENVIRONMENT_NAME=development
export HEIZEN_STUDIO_API_KEY=xxx
heizen-secrets run -- nest start --watchWith explicit API key:
heizen-secrets run proj_11 development --api-key xxx -- pnpm devCLI argument resolution
Positional arguments are positional: the first value is always projectId, and the second is always environment.
- To pass the environment from the CLI, you must pass
projectIdfirst. - A single positional is treated as
projectId, notenvironment. --api-keyis independent of positionals. You can pass it withoutprojectIdorenvironmenton the command line.
Examples:
# All values from env / .env files
heizen-secrets run -- nest start --watch
# Project ID from CLI; environment and API key from env
heizen-secrets run proj_123 -- nest start --watch
# API key from CLI; project ID and environment from env
heizen-secrets run --api-key sk_fdsfsdf -- nest start --watch
# Both project ID and environment from CLI; API key from env
heizen-secrets run proj_123 env_1 -- nest start --watchCommon mistake:
# env_1 is treated as projectId, not environment
heizen-secrets run env_1 -- nest start --watchIf you want env_1 as the environment name, pass both positionals:
heizen-secrets run proj_123 env_1 -- nest start --watchOr set both in env and omit positionals:
export HEIZEN_STUDIO_PROJECT_ID=proj_123
export HEIZEN_STUDIO_ENVIRONMENT_NAME=env_1
heizen-secrets run -- nest start --watchWhat you pass on the CLI vs what must come from env:
| You pass on CLI | You need in env / .env |
| --- | --- |
| nothing | HEIZEN_STUDIO_PROJECT_ID, HEIZEN_STUDIO_ENVIRONMENT_NAME, HEIZEN_STUDIO_API_KEY |
| --api-key only | HEIZEN_STUDIO_PROJECT_ID, HEIZEN_STUDIO_ENVIRONMENT_NAME |
| <projectId> only | HEIZEN_STUDIO_ENVIRONMENT_NAME, HEIZEN_STUDIO_API_KEY |
| <projectId> and <environment> | HEIZEN_STUDIO_API_KEY |
| <projectId>, <environment>, and --api-key | nothing |
If a required value cannot be resolved, the CLI exits with a clear error:
Missing project ID. Pass <projectId> or set HEIZEN_STUDIO_PROJECT_ID.Missing environment name. Pass <environment> or set HEIZEN_STUDIO_ENVIRONMENT_NAME.Missing API key. Pass --api-key or set HEIZEN_STUDIO_API_KEY.
Behavior and guarantees:
- Secrets are fetched and injected only into the spawned process environment.
- Secrets are never printed, written to files, or exported by the CLI.
- Parent process env is not mutated.
- Project ID lookup order:
<projectId>->process.env.HEIZEN_STUDIO_PROJECT_ID->.env.local->.env. - Environment lookup order:
<environment>->process.env.HEIZEN_STUDIO_ENVIRONMENT_NAME->.env.local->.env. - API key lookup order:
--api-key->process.env.HEIZEN_STUDIO_API_KEY->.env.local->.env.
Limitation:
- Your application can still read and print its own environment values if your code chooses to do that.
Environment variables
| Variable | Used for |
| --- | --- |
| HEIZEN_STUDIO_PROJECT_ID | Heizen project ID |
| HEIZEN_STUDIO_ENVIRONMENT_NAME | Environment name (for example, development) |
| HEIZEN_STUDIO_API_KEY | API key sent as x-api-key |
How to get HEIZEN_STUDIO_API_KEY
- Go to
https://studio.heizen.work. - Open your project.
- Go to
Project Settings. - Create a new API key.
- Grant
secrets:readpermission. - Save the key and set it as
HEIZEN_STUDIO_API_KEYin your environment.
App Script Integration
In your app package.json:
{
"scripts": {
"dev": "heizen-secrets run proj_11 development -- nest start --watch"
}
}API Reference
new SecretsClient(options)
| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| projectId | string | No* | - | Heizen project ID (example: proj_123). Falls back to process.env.HEIZEN_STUDIO_PROJECT_ID. |
| environment | string | No* | - | Environment name (example: development, production). Falls back to process.env.HEIZEN_STUDIO_ENVIRONMENT_NAME. |
| apiKey | string | No* | - | API key sent as x-api-key. Falls back to process.env.HEIZEN_STUDIO_API_KEY. |
| baseUrl | string | No | https://api.studio.heizen.work | Override API host |
| axiosInstance | AxiosInstance | No | internal instance | Custom axios config/interceptors |
* At least one source must be provided for each field (option value or matching environment variable).
client.loadSecrets(options?): Promise<Record<string, string>>
Fetches secrets and writes them into an env-like target object.
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| override | boolean | false | If true, replaces existing values in target |
| target | Record<string, string \| undefined> | process.env | Target object where secrets are written |
loadSecrets Examples
// Default: writes into process.env, does not overwrite existing keys
await client.loadSecrets();
// Overwrite existing process.env keys
await client.loadSecrets({ override: true });
// Write into a custom object
const envObject: Record<string, string | undefined> = {};
await client.loadSecrets({ target: envObject });Errors
All SDK errors are thrown as SecretsClientError.
import { SecretsClientError } from "@heizen-labs/secrets-sdk";
try {
await client.loadSecrets();
} catch (error) {
if (error instanceof SecretsClientError) {
console.error(error.message, error.status);
}
}