@neondatabase/env 0.1.2 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":["ComputeUnit","ComputeSettings","BranchTarget","ServiceToggle","PostgresConfig","FunctionRuntime","FunctionMemoryMib","FunctionDevConfig","FunctionConfig","Record","BucketAccessLevel","BucketConfig","PreviewConfig","BranchConfigBase","BranchServiceConfig","BranchConfig","Config","ResolvedFunctionConfig","ResolvedBucketConfig","ResolvedPreviewConfig","ResolvedBranchConfig","AppliedChange","ConflictReport","PushResult"],"sources":["../../../../../config/dist/lib/types.d.ts"],"sourcesContent":["//#region src/lib/types.d.ts\n/**\n * Valid Neon Compute Unit values.\n * Most plans support 0.25, 0.5, 1, 2, 4, 8. Higher values may be available on Business plans.\n */\ntype ComputeUnit = 0.25 | 0.5 | 1 | 2 | 4 | 8;\n/**\n * Compute settings applied to the read/write endpoint of a branch.\n *\n * Mirrors the subset of {@link https://api-docs.neon.tech/reference/getting-started-with-neon-api Neon endpoint}\n * fields that we expose as IaC primitives. Anything left undefined falls back to the project's\n * `default_endpoint_settings` (which themselves fall back to Neon platform defaults).\n */\ninterface ComputeSettings {\n /**\n * Minimum number of Compute Units. Set to 0.25 for true scale-to-zero.\n * @example 0.25 // scale-to-zero\n * @example 1 // always-on with 1 CU minimum\n */\n autoscalingLimitMinCu?: ComputeUnit;\n /**\n * Maximum number of Compute Units for autoscaling.\n * @example 2\n * @example 8\n */\n autoscalingLimitMaxCu?: ComputeUnit;\n /**\n * How long to wait before suspending an idle compute.\n *\n * - `false` — never suspend (always-on compute)\n * - `\"5m\"` — duration string (supports \"30s\", \"5m\", \"1h\", \"7d\", etc)\n * - `300` — custom timeout in seconds (60-604800)\n * - `undefined` — use Neon platform default (currently 300s / 5 minutes)\n *\n * @example false // never suspend\n * @example \"5m\" // 5 minutes\n * @example \"1h\" // 1 hour\n * @example 300 // 5 minutes in seconds\n */\n suspendTimeout?: false | \"5m\" | \"1h\" | string | number;\n}\n/**\n * Read-only descriptor of the branch a {@link Config} policy is being evaluated for — the\n * `branch` argument passed to your `defineConfig((branch) => …)` callback. It describes\n * **which** branch this invocation decides for; it is not a live branch handle and must not\n * be mutated. Switch on its fields and return the desired {@link BranchConfig}.\n */\ninterface BranchTarget {\n /** Branch name being evaluated. For `branch dev`, this is the generated branch name. */\n name: string;\n /** Neon branch id when the branch already exists. Undefined during pre-create eval. */\n id?: string;\n /** Whether this branch already exists on Neon. */\n exists: boolean;\n /** Parent branch id from Neon when known. */\n parentId?: string;\n /** Whether Neon marks this branch as the project default. */\n isDefault?: boolean;\n /** Whether Neon currently marks this branch protected. */\n isProtected?: boolean;\n /** Current expiration timestamp from Neon, when set. */\n expiresAt?: string;\n}\ninterface ServiceToggle {\n /** Defaults to `true` when the service namespace is present. Set `false` to opt out. */\n enabled?: boolean;\n}\ninterface PostgresConfig {\n computeSettings?: ComputeSettings;\n}\n/**\n * Supported function runtimes. Mirrors the Neon Functions deploy API `runtime` enum.\n * Only `nodejs24` exists today; kept as a union so adding runtimes later is a\n * non-breaking, type-checked change.\n */\ntype FunctionRuntime = \"nodejs24\";\n/**\n * Memory sizes (MiB) accepted by the Neon Functions deploy API. Mirrors the\n * `memory_mib` enum in the spec.\n */\ntype FunctionMemoryMib = 256 | 512 | 1024 | 2048 | 4096 | 8192;\n/**\n * Local-development settings for a function, used by `neon dev` when it serves every\n * function declared in `neon.ts` (i.e. invoked with no `--source`). Never affects deploy.\n *\n * `port` and `portless` are independent:\n *\n * - `portless: true` — wrap this function's local server with `portless <slug> …` so it gets\n * a stable `slug.localhost` URL. Portless assigns the port itself (it injects `PORT`), so\n * `port` is ignored in this mode.\n * - otherwise — serve directly. `port`, when set, is bound exactly (and `neon dev` fails\n * loudly if it is taken); when omitted a free port is found automatically.\n */\ninterface FunctionDevConfig {\n /**\n * Port the local server binds. Bound exactly (fails if taken) when set; a free port is\n * found when omitted. Ignored when `portless` is true (portless assigns the port).\n */\n port?: number;\n /**\n * Expose this function via `portless` (a stable `slug.localhost` URL). Requires the\n * `portless` binary on PATH. Portless assigns the port, so `port` is ignored here.\n */\n portless?: boolean;\n}\n/**\n * A single Neon Function deployed to a branch (Preview feature).\n *\n * A function is invoked like a Cloudflare/Vercel handler — its source module\n * `export default { fetch }` or `export async function handler(req): Response`. The\n * `source` path is bundled (esbuild) and uploaded as a deployment; the newest\n * deployment becomes active.\n */\ninterface FunctionConfig {\n /**\n * Branch-unique slug used as the path segment in the function's invocation URL.\n * Immutable once created. 1–20 lowercase letters and digits: `^[a-z0-9]{1,20}$`.\n * @example \"hellofn\"\n */\n slug: string;\n /** Free-form display name. @example \"Hello World\" */\n name: string;\n /**\n * Path to the function's entry module, **relative to `neon.ts`** (or absolute). The\n * module's default export (`{ fetch }`) or `handler` export is the function entry. This\n * path is resolved against the loaded `neon.ts` location and bundled with esbuild at\n * deploy time.\n *\n * We require a string path rather than an imported handler because a JS function value\n * carries no reference back to its source file, so esbuild has nothing to bundle from.\n * @example \"./functions/hello-world.ts\"\n */\n source: string;\n /**\n * Environment variables injected into the deployed function. Every value must be a\n * defined string — a `process.env.X` that is `undefined` (unset) errors at validation\n * time rather than silently shipping `undefined`.\n * @example { RESEND_API_KEY: process.env.RESEND_API_KEY }\n */\n env?: Record<string, string>;\n /** Runtime to execute the function with. Defaults to `\"nodejs24\"`. */\n runtime?: FunctionRuntime;\n /** Memory allotted to each invocation, in MiB. Defaults to `512`. */\n memoryMib?: FunctionMemoryMib;\n /**\n * Local-development settings used by `neon dev` when serving every function from\n * `neon.ts`. Ignored at deploy time. See {@link FunctionDevConfig}.\n */\n dev?: FunctionDevConfig;\n}\n/** Anonymous-access level for a branchable object-storage bucket. */\ntype BucketAccessLevel = \"private\" | \"public_read\";\n/**\n * A branchable object-storage bucket on a branch (Preview feature).\n */\ninterface BucketConfig {\n /** Bucket name, unique within a branch. 1–255 chars. */\n name: string;\n /**\n * Anonymous access level. `private` (default) requires authenticated reads/writes;\n * `public_read` allows anonymous GetObject/HeadObject.\n */\n access?: BucketAccessLevel;\n}\n/**\n * Branch-scoped Preview features. Grouped under `preview` to signal they are backed by\n * Neon `x-stability-level: beta` endpoints and may change before GA.\n */\ninterface PreviewConfig {\n /** Functions to deploy on the branch. */\n functions?: FunctionConfig[];\n /** Object-storage buckets to create on the branch. */\n buckets?: BucketConfig[];\n /** Enable/disable the AI Gateway on the branch (toggle, like auth / dataApi). */\n aiGateway?: ServiceToggle;\n}\ninterface BranchConfigBase {\n /** Parent branch name used when creating a new branch. Not a Postgres setting. */\n parent?: string;\n /** Time-to-live applied when creating a new branch, or reconciled on existing branches. */\n ttl?: string | number;\n /** Whether the selected branch should be protected. Undefined means \"leave as-is\". */\n protected?: boolean;\n postgres?: PostgresConfig;\n /**\n * Branch-scoped Preview features (functions, object-storage buckets, AI Gateway).\n * Backed by Neon `x-stability-level: beta` endpoints — see {@link PreviewConfig}.\n */\n preview?: PreviewConfig;\n}\ntype BranchServiceConfig = {\n auth?: never;\n dataApi?: never;\n} | {\n auth: ServiceToggle;\n dataApi?: never;\n} | {\n auth?: never;\n dataApi: ServiceToggle;\n} | {\n auth: ServiceToggle;\n dataApi: ServiceToggle;\n};\ntype BranchConfig = BranchConfigBase & BranchServiceConfig;\ntype Config = (branch: BranchTarget) => BranchConfig;\n/**\n * A function with all deploy defaults applied. `resolveConfig` fills in `runtime` and\n * `memoryMib` so downstream diff/apply never has to re-derive them.\n */\ninterface ResolvedFunctionConfig {\n slug: string;\n name: string;\n source: string;\n env: Record<string, string>;\n runtime: FunctionRuntime;\n memoryMib: FunctionMemoryMib;\n /**\n * Local-development settings, passed through untouched from {@link FunctionConfig.dev}\n * (no defaults applied). Only consumed by `neon dev`; deploy ignores it.\n */\n dev?: FunctionDevConfig;\n}\n/** A bucket with its access level defaulted to `private`. */\ninterface ResolvedBucketConfig {\n name: string;\n access: BucketAccessLevel;\n}\n/**\n * Normalized {@link PreviewConfig}. Only present on {@link ResolvedBranchConfig} when the\n * policy returned a `preview` block. `aiGatewayEnabled` follows the same\n * \"present-and-not-`false`\" semantics as `authEnabled` / `dataApiEnabled`.\n */\ninterface ResolvedPreviewConfig {\n functions: ResolvedFunctionConfig[];\n buckets: ResolvedBucketConfig[];\n aiGatewayEnabled: boolean;\n}\ninterface ResolvedBranchConfig {\n parent?: string;\n ttlSeconds?: number;\n protected?: boolean;\n postgres?: PostgresConfig;\n authEnabled: boolean;\n dataApiEnabled: boolean;\n preview?: ResolvedPreviewConfig;\n}\n/**\n * One concrete change `pushConfig` made (or, in dry-run, would make) on the remote.\n */\ninterface AppliedChange {\n /**\n * `service` covers branch-scoped integrations driven by the branch policy (e.g.\n * Neon Auth, Data API).\n */\n kind: \"branch\" | \"service\";\n action: \"create\" | \"update\" | \"noop\";\n identifier: string;\n details?: Record<string, unknown>;\n}\n/**\n * A diff entry that conflicts with the desired config. `pushConfig` throws\n * {@link PushConflictError} on the first call when conflicts exist; pass\n * `updateExisting: true` to apply mutable drift (settings, `protected`, TTL, project\n * rename). Immutable fields (region, Postgres major version) are always conflicts —\n * recreate the project to change them.\n */\ninterface ConflictReport {\n kind: \"branch\";\n identifier: string;\n field: string;\n current: unknown;\n desired: unknown;\n reason: string;\n}\n/**\n * Result of a `pushConfig` invocation.\n */\ninterface PushResult {\n projectId: string;\n orgId?: string;\n branchId: string;\n branchName: string;\n /**\n * `true` when `pushConfig` was called with `{ dryRun: true }`. `applied` then records\n * what **would** be applied on a real push; no API mutations were performed.\n */\n dryRun: boolean;\n applied: AppliedChange[];\n conflicts: ConflictReport[];\n}\n//#endregion\nexport { AppliedChange, BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, ComputeUnit, Config, ConflictReport, FunctionConfig, FunctionDevConfig, FunctionMemoryMib, FunctionRuntime, PostgresConfig, PreviewConfig, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle };\n//# sourceMappingURL=types.d.ts.map"],"mappings":";;;AAKgB;;;KAAXA,WAAAA,GAoBqBA,IAAAA,GAAAA,GAAAA,GAAAA,CAAAA,GAAAA,CAAAA,GAAAA,CAAAA,GAAAA,CAAAA;AAAW;AAAA;AAsBf;AAgBC;AAKY;AAOf;AAKE;AAaK,UAhFjBC,eAAAA,CAoGc;EAAA;;;;;EAmCC,qBAAA,CAAA,EAjICD,WAiID;EAAA;AAGH;AAWM;;;uBAUhBW,CAAAA,EAnJcX,WAmJdW;;AAEe;AAAA;;;;AAcF;AAAA;;;;;;EAaD,cAAA,CAAA,EAAA,KAAA,GAAA,IAAA,GAAA,IAAA,GAAA,MAAA,GAAA,MAAA;AAAA;;;;AAEkC;AAAA;;UA5JhDT,YAAAA,CA6JaA;;EAA6B,IAAA,EAAA,MAAA;;;;;;;;;;;;;;UA7I1CC,aAAAA;;;;UAIAC,cAAAA;oBACUH;;;;;;;KAOfI,eAAAA;;;;;KAKAC,iBAAAA;;;;;;;;;;;;;UAaKC,iBAAAA;;;;;;;;;;;;;;;;;;;;UAoBAC,cAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;QA0BFC;;YAEIJ;;cAEEC;;;;;QAKNC;;;KAGHG,iBAAAA;;;;UAIKC,YAAAA;;;;;;;WAOCD;;;;;;UAMDE,aAAAA;;cAEIJ;;YAEFG;;cAEER;;UAEJU,gBAAAA;;;;;;;aAOGT;;;;;YAKDQ;;KAEPE,mBAAAA;;;;QAIGX;;;;WAIGA;;QAEHA;WACGA;;KAENY,YAAAA,GAAeF,mBAAmBC;KAClCE,MAAAA,YAAkBd,iBAAiBa"}
1
+ {"version":3,"file":"types.d.ts","names":["ComputeUnit","DurationUnit","DurationString","SuspendTimeoutSuggestion","TtlSuggestion","DurationField","Suggestions","NonNullable","ComputeSettings","BranchTarget","ServiceToggle","ServiceToggleInput","PostgresConfig","FunctionRuntime","FunctionDevConfig","FunctionDef","Record","BucketAccessLevel","BucketDef","PreviewInput","FunctionTuning","PreviewTuning","Slug","Partial","BranchTuning","FunctionSlugsOf","Preview","F","Extract","BranchTuningFn","Config","Auth","DataApi","ResolvedFunctionConfig","ResolvedBucketConfig","ResolvedPreviewConfig","ResolvedBranchConfig","AppliedChange","ConflictReport","PushResult"],"sources":["../../../../../config/dist/lib/types.d.ts"],"sourcesContent":["//#region src/lib/types.d.ts\n/**\n * Valid Neon Compute Unit values.\n * Most plans support 0.25, 0.5, 1, 2, 4, 8. Higher values may be available on Business plans.\n */\ntype ComputeUnit = 0.25 | 0.5 | 1 | 2 | 4 | 8;\n/** Time units accepted in a {@link DurationString}: seconds, minutes, hours, days, weeks. */\ntype DurationUnit = \"s\" | \"m\" | \"h\" | \"d\" | \"w\";\n/**\n * A Neon duration string: a positive integer **followed by a unit** — `s` (seconds),\n * `m` (minutes), `h` (hours), `d` (days), or `w` (weeks). Used by\n * {@link ComputeSettings.suspendTimeout} and {@link BranchTuning.ttl}.\n *\n * A **unit is required**: a bare numeric string like `\"7\"` is rejected at the type level. To\n * express a raw number of seconds, pass a `number` (`300`) — not a string (`\"300\"`). This\n * removes the old ambiguity where `\"7\"` silently meant 7 *seconds* instead of, say, `\"7d\"`.\n *\n * @example \"5m\" // 5 minutes\n * @example \"1h\" // 1 hour\n * @example \"7d\" // 7 days\n */\ntype DurationString = `${number}${DurationUnit}`;\n/**\n * Autocomplete suggestions for {@link ComputeSettings.suspendTimeout}. Every value sits inside\n * the Neon API's allowed scale-to-zero band: **60s–604800s** (1 minute – 1 week). This is *not*\n * a closed set — the field also accepts any other {@link DurationString} or a `number` of\n * seconds; out-of-range values type-check but are rejected at apply time.\n */\ntype SuspendTimeoutSuggestion = \"1m\" | \"5m\" | \"15m\" | \"30m\" | \"1h\" | \"6h\" | \"12h\" | \"1d\" | \"7d\";\n/**\n * Autocomplete suggestions for {@link BranchTuning.ttl}. Every value sits within the Neon API's\n * branch-expiration limit (**max 30 days** from creation; the Console's own presets are 1h / 1d\n * / 7d). This is *not* a closed set — the field also accepts any other {@link DurationString} or\n * a `number` of seconds; values over 30 days are rejected at apply time.\n */\ntype TtlSuggestion = \"1h\" | \"6h\" | \"12h\" | \"1d\" | \"3d\" | \"7d\" | \"14d\" | \"30d\";\n/**\n * Compose a field's duration type: its curated autocomplete `Suggestions` plus the open\n * `DurationString` template (so any `<integer><unit>` string still type-checks) and a `number`\n * of seconds. Intersecting the template arm with `NonNullable<unknown>` stops TypeScript from\n * collapsing the literal suggestions into the template, which is what preserves the autocomplete.\n */\ntype DurationField<Suggestions extends DurationString> = Suggestions | (DurationString & NonNullable<unknown>) | number;\n/**\n * Compute settings applied to the read/write endpoint of a branch.\n *\n * Mirrors the subset of {@link https://api-docs.neon.tech/reference/getting-started-with-neon-api Neon endpoint}\n * fields that we expose as IaC primitives. Anything left undefined falls back to the project's\n * `default_endpoint_settings` (which themselves fall back to Neon platform defaults).\n */\ninterface ComputeSettings {\n /**\n * Minimum number of Compute Units. Set to 0.25 for true scale-to-zero.\n * @example 0.25 // scale-to-zero\n * @example 1 // always-on with 1 CU minimum\n */\n autoscalingLimitMinCu?: ComputeUnit;\n /**\n * Maximum number of Compute Units for autoscaling.\n * @example 2\n * @example 8\n */\n autoscalingLimitMaxCu?: ComputeUnit;\n /**\n * How long an idle compute waits before suspending (Neon's scale-to-zero). Accepts a\n * {@link DurationString} (autocompletes common values), a number of seconds, or `false`.\n *\n * - `false` — never suspend (always-on compute)\n * - {@link DurationString} — e.g. `\"5m\"`; autocompletes the in-range values `\"1m\"`, `\"5m\"`,\n * `\"15m\"`, `\"30m\"`, `\"1h\"`, `\"6h\"`, `\"12h\"`, `\"1d\"`, `\"7d\"`, and accepts any other\n * `<integer><unit>` (units: `s`, `m`, `h`, `d`, `w`). A **unit is required** — for raw\n * seconds pass a `number`, not a string.\n * - `number` — custom timeout in **seconds**, must be in `60`–`604800` (1 minute to 1 week)\n * - `undefined` — use the Neon platform default (currently 300s / 5 minutes)\n *\n * Whichever form you use, the resolved timeout must fall in `60`–`604800` seconds (the Neon\n * API limit); the suggestions are all within that band, anything else is checked at apply.\n *\n * @example false // never suspend (always-on)\n * @example \"5m\" // suspend after 5 minutes idle\n * @example \"1h\" // suspend after 1 hour idle\n * @example 300 // 5 minutes, expressed in seconds\n */\n suspendTimeout?: false | DurationField<SuspendTimeoutSuggestion>;\n}\n/**\n * Read-only descriptor of the branch a {@link Config} policy is being evaluated for — the\n * `branch` argument passed to your `defineConfig((branch) => …)` callback. It describes\n * **which** branch this invocation decides for; it is not a live branch handle and must not\n * be mutated. Switch on its fields and return the desired {@link BranchConfig}.\n */\ninterface BranchTarget {\n /** Branch name being evaluated. For `branch dev`, this is the generated branch name. */\n name: string;\n /** Neon branch id when the branch already exists. Undefined during pre-create eval. */\n id?: string;\n /** Whether this branch already exists on Neon. */\n exists: boolean;\n /** Parent branch id from Neon when known. */\n parentId?: string;\n /** Whether Neon marks this branch as the project default. */\n isDefault?: boolean;\n /** Whether Neon currently marks this branch protected. */\n isProtected?: boolean;\n /** Current expiration timestamp from Neon, when set. */\n expiresAt?: string;\n}\n/**\n * Object form of a branch-scoped service toggle. `{}` or `{ enabled: true }` enables it;\n * `{ enabled: false }` opts out. Used as the object half of {@link ServiceToggleInput}.\n */\ninterface ServiceToggle {\n /** Defaults to `true` when the service namespace is present. Set `false` to opt out. */\n enabled?: boolean;\n}\n/**\n * How a branch-scoped service (Neon Auth, Data API, AI Gateway) is toggled in a policy.\n *\n * - `true` / `{}` / `{ enabled: true }` — enabled.\n * - `false` / `{ enabled: false }` — disabled.\n * - omitted (`undefined`) — not part of the policy at all.\n *\n * These toggles are **static** (they live in the top-level `defineConfig({ … })` object,\n * not in the per-branch `branch` closure) so the secret set they imply can be derived at\n * the type level — that's what makes `NeonEnv<typeof config>` exact.\n */\ntype ServiceToggleInput = boolean | ServiceToggle;\ninterface PostgresConfig {\n computeSettings?: ComputeSettings;\n}\n/**\n * Supported function runtimes. Mirrors the Neon Functions deploy API `runtime` enum.\n * Only `nodejs24` exists today; kept as a union so adding runtimes later is a\n * non-breaking, type-checked change.\n */\ntype FunctionRuntime = \"nodejs24\";\n/**\n * Local-development settings for a function, used by `neon dev` when it serves every\n * function declared in `neon.ts` (i.e. invoked with no `--source`). Never affects deploy.\n *\n * `port` and `portless` are independent:\n *\n * - `portless: true` — wrap this function's local server with `portless <slug> …` so it gets\n * a stable `slug.localhost` URL. Portless assigns the port itself (it injects `PORT`), so\n * `port` is ignored in this mode.\n * - otherwise — serve directly. `port`, when set, is bound exactly (and `neon dev` fails\n * loudly if it is taken); when omitted a free port is found automatically.\n */\ninterface FunctionDevConfig {\n /**\n * Port the local server binds. Bound exactly (fails if taken) when set; a free port is\n * found when omitted. Ignored when `portless` is true (portless assigns the port).\n */\n port?: number;\n /**\n * Expose this function via `portless` (a stable `slug.localhost` URL). Requires the\n * `portless` binary on PATH. Portless assigns the port, so `port` is ignored here.\n */\n portless?: boolean;\n}\n/**\n * Static definition of a Neon Function (Preview feature). Declares that the function\n * **exists** on every branch; its branch-unique slug is the **record key** in\n * {@link PreviewInput.functions} (not a field here), so slugs are statically enumerable,\n * cannot duplicate, and the `branch` closure can only tune slugs that are declared here.\n *\n * A function is invoked like a Cloudflare/Vercel handler — its source module\n * `export default { fetch }` or `export async function handler(req): Response`. The\n * `source` path is bundled (esbuild) and uploaded as a deployment; the newest deployment\n * becomes active.\n *\n * Runtime tuning is **not** here — it varies per branch and lives in the `branch` closure\n * (see {@link FunctionTuning}). Memory is fixed by the platform policy for now and is not\n * user-configurable.\n */\ninterface FunctionDef {\n /** Free-form display name. @example \"Hello World\" */\n name: string;\n /**\n * Path to the function's entry module, **relative to `neon.ts`** (or absolute). The\n * module's default export (`{ fetch }`) or `handler` export is the function entry. This\n * path is resolved against the loaded `neon.ts` location and bundled with esbuild at\n * deploy time.\n *\n * We require a string path rather than an imported handler because a JS function value\n * carries no reference back to its source file, so esbuild has nothing to bundle from.\n * @example \"./functions/hello-world.ts\"\n */\n source: string;\n /**\n * Environment variables injected into the deployed function, keyed by the var name the\n * function reads at runtime. The **keys** are static (preserved at the type level so\n * `parseEnv(config, \"<slug>\").function.<key>` is typed); the **values** are arbitrary\n * strings evaluated when `neon.ts` is loaded (typically `process.env.X`) and uploaded\n * at `config apply`. Every value must be a defined string — a `process.env.X` that is\n * `undefined` (unset) errors at validation time rather than silently shipping\n * `undefined`.\n * @example { resendApiKey: process.env.RESEND_API_KEY ?? \"\" }\n */\n env?: Record<string, string>;\n /**\n * Local-development settings used by `neon dev` when serving every function from\n * `neon.ts`. Ignored at deploy time. See {@link FunctionDevConfig}.\n */\n dev?: FunctionDevConfig;\n}\n/** Anonymous-access level for a branchable object-storage bucket. */\ntype BucketAccessLevel = \"private\" | \"public_read\";\n/**\n * Static definition of a branchable object-storage bucket (Preview feature). The bucket's\n * name is the **record key** in {@link PreviewInput.buckets}, so names are statically\n * enumerable and cannot duplicate.\n */\ninterface BucketDef {\n /**\n * Anonymous access level. `private` (default) requires authenticated reads/writes;\n * `public_read` allows anonymous GetObject/HeadObject.\n */\n access?: BucketAccessLevel;\n}\n/**\n * Static, branch-scoped **Preview** features. Grouped under `preview` to signal they are\n * backed by Neon `x-stability-level: beta` endpoints and may change before GA. Everything\n * here is existential (it determines what exists on the branch); per-branch tuning lives in\n * the `branch` closure.\n */\ninterface PreviewInput {\n /** Enable/disable the AI Gateway on the branch (toggle, like auth / dataApi). */\n aiGateway?: ServiceToggleInput;\n /** Functions to deploy, keyed by branch-unique slug (`^[a-z0-9]{1,20}$`). */\n functions?: Record<string, FunctionDef>;\n /** Object-storage buckets to create, keyed by bucket name. */\n buckets?: Record<string, BucketDef>;\n}\n/**\n * Per-branch deploy tuning for a single function. Returned (per slug) by the `branch`\n * closure. Deliberately **cannot** change the function's existence, source, name, env\n * **keys**, or memory — only runtime selection is currently configurable — so the static\n * secret/function set stays sound.\n */\ninterface FunctionTuning {\n /** Runtime to execute the function with. Defaults to `\"nodejs24\"`. */\n runtime?: FunctionRuntime;\n}\n/**\n * Per-branch tuning of Preview features. Only existing function slugs (those declared in\n * the static {@link PreviewInput.functions}) may be tuned — `Slug` is constrained to the\n * declared keys by {@link BranchTuningFn}.\n */\ninterface PreviewTuning<Slug extends string = string> {\n functions?: Partial<Record<Slug, FunctionTuning>>;\n}\n/**\n * The per-branch tuning object returned by the `branch` closure. It can adjust branch\n * lifecycle (`parent`, `ttl`, `protected`), Postgres compute settings, and per-function\n * deploy tuning — but **cannot** add/remove services or functions. That guarantee is what\n * keeps the static secret set (and therefore `NeonEnv`) exact.\n */\ninterface BranchTuning<Slug extends string = string> {\n /** Parent branch name used when creating a new branch. Not a Postgres setting. */\n parent?: string;\n /**\n * Branch time-to-live: how long after creation the branch should auto-expire. Applied\n * when creating a new branch and reconciled on existing branches (when `updateExisting`\n * is set). Accepts a {@link DurationString} (autocompletes common values) or a number of\n * seconds. Omit to keep the branch indefinitely.\n *\n * - {@link DurationString} — e.g. `\"7d\"`; autocompletes `\"1h\"`, `\"6h\"`, `\"12h\"`, `\"1d\"`,\n * `\"3d\"`, `\"7d\"`, `\"14d\"`, `\"30d\"`, and accepts any other `<integer><unit>` (units: `s`,\n * `m`, `h`, `d`, `w` — e.g. `\"12h\"`, `\"2w\"`). A **unit is required** — `\"7\"` is rejected;\n * for raw seconds pass a `number`.\n * - `number` — custom TTL in **seconds** (e.g. `3600`)\n * - `undefined` — no expiry; the branch persists until explicitly deleted\n *\n * The Neon API caps branch expiration at **30 days** from creation, so the resolved TTL must\n * be `> 0` and `<= 30d`; the suggestions stay within that limit and anything longer is\n * rejected at apply.\n *\n * @example \"1d\" // ephemeral preview branch: expires a day after creation\n * @example \"7d\" // one-week TTL\n * @example \"30d\" // the maximum the API allows\n * @example 3600 // 1 hour, expressed in seconds\n */\n ttl?: DurationField<TtlSuggestion>;\n /** Whether the selected branch should be protected. Undefined means \"leave as-is\". */\n protected?: boolean;\n postgres?: PostgresConfig;\n preview?: PreviewTuning<Slug>;\n}\n/** Extract the declared function slugs from a {@link PreviewInput} for closure typing. */\ntype FunctionSlugsOf<Preview extends PreviewInput | undefined> = Preview extends {\n functions: infer F;\n} ? Extract<keyof F, string> : string;\n/**\n * Signature of the `branch` closure. Generic over the static {@link PreviewInput} so the\n * `preview.functions` keys it may tune are constrained to the slugs actually declared.\n */\ntype BranchTuningFn<Preview extends PreviewInput | undefined = PreviewInput | undefined> = (branch: BranchTarget) => BranchTuning<FunctionSlugsOf<Preview>>;\n/**\n * A validated Neon branch policy — the value `defineConfig({ … })` returns and `neon.ts`\n * default-exports.\n *\n * Split into a **static** existential set (top-level `auth` / `dataApi` GA toggles plus the\n * beta `preview` block) and a **dynamic** per-branch `branch` closure for tuning. The\n * static half is what makes the secret set — and therefore `NeonEnv<typeof config>` and\n * `parseEnv` — exact; the closure can tune but never change what exists.\n *\n * Generic over the three static fields so the type system can read the exact toggle/slug\n * literals; the defaults make the bare `Config` a usable \"any policy\" type for runtime\n * function signatures.\n */\ninterface Config<Auth extends ServiceToggleInput | undefined = ServiceToggleInput | undefined, DataApi extends ServiceToggleInput | undefined = ServiceToggleInput | undefined, Preview extends PreviewInput | undefined = PreviewInput | undefined> {\n /** Neon Auth integration toggle (GA). Static — drives `NeonEnv.auth`. */\n auth?: Auth;\n /** Neon Data API integration toggle (GA). Static — drives `NeonEnv.dataApi`. */\n dataApi?: DataApi;\n /** Beta (Preview) feature set: AI Gateway, functions, buckets. Static. */\n preview?: Preview;\n /** Per-branch tuning closure. Cannot change the static existential set. */\n branch?: BranchTuningFn<Preview>;\n}\n/**\n * A function with all deploy defaults applied. `resolveConfig` fills in `runtime` so\n * downstream diff/apply never has to re-derive it.\n */\ninterface ResolvedFunctionConfig {\n slug: string;\n name: string;\n source: string;\n env: Record<string, string>;\n runtime: FunctionRuntime;\n /**\n * Local-development settings, passed through untouched from {@link FunctionDef.dev}\n * (no defaults applied). Only consumed by `neon dev`; deploy ignores it.\n */\n dev?: FunctionDevConfig;\n}\n/** A bucket with its access level defaulted to `private`. */\ninterface ResolvedBucketConfig {\n name: string;\n access: BucketAccessLevel;\n}\n/**\n * Normalized {@link PreviewInput}. Only present on {@link ResolvedBranchConfig} when the\n * policy returned a `preview` block. `aiGatewayEnabled` follows the same\n * \"present-and-not-`false`\" semantics as `authEnabled` / `dataApiEnabled`.\n */\ninterface ResolvedPreviewConfig {\n functions: ResolvedFunctionConfig[];\n buckets: ResolvedBucketConfig[];\n aiGatewayEnabled: boolean;\n}\ninterface ResolvedBranchConfig {\n parent?: string;\n ttlSeconds?: number;\n protected?: boolean;\n postgres?: PostgresConfig;\n authEnabled: boolean;\n dataApiEnabled: boolean;\n preview?: ResolvedPreviewConfig;\n}\n/**\n * One concrete change `pushConfig` made (or, in dry-run, would make) on the remote.\n */\ninterface AppliedChange {\n /**\n * `service` covers branch-scoped integrations driven by the branch policy (e.g.\n * Neon Auth, Data API).\n */\n kind: \"branch\" | \"service\";\n action: \"create\" | \"update\" | \"noop\";\n identifier: string;\n details?: Record<string, unknown>;\n}\n/**\n * A diff entry that conflicts with the desired config. `pushConfig` throws\n * {@link PushConflictError} on the first call when conflicts exist; pass\n * `updateExisting: true` to apply mutable drift (settings, `protected`, TTL, project\n * rename). Immutable fields (region, Postgres major version) are always conflicts —\n * recreate the project to change them.\n */\ninterface ConflictReport {\n kind: \"branch\";\n identifier: string;\n field: string;\n current: unknown;\n desired: unknown;\n reason: string;\n}\n/**\n * Result of a `pushConfig` invocation.\n */\ninterface PushResult {\n projectId: string;\n orgId?: string;\n branchId: string;\n branchName: string;\n /**\n * `true` when `pushConfig` was called with `{ dryRun: true }`. `applied` then records\n * what **would** be applied on a real push; no API mutations were performed.\n */\n dryRun: boolean;\n applied: AppliedChange[];\n conflicts: ConflictReport[];\n}\n//#endregion\nexport { AppliedChange, BranchTarget, BranchTuning, BranchTuningFn, BucketAccessLevel, BucketDef, ComputeSettings, ComputeUnit, Config, ConflictReport, DurationString, DurationUnit, FunctionDef, FunctionDevConfig, FunctionRuntime, FunctionTuning, PostgresConfig, PreviewInput, PreviewTuning, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle, ServiceToggleInput };\n//# sourceMappingURL=types.d.ts.map"],"mappings":";;;AAKgB;AAEC;AAc6B;AAOjB,KAvBxBA,WAAAA,GA8BAI,IAAa,GAAA,GAAA,GAAA,CAAA,GAAA,CAAA,GAAA,CAAA,GAAA,CAAA;AAAA;KA5BbH,YAAAA,GAmCa,GAAA,GAAA,GAAA,GAAA,GAAA,GAAA,GAAA,GAAA,GAAA;;;;;AAAkF;AAAA;;;;;;AAyC5D;AAAA;AAQlB,KAtEjBC,cAAAA,GA0FkB,GAAA,MAAA,GA1FWD,YA0FX,EAAA;AAAA;AAe0B;AAEd;AAOf;AAaO;;KAxHtBE,wBAAAA,GA2KGa,IAAAA,GAAAA,IAAAA,GAAAA,KAAAA,GAAAA,KAAAA,GAAAA,IAAAA,GAAAA,IAAAA,GAAAA,KAAAA,GAAAA,IAAAA,GAAAA,IAAAA;;AAKiB;AAAA;AAGH;AAWM;;KAvLvBZ,aAAAA,GAiMSO,IAAAA,GAAAA,IAAAA,GAAAA,KAAAA,GAAAA,IAAAA,GAAAA,IAAAA,GAAAA,IAAAA,GAAAA,KAAAA,GAAAA,KAAAA;;;;;AAII;AAAA;AAUS,KAxMtBN,aA+MKgB,CAAAA,oBA/M6BnB,cA+MhB,CAAA,GA/MkCI,WA+MlC,GAAA,CA/MiDJ,cA+MjD,GA/MkEK,WA+MlE,CAAA,OAAA,CAAA,CAAA,GAAA,MAAA;;;;;;AACF;AAAA;UAxMXC,eAAAA,CAgNY;;;;;;EA6BG,qBAAA,CAAA,EAvOCR,WAuOD;EAAA;;;;;uBAKrB4B,CAAAA,EAtOsB5B,WAsOtB4B;EAAO;AAAA;;;;;;;;AAKsH;AAAA;;;;;;;;;;gBAoBrHF,CAAAA,EAAAA,KAAAA,GA1OerB,aA0OfqB,CA1O6BvB,wBA0O7BuB,CAAAA;;;AAEa;;;;;UApOfjB,YAAAA;;;;;;;;;;;;;;;;;;;;UAoBAC,aAAAA;;;;;;;;;;;;;;;KAeLC,kBAAAA,aAA+BD;UAC1BE,cAAAA;oBACUJ;;;;;;;KAOfK,eAAAA;;;;;;;;;;;;;UAaKC,iBAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;UA2BAC,WAAAA;;;;;;;;;;;;;;;;;;;;;;;;QAwBFC;;;;;QAKAF;;;KAGHG,iBAAAA;;;;;;UAMKC,SAAAA;;;;;WAKCD;;;;;;;;UAQDE,YAAAA;;cAEIR;;cAEAK,eAAeD;;YAEjBC,eAAeE;;;;;;;;UAQjBE,cAAAA;;YAEEP;;;;;;;UAOFQ;cACIE,QAAQP,OAAOM,MAAMF;;;;;;;;UAQzBI;;;;;;;;;;;;;;;;;;;;;;;;;QAyBFnB,cAAcD;;;aAGTQ;YACDS,cAAcC;;;KAGrBG,gCAAgCN,4BAA4BO;;IAE7DE,cAAcD;;;;;KAKbE,+BAA+BV,2BAA2BA,qCAAqCV,iBAAiBe,aAAaC,gBAAgBC;;;;;;;;;;;;;;UAcxII,oBAAoBnB,iCAAiCA,gDAAgDA,iCAAiCA,gDAAgDQ,2BAA2BA;;SAElNY;;YAEGC;;YAEAN;;WAEDG,eAAeH"}
@@ -1,4 +1,4 @@
1
- import { BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, Config, FunctionConfig, FunctionDevConfig, FunctionMemoryMib, FunctionRuntime, PostgresConfig, PreviewConfig, ServiceToggle } from "./lib/types.js";
1
+ import { BranchTarget, BranchTuning, BranchTuningFn, BucketAccessLevel, BucketDef, ComputeSettings, ComputeUnit, Config, DurationString, DurationUnit, FunctionDef, FunctionDevConfig, FunctionRuntime, FunctionTuning, PostgresConfig, PreviewInput, PreviewTuning, ServiceToggle, ServiceToggleInput } from "./lib/types.js";
2
2
  import { CreateBranchInput, CreateBucketInput, CreateProjectInput, DeployFunctionInput, GetConnectionUriInput, NeonApi, NeonAuthSnapshot, NeonBranchSnapshot, NeonBucketSnapshot, NeonDataApiSnapshot, NeonDatabaseSnapshot, NeonEndpointSnapshot, NeonFunctionDeploymentSnapshot, NeonFunctionSnapshot, NeonProjectSnapshot, NeonRoleSnapshot, UpdateBranchInput } from "./lib/neon-api.js";
