@neondatabase/env 0.15.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -29
- package/dist/cli.js +971 -6
- package/dist/cli.js.map +1 -1
- package/dist/{lib/env.js → env.js} +70 -219
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +528 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +197 -1
- package/dist/index.js.map +1 -0
- package/package.json +11 -14
- package/dist/_shared/auth_selection.js +0 -76
- package/dist/_shared/auth_selection.js.map +0 -1
- package/dist/_shared/credentials.js +0 -131
- package/dist/_shared/credentials.js.map +0 -1
- package/dist/_shared/paths.js +0 -131
- package/dist/_shared/paths.js.map +0 -1
- package/dist/_shared/profiles.d.ts +0 -7
- package/dist/_shared/profiles.d.ts.map +0 -1
- package/dist/_shared/profiles.js +0 -124
- package/dist/_shared/profiles.js.map +0 -1
- package/dist/config/dist/lib/define-config.d.ts +0 -20
- package/dist/config/dist/lib/define-config.d.ts.map +0 -1
- package/dist/config/dist/lib/neon-api.d.ts +0 -375
- package/dist/config/dist/lib/neon-api.d.ts.map +0 -1
- package/dist/config/dist/lib/types.d.ts +0 -544
- package/dist/config/dist/lib/types.d.ts.map +0 -1
- package/dist/config/dist/v1.d.ts +0 -5
- package/dist/lib/cli/commands.d.ts +0 -68
- package/dist/lib/cli/commands.d.ts.map +0 -1
- package/dist/lib/cli/commands.js +0 -233
- package/dist/lib/cli/commands.js.map +0 -1
- package/dist/lib/cli/resolve-api-key.d.ts +0 -29
- package/dist/lib/cli/resolve-api-key.d.ts.map +0 -1
- package/dist/lib/cli/resolve-api-key.js +0 -74
- package/dist/lib/cli/resolve-api-key.js.map +0 -1
- package/dist/lib/cli/resolve-context.d.ts +0 -34
- package/dist/lib/cli/resolve-context.d.ts.map +0 -1
- package/dist/lib/cli/resolve-context.js +0 -88
- package/dist/lib/cli/resolve-context.js.map +0 -1
- package/dist/lib/env.d.ts +0 -509
- package/dist/lib/env.d.ts.map +0 -1
- package/dist/lib/env.js.map +0 -1
- package/dist/lib/reuse-secrets.d.ts +0 -95
- package/dist/lib/reuse-secrets.d.ts.map +0 -1
- package/dist/lib/reuse-secrets.js +0 -181
- package/dist/lib/reuse-secrets.js.map +0 -1
- package/dist/runtime.d.ts +0 -2
- package/dist/runtime.js +0 -2
package/README.md
CHANGED
|
@@ -12,14 +12,13 @@ npm install @neon/env
|
|
|
12
12
|
|
|
13
13
|
> **Requirements:** Node.js >= 20.19.
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## What's in it
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
| `@neon/env/runtime` | The stateful half: `fetchEnvReusingSecrets`, for tools that resolve the same branch repeatedly and must not re-mint a credential each time. It reads an env source and can mint and revoke credentials. Import it from a CLI or CI, never from an app bootstrap. |
|
|
17
|
+
Everything is on `@neon/env`, and none of it has side effects: `fetchEnv` asks the Neon API for a branch's env, `parseEnv` validates what was already injected into `process.env`, `toEntries` projects a resolved env into `{ KEY: value }`. Nothing here writes a file, mutates `process.env`, or creates or destroys anything on your Neon project — so importing this package from an app, a build script, or a `neon.ts` policy can't surprise you.
|
|
18
|
+
|
|
19
|
+
> **`@neon/env/runtime` was removed in 0.16.0.** It held `fetchEnvReusingSecrets`, which reads an env source and can mint and revoke branch credentials — implementation shared with the `neon` CLI, not something to hand an application. If you were importing it, the [`neon` CLI](../cli) (`neon env pull`, `neon dev`) does the same job; if you need to do it yourself, [The branch credential](#the-branch-credential) says what the hard part actually is.
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
Contributing? See [`CONTRIBUTING.md`](./CONTRIBUTING.md).
|
|
23
22
|
|
|
24
23
|
## Functions
|
|
25
24
|
|
|
@@ -55,7 +54,6 @@ Both return the same namespaced `NeonEnv` shape: `postgres` is always present; `
|
|
|
55
54
|
| Function | Description |
|
|
56
55
|
| --- | --- |
|
|
57
56
|
| `fetchEnv(config, { projectId, branch, ... })` | Async. Calls the Neon API for the given project + branch and returns live connection strings (and Auth/Data API values when enabled). `projectId` and `branch` are required; `branch` accepts a branch **name** (e.g. `main`) or a `br-…` id. (The legacy id-only `branchId` option still works.) Pass `keys` to fetch only some vars — see [Fetching a subset](#fetching-a-subset). Reads nothing from `process.env` or disk. |
|
|
58
|
-
| `fetchEnvReusingSecrets(config, { projectId, branch, env })` | Async, from **`@neon/env/runtime`**. `fetchEnv` plus reuse of one-time secrets you already hold: verifies them against the branch, keeps what's valid, mints and revokes only when it must. Returns `{ vars, credential }`. Takes an optional `revokeSuperseded`, which keeps the replaced credential live when your call resolves only part of the branch. Use this rather than `fetchEnv` anywhere the same branch is resolved repeatedly — see [The branch credential](#the-branch-credential). |
|
|
59
57
|
| `parseEnv(config)` / `parseEnv(config, slug)` / `parseEnv(config, keys)` | Sync. Reads/validates the Neon env vars already present in `process.env` against the static policy toggles. With a function `slug`, also returns a typed `function` namespace of that function's declared env keys. With a `keys` array (e.g. `["DATABASE_URL"]`), only those vars are required and returned, as a narrowed namespaced shape — the keys are typesafe against the policy. Throws `PlatformError(EnvNotInjected)` listing missing vars when the env isn't populated. |
|
|
60
58
|
| `toEntries(env)` | Project a resolved `NeonEnv` into `{ KEY: value }` pairs for cross-process transport (named after the web `.entries()` convention; returns a `Record`). |
|
|
61
59
|
|
|
@@ -135,30 +133,11 @@ These are the OS-level vars `fetchEnv` / `parseEnv` read and `toEntries` (so `ne
|
|
|
135
133
|
|
|
136
134
|
Object storage and the AI Gateway are backed by one branch credential, and the Neon API returns its secrets (`s3_secret_access_key`, `api_token`) **once**, at mint time — they aren't stored server-side, and the list endpoint returns metadata only. So there is nothing to *fetch*: `fetchEnv` mints. Call it on every `neon dev` start and you leave a live credential behind each time.
|
|
137
135
|
|
|
138
|
-
|
|
136
|
+
Handling that is the caller's problem, and it is not just "cache the secret": a persisted secret is only reusable if it still names a live credential on that branch — unrevoked, unexpired, and carrying every scope the policy needs. A presence check cannot tell a real secret from a `.env.example` placeholder.
|
|
139
137
|
|
|
140
|
-
|
|
141
|
-
import { fetchEnvReusingSecrets } from "@neon/env/runtime";
|
|
142
|
-
|
|
143
|
-
const { vars, credential } = await fetchEnvReusingSecrets(config, {
|
|
144
|
-
projectId,
|
|
145
|
-
branch: "main",
|
|
146
|
-
env: { ...process.env, ...readEnvFile(".env") },
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
// vars: { DATABASE_URL: "…", AWS_ACCESS_KEY_ID: "…", … } — ready to write or inject
|
|
150
|
-
if (credential.issued) {
|
|
151
|
-
console.log(`new values for ${credential.keys.join(", ")}`);
|
|
152
|
-
// credential.revoked — ids it replaced and revoked
|
|
153
|
-
// credential.superseded — ids it replaced but left live (`revokeSuperseded: false`)
|
|
154
|
-
}
|
|
155
|
-
```
|
|
138
|
+
No local bookkeeping is needed to do it, because the secrets carry their own credential id: `AWS_ACCESS_KEY_ID` **is** the credential's token id, and the AI Gateway token is minted as `nt_live_<tokenIdShort>_<secret>`. So the `.env` you are about to rewrite already records which credential issued it.
|
|
156
139
|
|
|
157
|
-
The
|
|
158
|
-
|
|
159
|
-
No local bookkeeping backs this: `AWS_ACCESS_KEY_ID` **is** the credential's token id, and the AI Gateway token is minted as `nt_live_<tokenIdShort>_<secret>`, so the persisted secrets already name the credential that issued them.
|
|
160
|
-
|
|
161
|
-
Revoking is only safe because the call resolves everything the policy enables. Pass `revokeSuperseded: false` when yours resolves a **subset** — the credential your persisted secrets name may also back a service you are not resolving, and revoking it would break that service while its vars, which you are not rewriting, stay in place. The cost is an orphaned credential, which is the safer of the two failures, and `credential.superseded` names it so you can report it rather than leave it invisible. `neon env pull --service` is the caller this exists for.
|
|
140
|
+
The [`neon` CLI](../cli) does all of this — `neon env pull` and `neon dev` reuse a branch credential rather than issuing one per run. If you are calling `fetchEnv` on a loop yourself, `credentialScopesSatisfied` and `deriveCredentialScopes` from `@neon/config/v1`, plus `listCredentials` / `createCredential` / `revokeCredential` on a `NeonApi`, are the pieces you need.
|
|
162
141
|
|
|
163
142
|
### Fetching a subset
|
|
164
143
|
|
|
@@ -173,6 +152,19 @@ const { storage } = await fetchEnv(config, {
|
|
|
173
152
|
storage.endpoint; // string — `accessKeyId` is absent, and never fetched
|
|
174
153
|
```
|
|
175
154
|
|
|
155
|
+
Inline key arrays autocomplete from the services enabled in `config`, reject unknown or disabled keys, and narrow the result exactly without `as const`. A runtime-built array returns the same selected values with optional namespaces and properties, because the array may contain any subset of its declared key union:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
const keys: Array<"DATABASE_URL" | "NEON_BRANCH"> =
|
|
159
|
+
process.env.INCLUDE_BRANCH ? ["DATABASE_URL", "NEON_BRANCH"] : ["DATABASE_URL"];
|
|
160
|
+
const selected = await fetchEnv(config, { projectId, branch: "main", keys });
|
|
161
|
+
|
|
162
|
+
selected.postgres?.databaseUrl; // string | undefined
|
|
163
|
+
selected.branch?.name; // string | undefined
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` are one credential and must be selected together. Literal lists that contain only one half are a type error; a runtime-built list that resolves to one half throws before any API request or credential issuance.
|
|
167
|
+
|
|
176
168
|
Work is skipped, not just the result narrowed. Leave out `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `NEON_AI_GATEWAY_TOKEN` and **no credential is minted at all** — which is exactly how `fetchEnvReusingSecrets` refreshes everything else while keeping secrets you already have. The non-secret vars of those features (`AWS_ENDPOINT_URL_S3`, `AWS_REGION`, `NEON_AI_GATEWAY_BASE_URL`) are branch metadata and stay available on their own.
|
|
177
169
|
|
|
178
170
|
## Connection role & database selection
|