# Node.js client

```bash
npm install envpass-cli
```

The package works in Node.js 20+ and Bun. It ships TypeScript types for the whole REST API.

## Load values into process.env

```ts
import { loadEnv } from "envpass-cli"

await loadEnv({ environment: "prod" })
console.log(process.env.DATABASE_URL)
```

`loadEnv` reads the token from `ENVPASS_TOKEN` or the CLI login, and scope from its arguments, `ENVPASS_*` variables or `.envpass.json`. Existing variables are kept unless you pass `override: true`. It returns the loaded values as an object.

With a user login, pass the workspace and project too, unless `.envpass.json` already has them:

```ts
await loadEnv({ workspace: "acme", project: "shop", environment: "dev" })
```

## Client

```ts
import { createEnvpass } from "envpass-cli"

const envpass = createEnvpass({ token: process.env.ENVPASS_TOKEN })

const entries = await envpass.resolve({ environment: "prod" })
// [{ key: "DATABASE_URL", value: "postgres://...", source: "shared" }, ...]

const dotenv = await envpass.resolveText({ environment: "prod" }, "dotenv")
const me = await envpass.me()
```

`source` is `"shared"` for the team value and `"personal"` for your own override, which only applies with a user login on environments that allow it.

| Option | Default |
|---|---|
| `baseUrl` | `ENVPASS_URL` or `https://envpass.dev` |
| `token` | `ENVPASS_TOKEN` or the saved CLI login |
| `userAgent` | `envpass-node` |
| `fetch` | `globalThis.fetch` |

## Webhooks and syncs

These methods need a user login. With a service token they throw `EnvpassError` with code `forbidden`. Each takes an optional scope as its last argument, resolved like `loadEnv`: `{ workspace }` for webhooks, `{ workspace, project }` for syncs.

```ts
const scope = { workspace: "acme", project: "shop" }

const { webhook, secret } = await envpass.createWebhook(
  { url: "https://example.com/hooks/envpass", events: ["secrets.changed"], environments: ["prod"] },
  scope
)
// store `secret` now: it is only returned once

const result = await envpass.testWebhook(webhook.id, scope)
// { ok: true, responseStatus: 200, durationMs: 143, error: null }

for (const sync of await envpass.listSyncs(scope)) {
  if (sync.status === "error") await envpass.runSync(sync.id, scope)
}
```

| Method | Does |
|---|---|
| `listWebhooks(scope?)` | The workspace's webhooks |
| `createWebhook(input, scope?)` | `input`: `url`, `events`, `environments` and `projects` (slugs), `format`, `description`. Returns `{ webhook, secret }`. |
| `deleteWebhook(id, scope?)` | Delete a webhook |
| `testWebhook(id, scope?)` | Send a test event and return the result |
| `listWebhookDeliveries(id, { limit, before }?, scope?)` | Recent deliveries, newest first |
| `listConnections(scope?)` | Vercel and GitHub connections |
| `listSyncs(scope?)` | The project's syncs |
| `runSync(id, scope?)` | Queue a sync now |
| `setSyncEnabled(id, enabled, scope?)` | Pause or resume a sync |

`WEBHOOK_EVENTS` lists the event names. See [Webhooks](/docs/webhooks) for payloads and signature checks, and [Syncs](/docs/syncs) for how syncs behave.

## Typed REST API

`envpass.api` is an [openapi-fetch](https://openapi-ts.dev/openapi-fetch/) client generated from the OpenAPI spec, so paths, parameters and responses are typed:

```ts
const { data, error } = await envpass.api.GET("/api/v1/workspaces/{workspaceId}/projects", {
  params: { path: { workspaceId } },
})

await envpass.api.PUT("/api/v1/workspaces/{workspaceId}/projects/{projectId}/secrets", {
  params: { path: { workspaceId, projectId } },
  body: { environmentId, entries: [{ key: "FEATURE_FLAG", value: "on" }] },
})
```

## Errors

Methods throw `EnvpassError` with `status` and `code` (`unauthorized`, `forbidden`, `not_found`, `conflict`, `invalid`, `limit_reached`, `rate_limited`).

```ts
import { EnvpassError } from "envpass-cli"

try {
  await envpass.resolve({ environment: "prod" })
} catch (error) {
  if (error instanceof EnvpassError && error.code === "forbidden") {
    console.error("This token can't read prod")
  }
}
```