3
3
  import "zod";
4
4
  export {};
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { FetchEnvOptions, NEON_ENV_VAR_KEYS, NeonAuthEnv, NeonDataApiEnv, NeonEnv, NeonPostgresEnv, fetchEnv, parseEnv, toEntries } from "./lib/env.js";
2
- export { FetchEnvOptions, NEON_ENV_VAR_KEYS, NeonAuthEnv, NeonDataApiEnv, NeonEnv, NeonPostgresEnv, fetchEnv, parseEnv, toEntries };
1
+ import { FetchEnvOptions, FunctionSlugOf, NEON_ENV_VAR_KEYS, NeonAuthEnv, NeonDataApiEnv, NeonEnv, NeonFunctionEnv, NeonPostgresEnv, fetchEnv, parseEnv, toEntries } from "./lib/env.js";
2
+ export { FetchEnvOptions, FunctionSlugOf, NEON_ENV_VAR_KEYS, NeonAuthEnv, NeonDataApiEnv, NeonEnv, NeonFunctionEnv, NeonPostgresEnv, fetchEnv, parseEnv, toEntries };
@@ -26,14 +26,21 @@ interface CommandResult {
26
26
  /** Optional structured debug payload — printed only when `--debug` is passed. */
27
27
  debugInfo?: string;
28
28
  }
29
- interface EnvRunCommandOptions {
30
- /** The user command to spawn (after `--`). The first element is the executable. */
31
- command: string[];
29
+ /**
30
+ * Inputs needed to resolve a branch and fetch its env, shared by `run` and `export`: an
31
+ * optional explicit `neon.ts` path, project/branch overrides, and an API key (otherwise
32
+ * resolved from `.neon` / `NEON_*` env by the CLI and `NEON_API_KEY` by `fetchEnv`).
33
+ */
34
+ interface EnvResolveOptions {
32
35
  configPath?: string;
33
36
  projectId?: string;
34
37
  branch?: string;
35
38
  apiKey?: string;
36
39
  }
40
+ interface EnvRunCommandOptions extends EnvResolveOptions {
41
+ /** The user command to spawn (after `--`). The first element is the executable. */
42
+ command: string[];
43
+ }
37
44
  /**
38
45
  * Implementation of `neon-env run -- <cmd...>`. Loads `neon.ts`, fetches the env from
39
46
  * Neon, then spawns the user-supplied command with the env vars injected on top of the
@@ -41,6 +48,17 @@ interface EnvRunCommandOptions {
41
48
  * The parent process exits with the child's exit code.
42
49
  */
43
50
  declare function runEnvRun(options: EnvRunCommandOptions, ctx: CommandEnv): Promise<CommandResult>;
51
+ interface EnvExportCommandOptions extends EnvResolveOptions {
52
+ /** Output format. `dotenv` (KEY=value lines) by default; `json` for tooling / bulk loaders. */
53
+ format?: "dotenv" | "json";
54
+ }
55
+ /**
56
+ * Implementation of `neon-env export`. Resolves the branch's Neon env the same way `run`
57
+ * does (neon.ts policy + linked branch), then writes it to stdout — as dotenv lines or JSON —
58
+ * instead of spawning a process, so other env tools can consume it. For example, varlock can
59
+ * bulk-load it with `@setValuesBulk(exec("neon-env export --format json"), format=json)`.
60
+ */
61
+ declare function runEnvExport(options: EnvExportCommandOptions, ctx: CommandEnv): Promise<CommandResult>;
44
62
  //#endregion
45
- export { CommandEnv, CommandResult, EnvRunCommandOptions, runEnvRun };
63
+ export { CommandEnv, CommandResult, EnvExportCommandOptions, EnvResolveOptions, EnvRunCommandOptions, runEnvExport, runEnvRun };
46
64
  //# sourceMappingURL=commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","names":[],"sources":["../../../src/lib/cli/commands.ts"],"mappings":";;;;;;;;AAsBA;AASA;AAWiB,UApBA,UAAA,CAoBoB;EAef,GAAA,EAAA,MAAA;EAAS;;;;KAG5B,CAAA,EAhCI,OAgCJ;AAAO;UA7BO,aAAA;;;;;;;;;;UAWA,oBAAA;;;;;;;;;;;;;;iBAeK,SAAA,UACZ,2BACJ,aACH,QAAQ"}
1
+ {"version":3,"file":"commands.d.ts","names":[],"sources":["../../../src/lib/cli/commands.ts"],"mappings":";;;;;;;;AAsBA;AASA;AAgBiB,UAzBA,UAAA,CAyBiB;EAOjB,GAAA,EAAA,MAAA;EAWK;;;;KAGX,CAAA,EAxCJ,OAwCI;;AAAD,UArCO,aAAA,CAqCP;EA4CO;EAWK,QAAA,EAAA,MAAY;EAAA;QACxB,EAAA,MAAA;;QAEC,EAAA,MAAA;;EAAD,SAAA,CAAA,EAAA,MAAA;;;;;;;UA/EO,iBAAA;;;;;;UAOA,oBAAA,SAA6B;;;;;;;;;;iBAWxB,SAAA,UACZ,2BACJ,aACH,QAAQ;UA4CM,uBAAA,SAAgC;;;;;;;;;;iBAW3B,YAAA,UACZ,8BACJ,aACH,QAAQ"}
@@ -45,6 +45,44 @@ async function runEnvRun(options, ctx) {
45
45
  };
46
46
  }
47
47
  /**
48
+ * Implementation of `neon-env export`. Resolves the branch's Neon env the same way `run`
49
+ * does (neon.ts policy + linked branch), then writes it to stdout — as dotenv lines or JSON —
50
+ * instead of spawning a process, so other env tools can consume it. For example, varlock can
51
+ * bulk-load it with `@setValuesBulk(exec("neon-env export --format json"), format=json)`.
52
+ */
53
+ async function runEnvExport(options, ctx) {
54
+ const resolved = resolveContext({
55
+ cwd: ctx.cwd,
56
+ ...options.projectId ? { projectId: options.projectId } : {},
57
+ ...options.branch ? { branch: options.branch } : {}
58
+ });
59
+ if (!resolved.ok) return failure(["`env export` could not resolve the Neon project and branch:", ...resolved.missing.map((m) => ` - ${m}`)].join("\n"), 3);
60
+ let entries;
61
+ try {
62
+ entries = toEntries(await loadConfigAndFetchEnv(options, ctx, resolved.context));
63
+ } catch (err) {
64
+ return handleError(err);
65
+ }
66
+ return {
67
+ exitCode: 0,
68
+ stdout: options.format === "json" ? `${JSON.stringify(entries, null, 2)}\n` : toDotenv(entries),
69
+ stderr: ""
70
+ };
71
+ }
72
+ /** Render an env map as dotenv `KEY=value` lines, quoting values that need it. */
73
+ function toDotenv(entries) {
74
+ const lines = Object.entries(entries).map(([key, value]) => formatDotenvLine(key, value));
75
+ return lines.length > 0 ? `${lines.join("\n")}\n` : "";
76
+ }
77
+ /**
78
+ * Render a single `KEY=value` dotenv line, double-quoting (and escaping) values that contain
79
+ * whitespace, `#`, quotes, or `=` so connection strings round-trip through dotenv parsers.
80
+ */
81
+ function formatDotenvLine(key, value) {
82
+ if (!/[\s#"'=]/.test(value)) return `${key}=${value}`;
83
+ return `${key}="${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
84
+ }
85
+ /**
48
86
  * Load `neon.ts`, then call `fetchEnv` with the explicitly-resolved project + branch.
49
87
  * Layers any one-time Auth keys from `.env.local` (next to the config file) into the env
50
88
  * source so re-runs keep round-tripping values the Neon API only returns once at
@@ -176,6 +214,6 @@ function failure(message, exitCode = 1) {
176
214
  };
177
215
  }
178
216
  //#endregion
179
- export { runEnvRun };
217
+ export { runEnvExport, runEnvRun };
180
218
 
181
219
  //# sourceMappingURL=commands.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.js","names":[],"sources":["../../../src/lib/cli/commands.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n\tConfigLoadError,\n\tErrorCode,\n\tloadConfigFromFile,\n\tMissingContextError,\n\ttype NeonApi,\n\tPlatformError,\n} from \"@neondatabase/config/v1\";\nimport { fetchEnv, toEntries } from \"../env.js\";\nimport { resolveContext } from \"./resolve-context.js\";\n\n/** File `env run` reads to layer one-time auth keys. Matches the Vercel/Next.js convention. */\nconst DEFAULT_ENV_FILE = \".env.local\";\n\n/**\n * Cross-cutting environment a CLI command is allowed to touch. Injected so tests can drive\n * the handler with a custom NeonApi and a controlled `cwd` without spawning child\n * processes.\n */\nexport interface CommandEnv {\n\tcwd: string;\n\t/**\n\t * When set, used directly as the NeonApi. When omitted, the real adapter is built from\n\t * `options.apiKey ?? NEON_API_KEY` inside `fetchEnv`.\n\t */\n\tapi?: NeonApi;\n}\n\nexport interface CommandResult {\n\t/** Process exit code. `0` for success, non-zero for failure. */\n\texitCode: number;\n\t/** Text intended for stdout. */\n\tstdout: string;\n\t/** Text intended for stderr (human-readable status / error messages). */\n\tstderr: string;\n\t/** Optional structured debug payload — printed only when `--debug` is passed. */\n\tdebugInfo?: string;\n}\n\nexport interface EnvRunCommandOptions {\n\t/** The user command to spawn (after `--`). The first element is the executable. */\n\tcommand: string[];\n\tconfigPath?: string;\n\tprojectId?: string;\n\tbranch?: string;\n\tapiKey?: string;\n}\n\n/**\n * Implementation of `neon-env run -- <cmd...>`. Loads `neon.ts`, fetches the env from\n * Neon, then spawns the user-supplied command with the env vars injected on top of the\n * inherited `process.env`. Stdio is inherited so interactive dev servers keep working.\n * The parent process exits with the child's exit code.\n */\nexport async function runEnvRun(\n\toptions: EnvRunCommandOptions,\n\tctx: CommandEnv,\n): Promise<CommandResult> {\n\tif (options.command.length === 0) {\n\t\treturn failure(\n\t\t\t[\n\t\t\t\t\"`env run` requires a command to spawn.\",\n\t\t\t\t\"Usage: neon-env run -- <command> [args...]\",\n\t\t\t\t\"Example: neon-env run -- npm run dev\",\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t}\n\n\t// The CLI owns project/branch resolution (flags → NEON_* env → .neon file) so the\n\t// library functions stay filesystem/env-agnostic.\n\tconst resolved = resolveContext({\n\t\tcwd: ctx.cwd,\n\t\t...(options.projectId ? { projectId: options.projectId } : {}),\n\t\t...(options.branch ? { branch: options.branch } : {}),\n\t});\n\tif (!resolved.ok) {\n\t\treturn failure(\n\t\t\t[\n\t\t\t\t\"`env run` could not resolve the Neon project and branch:\",\n\t\t\t\t...resolved.missing.map((m) => ` - ${m}`),\n\t\t\t].join(\"\\n\"),\n\t\t\t3,\n\t\t);\n\t}\n\n\tlet injected: Record<string, string>;\n\ttry {\n\t\tconst env = await loadConfigAndFetchEnv(options, ctx, resolved.context);\n\t\tinjected = toEntries(env);\n\t} catch (err) {\n\t\treturn handleError(err);\n\t}\n\n\tconst [executable, ...args] = options.command;\n\tconst exitCode = await spawnAndWait(executable, args, {\n\t\tcwd: ctx.cwd,\n\t\tenv: { ...process.env, ...injected },\n\t});\n\treturn { exitCode, stdout: \"\", stderr: \"\" };\n}\n\n/**\n * Load `neon.ts`, then call `fetchEnv` with the explicitly-resolved project + branch.\n * Layers any one-time Auth keys from `.env.local` (next to the config file) into the env\n * source so re-runs keep round-tripping values the Neon API only returns once at\n * integration-creation time.\n */\nasync function loadConfigAndFetchEnv(\n\toptions: EnvRunCommandOptions,\n\tctx: CommandEnv,\n\tresolved: { projectId: string; branchId: string },\n): Promise<Awaited<ReturnType<typeof fetchEnv>>> {\n\tconst { config, resolvedPath } = await loadConfigFromFile({\n\t\t...(options.configPath ? { path: options.configPath } : {}),\n\t\tcwd: ctx.cwd,\n\t});\n\tconst envFileSource = join(dirname(resolvedPath), DEFAULT_ENV_FILE);\n\tconst fileEnv = existsSync(envFileSource)\n\t\t? parseEnvFile(readFileSync(envFileSource, \"utf-8\"))\n\t\t: {};\n\treturn fetchEnv(config, {\n\t\tprojectId: resolved.projectId,\n\t\tbranchId: resolved.branchId,\n\t\tenv: { ...process.env, ...fileEnv },\n\t\t...(ctx.api ? { api: ctx.api } : {}),\n\t\t...(options.apiKey ? { apiKey: options.apiKey } : {}),\n\t});\n}\n\n/**\n * Spawn a child process with stdio inherited so dev servers stay interactive. Resolves\n * with the child's exit code (treating signal terminations as code 1 so the CLI surfaces\n * a non-zero exit consistently).\n */\nfunction spawnAndWait(\n\tcommand: string,\n\targs: string[],\n\toptions: { cwd: string; env: Record<string, string | undefined> },\n): Promise<number> {\n\treturn new Promise((resolve) => {\n\t\tconst child = spawn(command, args, {\n\t\t\tcwd: options.cwd,\n\t\t\tenv: options.env,\n\t\t\tstdio: \"inherit\",\n\t\t});\n\t\tchild.on(\"error\", (err) => {\n\t\t\tprocess.stderr.write(\n\t\t\t\t`neon-env run: failed to spawn '${command}': ${err.message}\\n`,\n\t\t\t);\n\t\t\tresolve(1);\n\t\t});\n\t\tchild.on(\"exit\", (code, signal) => {\n\t\t\tif (typeof code === \"number\") {\n\t\t\t\tresolve(code);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (signal) {\n\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t`neon-env run: child terminated by signal ${signal}\\n`,\n\t\t\t\t);\n\t\t\t\tresolve(1);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tresolve(1);\n\t\t});\n\t});\n}\n\nfunction parseEnvFile(body: string): NodeJS.ProcessEnv {\n\tconst out: NodeJS.ProcessEnv = {};\n\tfor (const line of body.split(\"\\n\")) {\n\t\tconst parsed = parseEnvLine(line);\n\t\tif (parsed) out[parsed.key] = parsed.value;\n\t}\n\treturn out;\n}\n\nfunction parseEnvLine(line: string): { key: string; value: string } | null {\n\tconst match = line.match(\n\t\t/^\\s*(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.*)$/,\n\t);\n\tconst key = match?.[1];\n\tconst rawValue = match?.[2];\n\tif (key === undefined || rawValue === undefined) return null;\n\treturn { key, value: unescapeEnvValue(rawValue.trim()) };\n}\n\nfunction unescapeEnvValue(value: string): string {\n\tif (value.length >= 2 && value.startsWith('\"') && value.endsWith('\"')) {\n\t\treturn value.slice(1, -1).replace(/\\\\\"/g, '\"').replace(/\\\\\\\\/g, \"\\\\\");\n\t}\n\tif (value.length >= 2 && value.startsWith(\"'\") && value.endsWith(\"'\")) {\n\t\treturn value.slice(1, -1);\n\t}\n\treturn value;\n}\n\n/**\n * Stable exit code per `PlatformError` code. Mirrors the table in the config package so\n * shell pipelines can branch on the specific failure mode without parsing free text.\n */\nconst EXIT_CODE_BY_PLATFORM_ERROR_CODE: Readonly<Record<string, number>> = {\n\t[ErrorCode.MissingApiKey]: 1,\n\t[ErrorCode.Unauthorized]: 6,\n\t[ErrorCode.Forbidden]: 7,\n\t[ErrorCode.NotFound]: 8,\n\t[ErrorCode.RateLimited]: 9,\n\t[ErrorCode.NetworkError]: 10,\n\t[ErrorCode.ServerError]: 11,\n\t[ErrorCode.Locked]: 11,\n\t[ErrorCode.InternalError]: 99,\n};\n\nfunction handleError(err: unknown): CommandResult {\n\tif (err instanceof MissingContextError)\n\t\treturn errorResult(err, `Missing context: ${err.message}`, 3);\n\tif (err instanceof ConfigLoadError)\n\t\treturn errorResult(err, `Failed to load config: ${err.message}`, 4);\n\tif (err instanceof PlatformError) {\n\t\tconst exitCode = EXIT_CODE_BY_PLATFORM_ERROR_CODE[err.code];\n\t\tif (exitCode !== undefined)\n\t\t\treturn errorResult(err, err.message, exitCode);\n\t\treturn errorResult(err, `[${err.code}] ${err.message}`, 5);\n\t}\n\tif (err instanceof Error) return errorResult(err, err.message, 1);\n\treturn failure(String(err), 1);\n}\n\nfunction errorResult(\n\terr: unknown,\n\tmessage: string,\n\texitCode: number,\n): CommandResult {\n\tconst result: CommandResult = {\n\t\texitCode,\n\t\tstdout: \"\",\n\t\tstderr: `${message}\\n`,\n\t};\n\tconst debug = buildDebugInfo(err);\n\tif (debug) result.debugInfo = debug;\n\treturn result;\n}\n\nfunction buildDebugInfo(err: unknown): string | undefined {\n\tif (!(err instanceof Error)) return undefined;\n\tconst lines: string[] = [];\n\tif (err instanceof PlatformError) {\n\t\tlines.push(`code : ${err.code}`);\n\t\tif (Object.keys(err.details).length > 0) {\n\t\t\tlines.push(`details : ${JSON.stringify(err.details, null, 2)}`);\n\t\t}\n\t}\n\tif (err.cause instanceof Error) {\n\t\tlines.push(`cause : ${err.cause.name}: ${err.cause.message}`);\n\t}\n\tif (err.stack) {\n\t\tlines.push(err.stack);\n\t}\n\treturn lines.length > 0 ? lines.join(\"\\n\") : undefined;\n}\n\nfunction failure(message: string, exitCode = 1): CommandResult {\n\treturn { exitCode, stdout: \"\", stderr: `${message}\\n` };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"commands.js","names":[],"sources":["../../../src/lib/cli/commands.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n\tConfigLoadError,\n\tErrorCode,\n\tloadConfigFromFile,\n\tMissingContextError,\n\ttype NeonApi,\n\tPlatformError,\n} from \"@neondatabase/config/v1\";\nimport { fetchEnv, toEntries } from \"../env.js\";\nimport { resolveContext } from \"./resolve-context.js\";\n\n/** File `env run` reads to layer one-time auth keys. Matches the Vercel/Next.js convention. */\nconst DEFAULT_ENV_FILE = \".env.local\";\n\n/**\n * Cross-cutting environment a CLI command is allowed to touch. Injected so tests can drive\n * the handler with a custom NeonApi and a controlled `cwd` without spawning child\n * processes.\n */\nexport interface CommandEnv {\n\tcwd: string;\n\t/**\n\t * When set, used directly as the NeonApi. When omitted, the real adapter is built from\n\t * `options.apiKey ?? NEON_API_KEY` inside `fetchEnv`.\n\t */\n\tapi?: NeonApi;\n}\n\nexport interface CommandResult {\n\t/** Process exit code. `0` for success, non-zero for failure. */\n\texitCode: number;\n\t/** Text intended for stdout. */\n\tstdout: string;\n\t/** Text intended for stderr (human-readable status / error messages). */\n\tstderr: string;\n\t/** Optional structured debug payload — printed only when `--debug` is passed. */\n\tdebugInfo?: string;\n}\n\n/**\n * Inputs needed to resolve a branch and fetch its env, shared by `run` and `export`: an\n * optional explicit `neon.ts` path, project/branch overrides, and an API key (otherwise\n * resolved from `.neon` / `NEON_*` env by the CLI and `NEON_API_KEY` by `fetchEnv`).\n */\nexport interface EnvResolveOptions {\n\tconfigPath?: string;\n\tprojectId?: string;\n\tbranch?: string;\n\tapiKey?: string;\n}\n\nexport interface EnvRunCommandOptions extends EnvResolveOptions {\n\t/** The user command to spawn (after `--`). The first element is the executable. */\n\tcommand: string[];\n}\n\n/**\n * Implementation of `neon-env run -- <cmd...>`. Loads `neon.ts`, fetches the env from\n * Neon, then spawns the user-supplied command with the env vars injected on top of the\n * inherited `process.env`. Stdio is inherited so interactive dev servers keep working.\n * The parent process exits with the child's exit code.\n */\nexport async function runEnvRun(\n\toptions: EnvRunCommandOptions,\n\tctx: CommandEnv,\n): Promise<CommandResult> {\n\tif (options.command.length === 0) {\n\t\treturn failure(\n\t\t\t[\n\t\t\t\t\"`env run` requires a command to spawn.\",\n\t\t\t\t\"Usage: neon-env run -- <command> [args...]\",\n\t\t\t\t\"Example: neon-env run -- npm run dev\",\n\t\t\t].join(\"\\n\"),\n\t\t);\n\t}\n\n\t// The CLI owns project/branch resolution (flags → NEON_* env → .neon file) so the\n\t// library functions stay filesystem/env-agnostic.\n\tconst resolved = resolveContext({\n\t\tcwd: ctx.cwd,\n\t\t...(options.projectId ? { projectId: options.projectId } : {}),\n\t\t...(options.branch ? { branch: options.branch } : {}),\n\t});\n\tif (!resolved.ok) {\n\t\treturn failure(\n\t\t\t[\n\t\t\t\t\"`env run` could not resolve the Neon project and branch:\",\n\t\t\t\t...resolved.missing.map((m) => ` - ${m}`),\n\t\t\t].join(\"\\n\"),\n\t\t\t3,\n\t\t);\n\t}\n\n\tlet injected: Record<string, string>;\n\ttry {\n\t\tconst env = await loadConfigAndFetchEnv(options, ctx, resolved.context);\n\t\tinjected = toEntries(env);\n\t} catch (err) {\n\t\treturn handleError(err);\n\t}\n\n\tconst [executable, ...args] = options.command;\n\tconst exitCode = await spawnAndWait(executable, args, {\n\t\tcwd: ctx.cwd,\n\t\tenv: { ...process.env, ...injected },\n\t});\n\treturn { exitCode, stdout: \"\", stderr: \"\" };\n}\n\nexport interface EnvExportCommandOptions extends EnvResolveOptions {\n\t/** Output format. `dotenv` (KEY=value lines) by default; `json` for tooling / bulk loaders. */\n\tformat?: \"dotenv\" | \"json\";\n}\n\n/**\n * Implementation of `neon-env export`. Resolves the branch's Neon env the same way `run`\n * does (neon.ts policy + linked branch), then writes it to stdout — as dotenv lines or JSON —\n * instead of spawning a process, so other env tools can consume it. For example, varlock can\n * bulk-load it with `@setValuesBulk(exec(\"neon-env export --format json\"), format=json)`.\n */\nexport async function runEnvExport(\n\toptions: EnvExportCommandOptions,\n\tctx: CommandEnv,\n): Promise<CommandResult> {\n\tconst resolved = resolveContext({\n\t\tcwd: ctx.cwd,\n\t\t...(options.projectId ? { projectId: options.projectId } : {}),\n\t\t...(options.branch ? { branch: options.branch } : {}),\n\t});\n\tif (!resolved.ok) {\n\t\treturn failure(\n\t\t\t[\n\t\t\t\t\"`env export` could not resolve the Neon project and branch:\",\n\t\t\t\t...resolved.missing.map((m) => ` - ${m}`),\n\t\t\t].join(\"\\n\"),\n\t\t\t3,\n\t\t);\n\t}\n\n\tlet entries: Record<string, string>;\n\ttry {\n\t\tconst env = await loadConfigAndFetchEnv(options, ctx, resolved.context);\n\t\tentries = toEntries(env);\n\t} catch (err) {\n\t\treturn handleError(err);\n\t}\n\n\tconst stdout =\n\t\toptions.format === \"json\"\n\t\t\t? `${JSON.stringify(entries, null, 2)}\\n`\n\t\t\t: toDotenv(entries);\n\treturn { exitCode: 0, stdout, stderr: \"\" };\n}\n\n/** Render an env map as dotenv `KEY=value` lines, quoting values that need it. */\nfunction toDotenv(entries: Record<string, string>): string {\n\tconst lines = Object.entries(entries).map(([key, value]) =>\n\t\tformatDotenvLine(key, value),\n\t);\n\treturn lines.length > 0 ? `${lines.join(\"\\n\")}\\n` : \"\";\n}\n\n/**\n * Render a single `KEY=value` dotenv line, double-quoting (and escaping) values that contain\n * whitespace, `#`, quotes, or `=` so connection strings round-trip through dotenv parsers.\n */\nfunction formatDotenvLine(key: string, value: string): string {\n\tif (!/[\\s#\"'=]/.test(value)) return `${key}=${value}`;\n\tconst escaped = value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n\treturn `${key}=\"${escaped}\"`;\n}\n\n/**\n * Load `neon.ts`, then call `fetchEnv` with the explicitly-resolved project + branch.\n * Layers any one-time Auth keys from `.env.local` (next to the config file) into the env\n * source so re-runs keep round-tripping values the Neon API only returns once at\n * integration-creation time.\n */\nasync function loadConfigAndFetchEnv(\n\toptions: EnvResolveOptions,\n\tctx: CommandEnv,\n\tresolved: { projectId: string; branchId: string },\n): Promise<Awaited<ReturnType<typeof fetchEnv>>> {\n\tconst { config, resolvedPath } = await loadConfigFromFile({\n\t\t...(options.configPath ? { path: options.configPath } : {}),\n\t\tcwd: ctx.cwd,\n\t});\n\tconst envFileSource = join(dirname(resolvedPath), DEFAULT_ENV_FILE);\n\tconst fileEnv = existsSync(envFileSource)\n\t\t? parseEnvFile(readFileSync(envFileSource, \"utf-8\"))\n\t\t: {};\n\treturn fetchEnv(config, {\n\t\tprojectId: resolved.projectId,\n\t\tbranchId: resolved.branchId,\n\t\tenv: { ...process.env, ...fileEnv },\n\t\t...(ctx.api ? { api: ctx.api } : {}),\n\t\t...(options.apiKey ? { apiKey: options.apiKey } : {}),\n\t});\n}\n\n/**\n * Spawn a child process with stdio inherited so dev servers stay interactive. Resolves\n * with the child's exit code (treating signal terminations as code 1 so the CLI surfaces\n * a non-zero exit consistently).\n */\nfunction spawnAndWait(\n\tcommand: string,\n\targs: string[],\n\toptions: { cwd: string; env: Record<string, string | undefined> },\n): Promise<number> {\n\treturn new Promise((resolve) => {\n\t\tconst child = spawn(command, args, {\n\t\t\tcwd: options.cwd,\n\t\t\tenv: options.env,\n\t\t\tstdio: \"inherit\",\n\t\t});\n\t\tchild.on(\"error\", (err) => {\n\t\t\tprocess.stderr.write(\n\t\t\t\t`neon-env run: failed to spawn '${command}': ${err.message}\\n`,\n\t\t\t);\n\t\t\tresolve(1);\n\t\t});\n\t\tchild.on(\"exit\", (code, signal) => {\n\t\t\tif (typeof code === \"number\") {\n\t\t\t\tresolve(code);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (signal) {\n\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t`neon-env run: child terminated by signal ${signal}\\n`,\n\t\t\t\t);\n\t\t\t\tresolve(1);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tresolve(1);\n\t\t});\n\t});\n}\n\nfunction parseEnvFile(body: string): NodeJS.ProcessEnv {\n\tconst out: NodeJS.ProcessEnv = {};\n\tfor (const line of body.split(\"\\n\")) {\n\t\tconst parsed = parseEnvLine(line);\n\t\tif (parsed) out[parsed.key] = parsed.value;\n\t}\n\treturn out;\n}\n\nfunction parseEnvLine(line: string): { key: string; value: string } | null {\n\tconst match = line.match(\n\t\t/^\\s*(?:export\\s+)?([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.*)$/,\n\t);\n\tconst key = match?.[1];\n\tconst rawValue = match?.[2];\n\tif (key === undefined || rawValue === undefined) return null;\n\treturn { key, value: unescapeEnvValue(rawValue.trim()) };\n}\n\nfunction unescapeEnvValue(value: string): string {\n\tif (value.length >= 2 && value.startsWith('\"') && value.endsWith('\"')) {\n\t\treturn value.slice(1, -1).replace(/\\\\\"/g, '\"').replace(/\\\\\\\\/g, \"\\\\\");\n\t}\n\tif (value.length >= 2 && value.startsWith(\"'\") && value.endsWith(\"'\")) {\n\t\treturn value.slice(1, -1);\n\t}\n\treturn value;\n}\n\n/**\n * Stable exit code per `PlatformError` code. Mirrors the table in the config package so\n * shell pipelines can branch on the specific failure mode without parsing free text.\n */\nconst EXIT_CODE_BY_PLATFORM_ERROR_CODE: Readonly<Record<string, number>> = {\n\t[ErrorCode.MissingApiKey]: 1,\n\t[ErrorCode.Unauthorized]: 6,\n\t[ErrorCode.Forbidden]: 7,\n\t[ErrorCode.NotFound]: 8,\n\t[ErrorCode.RateLimited]: 9,\n\t[ErrorCode.NetworkError]: 10,\n\t[ErrorCode.ServerError]: 11,\n\t[ErrorCode.Locked]: 11,\n\t[ErrorCode.InternalError]: 99,\n};\n\nfunction handleError(err: unknown): CommandResult {\n\tif (err instanceof MissingContextError)\n\t\treturn errorResult(err, `Missing context: ${err.message}`, 3);\n\tif (err instanceof ConfigLoadError)\n\t\treturn errorResult(err, `Failed to load config: ${err.message}`, 4);\n\tif (err instanceof PlatformError) {\n\t\tconst exitCode = EXIT_CODE_BY_PLATFORM_ERROR_CODE[err.code];\n\t\tif (exitCode !== undefined)\n\t\t\treturn errorResult(err, err.message, exitCode);\n\t\treturn errorResult(err, `[${err.code}] ${err.message}`, 5);\n\t}\n\tif (err instanceof Error) return errorResult(err, err.message, 1);\n\treturn failure(String(err), 1);\n}\n\nfunction errorResult(\n\terr: unknown,\n\tmessage: string,\n\texitCode: number,\n): CommandResult {\n\tconst result: CommandResult = {\n\t\texitCode,\n\t\tstdout: \"\",\n\t\tstderr: `${message}\\n`,\n\t};\n\tconst debug = buildDebugInfo(err);\n\tif (debug) result.debugInfo = debug;\n\treturn result;\n}\n\nfunction buildDebugInfo(err: unknown): string | undefined {\n\tif (!(err instanceof Error)) return undefined;\n\tconst lines: string[] = [];\n\tif (err instanceof PlatformError) {\n\t\tlines.push(`code : ${err.code}`);\n\t\tif (Object.keys(err.details).length > 0) {\n\t\t\tlines.push(`details : ${JSON.stringify(err.details, null, 2)}`);\n\t\t}\n\t}\n\tif (err.cause instanceof Error) {\n\t\tlines.push(`cause : ${err.cause.name}: ${err.cause.message}`);\n\t}\n\tif (err.stack) {\n\t\tlines.push(err.stack);\n\t}\n\treturn lines.length > 0 ? lines.join(\"\\n\") : undefined;\n}\n\nfunction failure(message: string, exitCode = 1): CommandResult {\n\treturn { exitCode, stdout: \"\", stderr: `${message}\\n` };\n}\n"],"mappings":"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"}
@@ -7,8 +7,6 @@
7
7
  interface ResolvedContext {
8
8
  projectId: string;
9
9
  branchId: string;
10
- /** Branch name for `parseEnv`-style policy evaluation, when known. */
11
- branchName?: string;
12
10
  }
13
11
  interface ResolveContextOptions {
14
12
  projectId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-context.d.ts","names":[],"sources":["../../../src/lib/cli/resolve-context.ts"],"mappings":";;AASA;AAOA;AAcA;;AACU,UAtBO,eAAA,CAsBP;WACc,EAAA,MAAA;EAAe,QAAA,EAAA,MAAA;;;;UAhBtB,qBAAA;;;;QAIV,MAAA,CAAO;;;;;;;;;iBAUE,cAAA,UACN;;WACc"}
1
+ {"version":3,"file":"resolve-context.d.ts","names":[],"sources":["../../../src/lib/cli/resolve-context.ts"],"mappings":";;AASA;AAKA;AAcA;;AACU,UApBO,eAAA,CAoBP;WACc,EAAA,MAAA;EAAe,QAAA,EAAA,MAAA;;UAhBtB,qBAAA;;;;QAIV,MAAA,CAAO;;;;;;;;;iBAUE,cAAA,UACN;;WACc"}
@@ -14,7 +14,6 @@ function resolveContext(options) {
14
14
  const file = findNeonFile(options.cwd);
15
15
  const projectId = nonEmpty(options.projectId) ?? nonEmpty(env.NEON_PROJECT_ID) ?? file?.projectId;
16
16
  const branchId = nonEmpty(options.branch) ?? nonEmpty(env.NEON_BRANCH_ID) ?? file?.branchId;
17
- const branchName = nonEmpty(env.NEON_BRANCH_NAME) ?? file?.branchName;
18
17
  const missing = [];
19
18
  if (!projectId) missing.push("project id — pass `--project-id`, set `NEON_PROJECT_ID`, or add `projectId` to `.neon/project.json` (run `npx neonctl link`).");
20
19
  if (!branchId) missing.push("branch — pass `--branch`, set `NEON_BRANCH_ID`, or add `branchId` to `.neon/project.json` (run `npx neonctl checkout <branch>`).");
@@ -26,8 +25,7 @@ function resolveContext(options) {
26
25
  ok: true,
27
26
  context: {
28
27
  projectId,
29
- branchId,
30
- ...branchName ? { branchName } : {}
28
+ branchId
31
29
  }
32
30
  };
33
31
  }
@@ -69,7 +67,6 @@ function readNeonFileAt(path) {
69
67
  const out = {};
70
68
  if (typeof obj.projectId === "string" && obj.projectId !== "") out.projectId = obj.projectId;
71
69
  if (typeof obj.branchId === "string" && obj.branchId !== "") out.branchId = obj.branchId;
72
- if (typeof obj.branchName === "string" && obj.branchName !== "") out.branchName = obj.branchName;
73
70
  return out;
74
71
  }
75
72
  function isFile(path) {
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-context.js","names":[],"sources":["../../../src/lib/cli/resolve-context.ts"],"sourcesContent":["import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, resolve } from \"node:path\";\n\n/**\n * Resolved project + branch context for the `neon-env` CLI. The CLI owns this resolution\n * (flags → `NEON_*` env → `.neon[/project.json]` file) so the `@neondatabase/env` library\n * functions can stay filesystem- and env-agnostic.\n */\nexport interface ResolvedContext {\n\tprojectId: string;\n\tbranchId: string;\n\t/** Branch name for `parseEnv`-style policy evaluation, when known. */\n\tbranchName?: string;\n}\n\nexport interface ResolveContextOptions {\n\tprojectId?: string;\n\tbranch?: string;\n\tcwd: string;\n\tenv?: NodeJS.ProcessEnv;\n}\n\n/**\n * Resolve `projectId` and `branch` for a CLI invocation. Precedence (each wins over the\n * next): explicit flag → `NEON_*` env var → `.neon[/project.json]` walked up from `cwd`.\n *\n * Returns the resolved values plus a list of human-readable reasons for any field that\n * could not be resolved (so the caller can render one combined error).\n */\nexport function resolveContext(\n\toptions: ResolveContextOptions,\n): { ok: true; context: ResolvedContext } | { ok: false; missing: string[] } {\n\tconst env = options.env ?? process.env;\n\tconst file = findNeonFile(options.cwd);\n\n\tconst projectId =\n\t\tnonEmpty(options.projectId) ??\n\t\tnonEmpty(env.NEON_PROJECT_ID) ??\n\t\tfile?.projectId;\n\n\tconst branchId =\n\t\tnonEmpty(options.branch) ??\n\t\tnonEmpty(env.NEON_BRANCH_ID) ??\n\t\tfile?.branchId;\n\n\tconst branchName = nonEmpty(env.NEON_BRANCH_NAME) ?? file?.branchName;\n\n\tconst missing: string[] = [];\n\tif (!projectId) {\n\t\tmissing.push(\n\t\t\t\"project id — pass `--project-id`, set `NEON_PROJECT_ID`, or add `projectId` to `.neon/project.json` (run `npx neonctl link`).\",\n\t\t);\n\t}\n\tif (!branchId) {\n\t\tmissing.push(\n\t\t\t\"branch — pass `--branch`, set `NEON_BRANCH_ID`, or add `branchId` to `.neon/project.json` (run `npx neonctl checkout <branch>`).\",\n\t\t);\n\t}\n\tif (!projectId || !branchId) return { ok: false, missing };\n\n\treturn {\n\t\tok: true,\n\t\tcontext: {\n\t\t\tprojectId,\n\t\t\tbranchId,\n\t\t\t...(branchName ? { branchName } : {}),\n\t\t},\n\t};\n}\n\ninterface NeonFile {\n\tprojectId?: string;\n\tbranchId?: string;\n\tbranchName?: string;\n}\n\n/**\n * Walk up from `cwd` looking for `.neon/project.json` (preferred) or `.neon` (neonctl\n * convention). Stops at the first `.git` directory or the home directory. Read-only.\n */\nfunction findNeonFile(cwd: string): NeonFile | null {\n\tlet current = resolve(cwd);\n\tconst stop = resolve(homedir());\n\tlet lastSeen: string | null = null;\n\n\twhile (true) {\n\t\tconst parsed =\n\t\t\treadNeonFileAt(resolve(current, \".neon\", \"project.json\")) ??\n\t\t\treadNeonFileAt(resolve(current, \".neon\"));\n\t\tif (parsed) return parsed;\n\n\t\tif (current === stop) return null;\n\t\tif (existsSync(resolve(current, \".git\"))) return null;\n\n\t\tconst parent = dirname(current);\n\t\tif (parent === current || parent === lastSeen) return null;\n\t\tlastSeen = current;\n\t\tcurrent = parent;\n\t}\n}\n\nfunction readNeonFileAt(path: string): NeonFile | null {\n\tif (!isFile(path)) return null;\n\tlet raw: string;\n\ttry {\n\t\traw = readFileSync(path, \"utf-8\");\n\t} catch {\n\t\treturn null;\n\t}\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\treturn null;\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\treturn null;\n\tconst obj = parsed as Record<string, unknown>;\n\tconst out: NeonFile = {};\n\tif (typeof obj.projectId === \"string\" && obj.projectId !== \"\")\n\t\tout.projectId = obj.projectId;\n\tif (typeof obj.branchId === \"string\" && obj.branchId !== \"\")\n\t\tout.branchId = obj.branchId;\n\tif (typeof obj.branchName === \"string\" && obj.branchName !== \"\")\n\t\tout.branchName = obj.branchName;\n\treturn out;\n}\n\nfunction isFile(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction nonEmpty(value: string | undefined): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst trimmed = value.trim();\n\treturn trimmed === \"\" ? undefined : trimmed;\n}\n"],"mappings":";;;;;;;;;;;AA8BA,SAAgB,eACf,SAC4E;CAC5E,MAAM,MAAM,QAAQ,OAAO,QAAQ;CACnC,MAAM,OAAO,aAAa,QAAQ,GAAG;CAErC,MAAM,YACL,SAAS,QAAQ,SAAS,KAC1B,SAAS,IAAI,eAAe,KAC5B,MAAM;CAEP,MAAM,WACL,SAAS,QAAQ,MAAM,KACvB,SAAS,IAAI,cAAc,KAC3B,MAAM;CAEP,MAAM,aAAa,SAAS,IAAI,gBAAgB,KAAK,MAAM;CAE3D,MAAM,UAAoB,CAAC;CAC3B,IAAI,CAAC,WACJ,QAAQ,KACP,+HACD;CAED,IAAI,CAAC,UACJ,QAAQ,KACP,kIACD;CAED,IAAI,CAAC,aAAa,CAAC,UAAU,OAAO;EAAE,IAAI;EAAO;CAAQ;CAEzD,OAAO;EACN,IAAI;EACJ,SAAS;GACR;GACA;GACA,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;EACpC;CACD;AACD;;;;;AAYA,SAAS,aAAa,KAA8B;CACnD,IAAI,UAAU,QAAQ,GAAG;CACzB,MAAM,OAAO,QAAQ,QAAQ,CAAC;CAC9B,IAAI,WAA0B;CAE9B,OAAO,MAAM;EACZ,MAAM,SACL,eAAe,QAAQ,SAAS,SAAS,cAAc,CAAC,KACxD,eAAe,QAAQ,SAAS,OAAO,CAAC;EACzC,IAAI,QAAQ,OAAO;EAEnB,IAAI,YAAY,MAAM,OAAO;EAC7B,IAAI,WAAW,QAAQ,SAAS,MAAM,CAAC,GAAG,OAAO;EAEjD,MAAM,SAAS,QAAQ,OAAO;EAC9B,IAAI,WAAW,WAAW,WAAW,UAAU,OAAO;EACtD,WAAW;EACX,UAAU;CACX;AACD;AAEA,SAAS,eAAe,MAA+B;CACtD,IAAI,CAAC,OAAO,IAAI,GAAG,OAAO;CAC1B,IAAI;CACJ,IAAI;EACH,MAAM,aAAa,MAAM,OAAO;CACjC,QAAQ;EACP,OAAO;CACR;CACA,IAAI;CACJ,IAAI;EACH,SAAS,KAAK,MAAM,GAAG;CACxB,QAAQ;EACP,OAAO;CACR;CACA,IAAI,WAAW,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GACxE,OAAO;CACR,MAAM,MAAM;CACZ,MAAM,MAAgB,CAAC;CACvB,IAAI,OAAO,IAAI,cAAc,YAAY,IAAI,cAAc,IAC1D,IAAI,YAAY,IAAI;CACrB,IAAI,OAAO,IAAI,aAAa,YAAY,IAAI,aAAa,IACxD,IAAI,WAAW,IAAI;CACpB,IAAI,OAAO,IAAI,eAAe,YAAY,IAAI,eAAe,IAC5D,IAAI,aAAa,IAAI;CACtB,OAAO;AACR;AAEA,SAAS,OAAO,MAAuB;CACtC,IAAI;EACH,OAAO,SAAS,IAAI,EAAE,OAAO;CAC9B,QAAQ;EACP,OAAO;CACR;AACD;AAEA,SAAS,SAAS,OAA+C;CAChE,IAAI,OAAO,UAAU,UAAU,OAAO,KAAA;CACtC,MAAM,UAAU,MAAM,KAAK;CAC3B,OAAO,YAAY,KAAK,KAAA,IAAY;AACrC"}
1
+ {"version":3,"file":"resolve-context.js","names":[],"sources":["../../../src/lib/cli/resolve-context.ts"],"sourcesContent":["import { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, resolve } from \"node:path\";\n\n/**\n * Resolved project + branch context for the `neon-env` CLI. The CLI owns this resolution\n * (flags → `NEON_*` env → `.neon[/project.json]` file) so the `@neondatabase/env` library\n * functions can stay filesystem- and env-agnostic.\n */\nexport interface ResolvedContext {\n\tprojectId: string;\n\tbranchId: string;\n}\n\nexport interface ResolveContextOptions {\n\tprojectId?: string;\n\tbranch?: string;\n\tcwd: string;\n\tenv?: NodeJS.ProcessEnv;\n}\n\n/**\n * Resolve `projectId` and `branch` for a CLI invocation. Precedence (each wins over the\n * next): explicit flag → `NEON_*` env var → `.neon[/project.json]` walked up from `cwd`.\n *\n * Returns the resolved values plus a list of human-readable reasons for any field that\n * could not be resolved (so the caller can render one combined error).\n */\nexport function resolveContext(\n\toptions: ResolveContextOptions,\n): { ok: true; context: ResolvedContext } | { ok: false; missing: string[] } {\n\tconst env = options.env ?? process.env;\n\tconst file = findNeonFile(options.cwd);\n\n\tconst projectId =\n\t\tnonEmpty(options.projectId) ??\n\t\tnonEmpty(env.NEON_PROJECT_ID) ??\n\t\tfile?.projectId;\n\n\tconst branchId =\n\t\tnonEmpty(options.branch) ??\n\t\tnonEmpty(env.NEON_BRANCH_ID) ??\n\t\tfile?.branchId;\n\n\tconst missing: string[] = [];\n\tif (!projectId) {\n\t\tmissing.push(\n\t\t\t\"project id — pass `--project-id`, set `NEON_PROJECT_ID`, or add `projectId` to `.neon/project.json` (run `npx neonctl link`).\",\n\t\t);\n\t}\n\tif (!branchId) {\n\t\tmissing.push(\n\t\t\t\"branch — pass `--branch`, set `NEON_BRANCH_ID`, or add `branchId` to `.neon/project.json` (run `npx neonctl checkout <branch>`).\",\n\t\t);\n\t}\n\tif (!projectId || !branchId) return { ok: false, missing };\n\n\treturn {\n\t\tok: true,\n\t\tcontext: { projectId, branchId },\n\t};\n}\n\ninterface NeonFile {\n\tprojectId?: string;\n\tbranchId?: string;\n}\n\n/**\n * Walk up from `cwd` looking for `.neon/project.json` (preferred) or `.neon` (neonctl\n * convention). Stops at the first `.git` directory or the home directory. Read-only.\n */\nfunction findNeonFile(cwd: string): NeonFile | null {\n\tlet current = resolve(cwd);\n\tconst stop = resolve(homedir());\n\tlet lastSeen: string | null = null;\n\n\twhile (true) {\n\t\tconst parsed =\n\t\t\treadNeonFileAt(resolve(current, \".neon\", \"project.json\")) ??\n\t\t\treadNeonFileAt(resolve(current, \".neon\"));\n\t\tif (parsed) return parsed;\n\n\t\tif (current === stop) return null;\n\t\tif (existsSync(resolve(current, \".git\"))) return null;\n\n\t\tconst parent = dirname(current);\n\t\tif (parent === current || parent === lastSeen) return null;\n\t\tlastSeen = current;\n\t\tcurrent = parent;\n\t}\n}\n\nfunction readNeonFileAt(path: string): NeonFile | null {\n\tif (!isFile(path)) return null;\n\tlet raw: string;\n\ttry {\n\t\traw = readFileSync(path, \"utf-8\");\n\t} catch {\n\t\treturn null;\n\t}\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(raw);\n\t} catch {\n\t\treturn null;\n\t}\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\treturn null;\n\tconst obj = parsed as Record<string, unknown>;\n\tconst out: NeonFile = {};\n\tif (typeof obj.projectId === \"string\" && obj.projectId !== \"\")\n\t\tout.projectId = obj.projectId;\n\tif (typeof obj.branchId === \"string\" && obj.branchId !== \"\")\n\t\tout.branchId = obj.branchId;\n\treturn out;\n}\n\nfunction isFile(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction nonEmpty(value: string | undefined): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst trimmed = value.trim();\n\treturn trimmed === \"\" ? undefined : trimmed;\n}\n"],"mappings":";;;;;;;;;;;AA4BA,SAAgB,eACf,SAC4E;CAC5E,MAAM,MAAM,QAAQ,OAAO,QAAQ;CACnC,MAAM,OAAO,aAAa,QAAQ,GAAG;CAErC,MAAM,YACL,SAAS,QAAQ,SAAS,KAC1B,SAAS,IAAI,eAAe,KAC5B,MAAM;CAEP,MAAM,WACL,SAAS,QAAQ,MAAM,KACvB,SAAS,IAAI,cAAc,KAC3B,MAAM;CAEP,MAAM,UAAoB,CAAC;CAC3B,IAAI,CAAC,WACJ,QAAQ,KACP,+HACD;CAED,IAAI,CAAC,UACJ,QAAQ,KACP,kIACD;CAED,IAAI,CAAC,aAAa,CAAC,UAAU,OAAO;EAAE,IAAI;EAAO;CAAQ;CAEzD,OAAO;EACN,IAAI;EACJ,SAAS;GAAE;GAAW;EAAS;CAChC;AACD;;;;;AAWA,SAAS,aAAa,KAA8B;CACnD,IAAI,UAAU,QAAQ,GAAG;CACzB,MAAM,OAAO,QAAQ,QAAQ,CAAC;CAC9B,IAAI,WAA0B;CAE9B,OAAO,MAAM;EACZ,MAAM,SACL,eAAe,QAAQ,SAAS,SAAS,cAAc,CAAC,KACxD,eAAe,QAAQ,SAAS,OAAO,CAAC;EACzC,IAAI,QAAQ,OAAO;EAEnB,IAAI,YAAY,MAAM,OAAO;EAC7B,IAAI,WAAW,QAAQ,SAAS,MAAM,CAAC,GAAG,OAAO;EAEjD,MAAM,SAAS,QAAQ,OAAO;EAC9B,IAAI,WAAW,WAAW,WAAW,UAAU,OAAO;EACtD,WAAW;EACX,UAAU;CACX;AACD;AAEA,SAAS,eAAe,MAA+B;CACtD,IAAI,CAAC,OAAO,IAAI,GAAG,OAAO;CAC1B,IAAI;CACJ,IAAI;EACH,MAAM,aAAa,MAAM,OAAO;CACjC,QAAQ;EACP,OAAO;CACR;CACA,IAAI;CACJ,IAAI;EACH,SAAS,KAAK,MAAM,GAAG;CACxB,QAAQ;EACP,OAAO;CACR;CACA,IAAI,WAAW,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GACxE,OAAO;CACR,MAAM,MAAM;CACZ,MAAM,MAAgB,CAAC;CACvB,IAAI,OAAO,IAAI,cAAc,YAAY,IAAI,cAAc,IAC1D,IAAI,YAAY,IAAI;CACrB,IAAI,OAAO,IAAI,aAAa,YAAY,IAAI,aAAa,IACxD,IAAI,WAAW,IAAI;CACpB,OAAO;AACR;AAEA,SAAS,OAAO,MAAuB;CACtC,IAAI;EACH,OAAO,SAAS,IAAI,EAAE,OAAO;CAC9B,QAAQ;EACP,OAAO;CACR;AACD;AAEA,SAAS,SAAS,OAA+C;CAChE,IAAI,OAAO,UAAU,UAAU,OAAO,KAAA;CACtC,MAAM,UAAU,MAAM,KAAK;CAC3B,OAAO,YAAY,KAAK,KAAA,IAAY;AACrC"}
package/dist/lib/env.d.ts CHANGED
@@ -1,19 +1,8 @@
1
- import { BranchConfig, Config } from "../config/dist/lib/types.js";
1
+ import { Config } from "../config/dist/lib/types.js";
2
2
  import { NeonApi } from "../config/dist/lib/neon-api.js";
3
3
  import "../config/dist/v1.js";
4
4
 
5
5
  //#region src/lib/env.d.ts
6
-
7
- /**
8
- * Mapping between the {@link NeonEnv} property paths and the OS-level env-var keys used
9
- * for cross-process transport (via `.env` files, `env run -- <cmd>`, or anything else
10
- * that talks to `process.env`).
11
- *
12
- * Each top-level key here is a {@link NeonEnv} namespace; the inner record maps the
13
- * camelCase property names exposed to TypeScript to the UPPER_SNAKE env-var names used
14
- * by the OS. Keep this in sync with {@link postgresEnvSchema} / {@link authEnvSchema} /
15
- * {@link dataApiEnvSchema}.
16
- */
17
6
  declare const NEON_ENV_VAR_KEYS: {
18
7
  readonly postgres: {
19
8
  readonly databaseUrl: "DATABASE_URL";
@@ -62,29 +51,58 @@ interface NeonDataApiEnv {
62
51
  * which biome rejects (it means "any non-null", not "empty object").
63
52
  */
64
53
  type NoNamespace = Record<never, never>;
65
- type BranchConfigOf<C extends Config> = ReturnType<C> extends BranchConfig ? ReturnType<C> : BranchConfig;
66
- type ServiceToggleOf<Cfg, Key extends "auth" | "dataApi"> = Cfg extends unknown ? Key extends keyof Cfg ? Cfg[Key] : never : never;
67
- type HasEnabledService<Cfg, Key extends "auth" | "dataApi"> = [Exclude<ServiceToggleOf<Cfg, Key>, undefined | {
54
+ /**
55
+ * Resolve a **static** service toggle (the value of `config.auth` / `config.dataApi`) to a
56
+ * type-level boolean. The whole-thing wrapping (`[T] extends […]`) turns off distribution
57
+ * so a union/`undefined` is checked as one unit:
58
+ *
59
+ * - `false` / `{ enabled: false }` / `undefined` → `false`
60
+ * - `true` / `{ enabled: true }` / any other object (`{}`, `{ enabled?: boolean }`) → `true`
61
+ * (a present toggle defaults to enabled)
62
+ * - the bare `boolean | ServiceToggle | undefined` (the default `Config` param, no literal
63
+ * info) → `false`, so an untyped policy yields just `{ postgres }`.
64
+ */
65
+ type ServiceOn<T> = [T] extends [false] ? false : [T] extends [{
68
66
  enabled: false;
69
- }>] extends [never] ? false : true;
70
- type IsDefaultConfig<C extends Config> = Config extends C ? true : false;
67
+ }] ? false : [T] extends [undefined] ? false : [T] extends [true] ? true : [T] extends [{
68
+ enabled: true;
69
+ }] ? true : [T] extends [object] ? true : false;
71
70
  /**
72
71
  * Static, namespaced shape of `fetchEnv` / `parseEnv`'s return value. Generic over the
73
72
  * {@link Config} so the type system knows which optional namespaces are present.
74
73
  *
74
+ * Because the secret-bearing toggles now live in the **static** top-level `config.auth` /
75
+ * `config.dataApi` (not inside a per-branch closure), the namespace presence is a direct
76
+ * read of those fields — no union-across-branches, no default-config escape hatch:
77
+ *
75
78
  * - `postgres` is always present.
76
- * - `auth` is added iff the config return type has an `auth` namespace that is not
77
- * explicitly disabled.
78
- * - `dataApi` is added iff the config return type has a `dataApi` namespace that is not
79
- * explicitly disabled.
79
+ * - `auth` is added iff `config.auth` is statically enabled.
80
+ * - `dataApi` is added iff `config.dataApi` is statically enabled.
80
81
  */
81
82
  type NeonEnv<C extends Config = Config> = {
82
83
  postgres: NeonPostgresEnv;
83
- } & (IsDefaultConfig<C> extends true ? NoNamespace : HasEnabledService<BranchConfigOf<C>, "auth"> extends true ? {
84
+ } & (ServiceOn<NonNullable<C["auth"]>> extends true ? {
84
85
  auth: NeonAuthEnv;
85
- } : NoNamespace) & (IsDefaultConfig<C> extends true ? NoNamespace : HasEnabledService<BranchConfigOf<C>, "dataApi"> extends true ? {
86
+ } : NoNamespace) & (ServiceOn<NonNullable<C["dataApi"]>> extends true ? {
86
87
  dataApi: NeonDataApiEnv;
87
88
  } : NoNamespace);
89
+ /** The static `preview.functions` record of a config, or an empty record when absent. */
90
+ type PreviewFunctionsOf<C extends Config> = NonNullable<C["preview"]> extends {
91
+ functions: infer F;
92
+ } ? F : Record<never, never>;
93
+ /** The declared function slugs of a config (record keys), as a string union. */
94
+ type FunctionSlugOf<C extends Config> = Extract<keyof PreviewFunctionsOf<C>, string>;
95
+ /** The declared env-var keys of one function `S`, as a string union. */
96
+ type FunctionEnvKeysOf<C extends Config, S extends string> = S extends keyof PreviewFunctionsOf<C> ? NonNullable<PreviewFunctionsOf<C>[S]> extends {
97
+ env: infer E;
98
+ } ? Extract<keyof E, string> : never : never;
99
+ /**
100
+ * The extra `function` namespace added to `parseEnv`'s result when called with a function
101
+ * slug scope: the declared env-var keys for that function, each resolved to a `string`.
102
+ */
103
+ type NeonFunctionEnv<C extends Config, S extends string> = {
104
+ function: Record<FunctionEnvKeysOf<C, S>, string>;
105
+ };
88
106
  interface FetchEnvOptions {
89
107
  /**
90
108
  * Neon project id. **Required** — the management API addresses branches through their
@@ -105,9 +123,11 @@ interface FetchEnvOptions {
105
123
  */
106
124
  api?: NeonApi;
107
125
  /**
108
- * Role name to fetch credentials for. When omitted, the only role on the branch is
109
- * auto-picked; throws {@link PlatformError} with `PLATFORM_AMBIGUOUS_BRANCH_AUTH` if
110
- * the branch has more than one role.
126
+ * Role name to fetch credentials for. When omitted, the connection role is auto-picked:
127
+ * the only role on the branch, else Neon's default owner (`neondb_owner`), else the
128
+ * single role left after dropping the managed Auth/Data API roles
129
+ * (`authenticator`/`anonymous`/`authenticated`). Throws {@link PlatformError} with
130
+ * `PLATFORM_AMBIGUOUS_BRANCH_AUTH` only when more than one app role remains.
111
131
  */
112
132
  roleName?: string;
113
133
  /**
@@ -147,36 +167,45 @@ interface FetchEnvOptions {
147
167
  */
148
168
  declare function fetchEnv<const C extends Config>(config: C, options: FetchEnvOptions): Promise<NeonEnv<C>>;
149
169
  /**
150
- * Synchronous, network-free counterpart to {@link fetchEnv}. Reads `process.env` (or
151
- * `options.env`), validates the required Neon env vars with zod, and returns the same
152
- * {@link NeonEnv} shape — so the rest of your app touches `env.postgres.databaseUrl`
153
- * instead of stringly-typed `process.env.DATABASE_URL` lookups.
170
+ * Synchronous, network-free counterpart to {@link fetchEnv}. Reads `process.env`, validates
171
+ * the required Neon env vars with zod, and returns the same {@link NeonEnv} shape — so the
172
+ * rest of your app touches `env.postgres.databaseUrl` instead of stringly-typed
173
+ * `process.env.DATABASE_URL` lookups.
154
174
  *
155
175
  * Designed for the **"env-vars-already-injected"** path:
156
- * - You wrapped your dev command with `neon-env run -- <cmd>`.
176
+ * - You wrapped your dev command with `neon-env run -- <cmd>` or `neon dev`.
157
177
  * - Your platform (Vercel, Fly, Railway, …) injected the vars via its own integration.
178
+ * - You are **inside a deployed Neon Function**, whose env was uploaded at `config apply`.
179
+ *
180
+ * Unlike the old API, `parseEnv` does **not** take a branch name: the secret set is now
181
+ * static (top-level `config.auth` / `config.dataApi`), so it reads those directly without
182
+ * evaluating the per-branch closure.
158
183
  *
159
- * Takes a branch **name** (not an id like the API-backed `fetchEnv` / config operations):
160
- * `parseEnv` makes no Neon API call, so the only thing it needs the branch for is
161
- * evaluating your `neon.ts` policy, which switches on `branch.name`. With no network round
162
- * trip there's no way to turn a `br-…` id into a name, so the name is passed directly.
163
- * Pass it explicitly so the result is deterministic and not coupled to any `NEON_*` env
164
- * var. (The `neon-env` CLI injects `NEON_BRANCH_NAME`; pass that through, or default to
165
- * your main branch name.) Prefer `fetchEnv` when runtime code needs the exact live branch.
184
+ * The second argument is a **scope**:
185
+ * - omitted *external* scope (app bootstrap, build scripts, your dev machine). Returns
186
+ * `{ postgres, auth?, dataApi? }`.
187
+ * - a **function slug** (a key of `config.preview.functions`) *function* scope: you are
188
+ * running inside that function. Returns the same branch secrets **plus** a typed
189
+ * `function` namespace with the function's declared env-var keys.
166
190
  *
167
191
  * Throws `PlatformError(EnvNotInjected)` listing every missing/invalid var when the env
168
- * isn't fully populated, with a fix hint pointing back at `neon-env run`.
192
+ * isn't fully populated, with a fix hint pointing back at `neon dev` / `neon-env run`.
169
193
  *
170
194
  * ```ts
171
195
  * import config from "../neon";
172
196
  * import { parseEnv } from "@neondatabase/env/v1";
173
197
  *
174
- * const env = parseEnv(config, process.env.NEON_BRANCH_NAME ?? "main");
198
+ * // External (app / build):
199
+ * const env = parseEnv(config);
175
200
  * const db = drizzle(neon(env.postgres.databaseUrl), { schema });
176
- * // env.auth is statically typed when the config return type has auth: {} or auth.enabled: true.
201
+ *
202
+ * // Inside the "hello" function:
203
+ * const env = parseEnv(config, "hello");
204
+ * env.function.resendApiKey; // typed from hello's declared env keys
177
205
  * ```
178
206
  */
179
- declare function parseEnv<const C extends Config>(config: C, branchName: string): NeonEnv<C>;
207
+ declare function parseEnv<const C extends Config>(config: C): NeonEnv<C>;
208
+ declare function parseEnv<const C extends Config, const S extends FunctionSlugOf<C>>(config: C, scope: S): NeonEnv<C> & NeonFunctionEnv<C, S>;
180
209
  /**
181
210
  * Project a fully-resolved {@link NeonEnv} into the OS-level `{ KEY: value }` pairs used
182
211
  * for cross-process transport. Named after the web-platform `.entries()` convention
@@ -190,5 +219,5 @@ declare function parseEnv<const C extends Config>(config: C, branchName: string)
190
219
  */
191
220
  declare function toEntries(env: NeonEnv<Config>): Record<string, string>;
192
221
  //#endregion
193
- export { FetchEnvOptions, NEON_ENV_VAR_KEYS, NeonAuthEnv, NeonDataApiEnv, NeonEnv, NeonPostgresEnv, fetchEnv, parseEnv, toEntries };
222
+ export { FetchEnvOptions, FunctionSlugOf, NEON_ENV_VAR_KEYS, NeonAuthEnv, NeonDataApiEnv, NeonEnv, NeonFunctionEnv, NeonPostgresEnv, fetchEnv, parseEnv, toEntries };
194
223
  //# sourceMappingURL=env.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","names":[],"sources":["../../src/lib/env.ts"],"mappings":";;;;;;;;;;AAwBA;AAcA;AAuBA;AAKA;AAEC;AAOwB;AAEN,cArDN,iBAqDM,EAAA;WAAW,QAAA,EAAA;IAAqB,SAAA,WAAA,EAAA,cAAA;IAAX,SAAA,mBAAA,EAAA,uBAAA;;WAC1B,IAAA,EAAA;IAAX,SAAA,OAAA,EAAA,oBAAA;;EACY,SAAA,OAAA,EAAA;IAEV,SAAA,GAAA,EAAe,mBAAA;EAAA,CAAA;;;AACC,UA5CJ,eAAA,CA4CI;;;AACV;AAAA;EAIW,WAAA,EAAA,MAAA;;;;;AACd;EAKH,mBAAe,EAAA,MAAA;;;;;AAAqC;AAYzD;;;;;AAEqB,UA9CJ,WAAA,CA8CI;SAAhB,EAAA,MAAA;;;AAEgB,UA3CJ,cAAA,CA2CI;KAAlB,EAAA,MAAA;;;;;;;KAlCE,WAAA,GAAc,MAuCG,CAAA,KAAA,EAAA,KAAA,CAAA;KArCjB,cAqCD,CAAA,UArC0B,MAqC1B,CAAA,GArCoC,UAqCpC,CArC+C,CAqC/C,CAAA,SArC0D,YAqC1D,GApCD,UAoCC,CApCU,CAoCV,CAAA,GAnCD,YAmCC;KAjCC,eAkCW,CAAA,GAAA,EAAA,YAAA,MAAA,GAAA,SAAA,CAAA,GAlC4C,GAkC5C,SAAA,OAAA,GAjCb,GAiCa,SAAA,MAjCK,GAiCL,GAhCZ,GAgCY,CAhCR,GAgCQ,CAAA,GAAA,KAAA,GAAA,KAAA;KA5BX,iBA6BA,CAAA,GAAA,EAAA,YAAA,MAAA,GAAA,SAAA,CAAA,GAAA,CA5BJ,OA4Be,CA5BP,eA4BO,CA5BS,GA4BT,EA5Bc,GA4Bd,CAAA,EAAA,SAAA,GAAA;EAEC,OAAA,EAAA,KAAe;AAAA,CAAA,CAAA,UAkBzB,CAAA,KAAA,CAAA,GAAA,KAAA,GAAA,IAAA;KA3CF,eA4DS,CAAA,UA5DiB,MA4DjB,CAAA,GA5D2B,MA4D3B,SA5D0C,CA4D1C,GAAA,IAAA,GAAA,KAAA;AAAU;AA0BxB;;;;;;;;AAGU;AAyUM,KAtZJ,OAsZY,CAAA,UAtZM,MAsZN,GAtZe,MAsZf,CAAA,GAAA;EAAA,QAAA,EArZb,eAqZa;KApZnB,eAoZoC,CApZpB,CAoZoB,CAAA,SAAA,IAAA,GAnZtC,WAmZsC,GAlZtC,iBAkZsC,CAlZpB,cAkZoB,CAlZL,CAkZK,CAAA,EAAA,MAAA,CAAA,SAAA,IAAA,GAAA;MAChC,EAlZG,WAkZH;IAjZL,WAmZO,CAAA,GAAA,CAlZT,eAkZS,CAlZO,CAkZP,CAAA,SAAA,IAAA,GAjZP,WAiZO,GAhZP,iBAgZO,CAhZW,cAgZX,CAhZ0B,CAgZ1B,CAAA,EAAA,SAAA,CAAA,SAAA,IAAA,GAAA;SAAR,EA/Ya,cA+Yb;AAAO,CAAA,GA9YL,WA8YK,CAAA;AAgFM,UA5dC,eAAA,CA4dQ;EAAA;;;;EAA8B,SAAA,EAAA,MAAA;;;;;;;;;;;;;QA1chD;;;;;;;;;;;;;;;;;QAiBA,MAAA,CAAO;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BQ,yBAAyB,gBACtC,YACC,kBACP,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyUH,yBAAyB,gBAChC,wBAEN,QAAQ;;;;;;;;;;;;iBAgFK,SAAA,MAAe,QAAQ,UAAU"}
1
+ {"version":3,"file":"env.d.ts","names":[],"sources":["../../src/lib/env.ts"],"mappings":"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"}