@neondatabase/env 0.12.1 → 0.13.0
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/dist/config/dist/lib/define-config.d.ts.map +1 -1
- package/dist/config/dist/lib/neon-api.d.ts +1 -1
- package/dist/config/dist/lib/neon-api.d.ts.map +1 -1
- package/dist/config/dist/lib/types.d.ts +44 -2
- package/dist/config/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/cli/commands.d.ts +5 -3
- package/dist/lib/cli/commands.d.ts.map +1 -1
- package/dist/lib/cli/commands.js +9 -1
- package/dist/lib/cli/commands.js.map +1 -1
- package/dist/lib/cli/resolve-api-key.d.ts +21 -0
- package/dist/lib/cli/resolve-api-key.d.ts.map +1 -0
- package/dist/lib/cli/resolve-api-key.js +52 -0
- package/dist/lib/cli/resolve-api-key.js.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-config.d.ts","names":["BranchTarget","BranchTuningFn","BucketDef","Config","DataApiInput","FunctionDef","PreviewInput","ResolvedBranchConfig","ServiceEnabled","ServiceToggleInput","DataApiUsesNeonAuth","DataApi","NeonAuthRequiredHint","DataApiField","Auth","PreviewAutocomplete","Preview","F","B","defineConfig","resolveConfig","normalizeRegion"],"sources":["../../../../../config/dist/lib/define-config.d.ts"],"sourcesContent":["import { BranchTarget, BranchTuningFn, BucketDef, Config, DataApiInput, FunctionDef, PreviewInput, ResolvedBranchConfig, ServiceEnabled, ServiceToggleInput } from \"./types.js\";\n\n//#region src/lib/define-config.d.ts\n\n/**\n * Whether a `dataApi` toggle is **enabled and verified by Neon Auth** at the type level: it is\n * on (see {@link ServiceEnabled}) and not the explicit `authProvider: \"external\"` variant\n * (so the default / `\"neon\"` provider). This is the case that requires top-level Neon Auth.\n */\ntype DataApiUsesNeonAuth<DataApi> = ServiceEnabled<DataApi> extends true ? [DataApi] extends [{\n authProvider: \"external\";\n}] ? false : true : false;\n/**\n * Human-readable hint surfaced as the **expected type** of `dataApi` when a Neon-Auth Data\n * API is declared without Neon Auth enabled (see {@link DataApiField}). TypeScript prints the\n * offending value against this string literal — `Type 'true' is not assignable to type\n * '…requires `auth: true`…'` — which points straight at the fix, instead of the opaque\n * `Type 'true' is not assignable to type 'never'` an intersection guard produces.\n *\n * It documents **both** fixes: enabling Neon Auth (`auth: true`), and running the Data API\n * *without* Neon Auth by verifying a third-party IdP (`authProvider: 'external'` + `jwksUrl`).\n */\ntype NeonAuthRequiredHint = \"`dataApi` with Neon Auth (the default `authProvider: 'neon'`) requires Neon Auth, so add `auth: true`. To enable the Data API WITHOUT Neon Auth, verify a third-party IdP instead: `dataApi: { authProvider: 'external', jwksUrl: 'https://your-idp/.well-known/jwks.json' }`\";\n/**\n * Static cross-field guard for {@link defineConfig}, expressed as the **type of the `dataApi`\n * field** rather than an intersected requirement on `auth`.\n *\n * - A Neon-Auth Data API (`authProvider: \"neon\"`, the default) with top-level `auth` enabled,\n * or any external Data API: the field keeps its normal `DataApi & DataApiInput` type (the\n * `& DataApiInput` preserves member autocomplete; the `const DataApi` still types the\n * returned {@link Config}).\n * - A Neon-Auth Data API **without** `auth` enabled: the field's expected type collapses to\n * the {@link NeonAuthRequiredHint} message, so the author sees the rule (and the two fixes)\n * right on the `dataApi` value.\n *\n * The runtime `superRefine` in {@link configInputSchema} enforces the same invariant for\n * non-typed (plain-JS) callers, so the behavior is identical — only the type-level message\n * changes.\n */\ntype DataApiField<Auth, DataApi> = DataApiUsesNeonAuth<DataApi> extends true ? ServiceEnabled<Auth> extends true ? DataApi & DataApiInput : NeonAuthRequiredHint : DataApi & DataApiInput;\n/**\n * Autocomplete bridge for the nested `preview.functions` / `preview.buckets` slug objects.\n *\n * {@link PreviewInput} types those records with a string index signature\n * (`Record<string, FunctionDef>` / `Record<string, BucketDef>`). When `defineConfig` infers\n * `const Preview`, every authored slug becomes a **named** property on the inferred literal\n * (e.g. `{ hello: { name; source } }`), and a named property **shadows** the index signature\n * when the editor computes the contextual type of that slug's value — so the rest of\n * {@link FunctionDef} / {@link BucketDef} (`env`, `dev`, `access`, …) never surfaces as\n * completions inside `hello: { … }` / `uploads: { … }`.\n *\n * Re-declaring each inferred slug's value as `FunctionDef` / `BucketDef` (a *named* member, via\n * a mapped type over the already-inferred keys) puts those members back onto the contextual\n * type without going through an index signature, which restores autocomplete. Intersected with\n * `Preview & PreviewInput` it neither widens what is accepted (the values were already\n * `FunctionDef` / `BucketDef`) nor perturbs the inferred `const Preview` — so slug inference for\n * `BranchTuningFn<Preview>` and the returned {@link Config} is unchanged.\n */\ntype PreviewAutocomplete<Preview> = (Preview extends {\n functions: infer F;\n} ? {\n functions: { [Slug in keyof F]: FunctionDef };\n} : unknown) & (Preview extends {\n buckets: infer B;\n} ? {\n buckets: { [Name in keyof B]: BucketDef };\n} : unknown);\n/**\n * Validate and freeze a Neon
|
|
1
|
+
{"version":3,"file":"define-config.d.ts","names":["BranchTarget","BranchTuningFn","BucketDef","Config","DataApiInput","FunctionDef","PreviewInput","ResolvedBranchConfig","ServiceEnabled","ServiceToggleInput","DataApiUsesNeonAuth","DataApi","NeonAuthRequiredHint","DataApiField","Auth","PreviewAutocomplete","Preview","F","B","defineConfig","resolveConfig","normalizeRegion"],"sources":["../../../../../config/dist/lib/define-config.d.ts"],"sourcesContent":["import { BranchTarget, BranchTuningFn, BucketDef, Config, DataApiInput, FunctionDef, PreviewInput, ResolvedBranchConfig, ServiceEnabled, ServiceToggleInput } from \"./types.js\";\n\n//#region src/lib/define-config.d.ts\n\n/**\n * Whether a `dataApi` toggle is **enabled and verified by Neon Auth** at the type level: it is\n * on (see {@link ServiceEnabled}) and not the explicit `authProvider: \"external\"` variant\n * (so the default / `\"neon\"` provider). This is the case that requires top-level Neon Auth.\n */\ntype DataApiUsesNeonAuth<DataApi> = ServiceEnabled<DataApi> extends true ? [DataApi] extends [{\n authProvider: \"external\";\n}] ? false : true : false;\n/**\n * Human-readable hint surfaced as the **expected type** of `dataApi` when a Neon-Auth Data\n * API is declared without Neon Auth enabled (see {@link DataApiField}). TypeScript prints the\n * offending value against this string literal — `Type 'true' is not assignable to type\n * '…requires `auth: true`…'` — which points straight at the fix, instead of the opaque\n * `Type 'true' is not assignable to type 'never'` an intersection guard produces.\n *\n * It documents **both** fixes: enabling Neon Auth (`auth: true`), and running the Data API\n * *without* Neon Auth by verifying a third-party IdP (`authProvider: 'external'` + `jwksUrl`).\n */\ntype NeonAuthRequiredHint = \"`dataApi` with Neon Auth (the default `authProvider: 'neon'`) requires Neon Auth, so add `auth: true`. To enable the Data API WITHOUT Neon Auth, verify a third-party IdP instead: `dataApi: { authProvider: 'external', jwksUrl: 'https://your-idp/.well-known/jwks.json' }`\";\n/**\n * Static cross-field guard for {@link defineConfig}, expressed as the **type of the `dataApi`\n * field** rather than an intersected requirement on `auth`.\n *\n * - A Neon-Auth Data API (`authProvider: \"neon\"`, the default) with top-level `auth` enabled,\n * or any external Data API: the field keeps its normal `DataApi & DataApiInput` type (the\n * `& DataApiInput` preserves member autocomplete; the `const DataApi` still types the\n * returned {@link Config}).\n * - A Neon-Auth Data API **without** `auth` enabled: the field's expected type collapses to\n * the {@link NeonAuthRequiredHint} message, so the author sees the rule (and the two fixes)\n * right on the `dataApi` value.\n *\n * The runtime `superRefine` in {@link configInputSchema} enforces the same invariant for\n * non-typed (plain-JS) callers, so the behavior is identical — only the type-level message\n * changes.\n */\ntype DataApiField<Auth, DataApi> = DataApiUsesNeonAuth<DataApi> extends true ? ServiceEnabled<Auth> extends true ? DataApi & DataApiInput : NeonAuthRequiredHint : DataApi & DataApiInput;\n/**\n * Autocomplete bridge for the nested `preview.functions` / `preview.buckets` slug objects.\n *\n * {@link PreviewInput} types those records with a string index signature\n * (`Record<string, FunctionDef>` / `Record<string, BucketDef>`). When `defineConfig` infers\n * `const Preview`, every authored slug becomes a **named** property on the inferred literal\n * (e.g. `{ hello: { name; source } }`), and a named property **shadows** the index signature\n * when the editor computes the contextual type of that slug's value — so the rest of\n * {@link FunctionDef} / {@link BucketDef} (`env`, `dev`, `access`, …) never surfaces as\n * completions inside `hello: { … }` / `uploads: { … }`.\n *\n * Re-declaring each inferred slug's value as `FunctionDef` / `BucketDef` (a *named* member, via\n * a mapped type over the already-inferred keys) puts those members back onto the contextual\n * type without going through an index signature, which restores autocomplete. Intersected with\n * `Preview & PreviewInput` it neither widens what is accepted (the values were already\n * `FunctionDef` / `BucketDef`) nor perturbs the inferred `const Preview` — so slug inference for\n * `BranchTuningFn<Preview>` and the returned {@link Config} is unchanged.\n */\ntype PreviewAutocomplete<Preview> = (Preview extends {\n functions: infer F;\n} ? {\n functions: { [Slug in keyof F]: FunctionDef };\n} : unknown) & (Preview extends {\n buckets: infer B;\n} ? {\n buckets: { [Name in keyof B]: BucketDef };\n} : unknown);\n/**\n * Validate and freeze a Neon branch policy.\n *\n * Used at the top of `neon.ts`:\n * ```ts\n * import { defineConfig } from \"@neon/config/v1\";\n *\n * export default defineConfig({\n * auth: true,\n * preview: {\n * functions: {\n * hello: { name: \"Hello\", source: \"./functions/hello.ts\", dev: { port: 8787 } },\n * },\n * },\n * branch: (branch) => ({ protected: branch.name === \"main\" }),\n * });\n * ```\n *\n * The policy is split into a **static** existential set (top-level `auth` / `dataApi`\n * toggles and the beta `preview` block) and a **dynamic** per-branch `branch` closure. The\n * static half determines which secrets exist — so `NeonEnv<typeof config>` and `parseEnv`\n * are exact — while the closure can only *tune* a branch (lifecycle, compute, per-function\n * deploy settings), never change what exists.\n *\n * The `branch` callback receives a read-only {@link BranchTarget} descriptor of the branch\n * being decided for (not a live handle); switch on its facts (`branch.name`,\n * `branch.isDefault`, `branch.exists`, …) and **return** the desired tuning. It runs in two\n * modes: against an existing branch (fields populated from Neon) and during pre-create\n * evaluation (`exists: false`, `id` undefined).\n *\n * Pure: no I/O, no side effects. The static parts are validated here; the closure's output\n * is validated every time it is evaluated so errors point at the concrete branch target.\n */\ndeclare function defineConfig<const Auth extends ServiceToggleInput | undefined = undefined, const DataApi extends DataApiInput | undefined = undefined, const Preview extends PreviewInput | undefined = undefined>(input: {\n auth?: Auth & ServiceToggleInput;\n dataApi?: DataApiField<Auth, DataApi>;\n preview?: Preview & PreviewInput & PreviewAutocomplete<Preview>;\n branch?: BranchTuningFn<Preview>;\n}): Config<Auth, DataApi, Preview>;\n/**\n * Evaluate a branch policy for a specific branch target and return a normalized config.\n *\n * Merges the static existential set (services + preview functions/buckets) with the\n * per-branch tuning returned by the `branch` closure into the same {@link\n * ResolvedBranchConfig} the rest of the runtime (diff / push / fetchEnv) consumes.\n */\ndeclare function resolveConfig(config: Config, branch: BranchTarget): ResolvedBranchConfig;\n/**\n * Normalize a region identifier to Neon's `<cloud>-<region>` format. When the user writes\n * `us-east-1` we assume `aws-us-east-1`. Pure helper used by both the validator and the\n * NeonApi adapter.\n */\ndeclare function normalizeRegion(region: string): string;\n//#endregion\nexport { DataApiField, NeonAuthRequiredHint, defineConfig, normalizeRegion, resolveConfig };\n//# sourceMappingURL=define-config.d.ts.map"],"mappings":";;;;;;;;;;;iBAiHiBoB,aAAAA,SAAsBjB,gBAAgBH,eAAeO"}
|
|
@@ -124,7 +124,7 @@ interface EnableDataApiInput {
|
|
|
124
124
|
settings?: DataApiSettings;
|
|
125
125
|
}
|
|
126
126
|
/**
|
|
127
|
-
* A branchable object-storage bucket (Preview). Backed by
|
|
127
|
+
* A branchable object-storage bucket (Preview). Backed by Neon's
|
|
128
128
|
* branchable-storage service.
|
|
129
129
|
*/
|
|
130
130
|
interface NeonBucketSnapshot {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"neon-api.d.ts","names":["BucketAccessLevel","ComputeSettings","CredentialPrincipalType","CredentialScope","DataApiAuthProvider","DataApiSettings","FunctionRuntime","NeonProjectSnapshot","NeonBranchSnapshot","NeonEndpointSnapshot","CreateProjectInput","CreateBranchInput","UpdateBranchInput","NeonRoleSnapshot","NeonDatabaseSnapshot","NeonAuthSnapshot","NeonDataApiSnapshot","EnableDataApiInput","NeonBucketSnapshot","NeonBranchStorageSnapshot","CreateBucketInput","NeonFunctionSnapshot","DeployFunctionInput","Uint8Array","Record","NeonFunctionDeploymentSnapshot","CreateCredentialInput","NeonCredentialSecret","NeonCredentialMeta","GetConnectionUriInput","NeonApi","Promise"],"sources":["../../../../../config/dist/lib/neon-api.d.ts"],"sourcesContent":["import { BucketAccessLevel, ComputeSettings, CredentialPrincipalType, CredentialScope, DataApiAuthProvider, DataApiSettings, FunctionRuntime } from \"./types.js\";\n\n//#region src/lib/neon-api.d.ts\n\n/**\n * Snapshot of a Neon project field set we care about. Maps onto a subset of the upstream\n * `@neondatabase/api-client` `Project` type. We do **not** widen this to the full upstream\n * shape — keeping the surface narrow makes the in-memory fake practical to maintain.\n */\ninterface NeonProjectSnapshot {\n id: string;\n name: string;\n regionId: string;\n pgVersion: number;\n orgId?: string;\n defaultEndpointSettings?: ComputeSettings;\n}\ninterface NeonBranchSnapshot {\n id: string;\n name: string;\n parentId?: string;\n isDefault: boolean;\n /** Whether the branch is marked protected on Neon. */\n protected: boolean;\n expiresAt?: string;\n}\ninterface NeonEndpointSnapshot {\n id: string;\n branchId: string;\n type: \"read_only\" | \"read_write\";\n autoscalingLimitMinCu: ComputeSettings[\"autoscalingLimitMinCu\"];\n autoscalingLimitMaxCu: ComputeSettings[\"autoscalingLimitMaxCu\"];\n suspendTimeout: ComputeSettings[\"suspendTimeout\"];\n}\ninterface CreateProjectInput {\n name: string;\n regionId: string;\n pgVersion?: number;\n orgId?: string;\n defaultEndpointSettings?: ComputeSettings;\n /**\n * Optional name for the project's auto-created default branch. When omitted, Neon\n * uses its own default (`main`).\n */\n defaultBranchName?: string;\n}\ninterface CreateBranchInput {\n name: string;\n parentId?: string;\n expiresAt?: string;\n /** When `true`, the branch is created with the `protected` flag set on Neon. */\n protected?: boolean;\n computeSettings?: ComputeSettings;\n}\ninterface UpdateBranchInput {\n name?: string;\n expiresAt?: string | null;\n /** When set, toggles the branch's `protected` flag on Neon. */\n protected?: boolean;\n}\n/**\n * A role on a Neon branch (e.g. `neondb_owner`). Passwords are never returned by\n * {@link NeonApi.listBranchRoles}; use {@link NeonApi.getConnectionUri} to fetch a URI\n * with the role's password baked in.\n */\ninterface NeonRoleSnapshot {\n name: string;\n branchId: string;\n /** Whether the role is system-protected (cannot be deleted). */\n protected: boolean;\n}\n/**\n * A database on a Neon branch (e.g. `neondb`).\n */\ninterface NeonDatabaseSnapshot {\n name: string;\n branchId: string;\n /** The role that owns the database (one role can own multiple databases). */\n ownerName: string;\n}\n/**\n * Bits of a Neon Auth integration. The key fields are optional because the Neon API only\n * includes them on create / rotate responses; `GET /auth` returns the public fields.\n */\ninterface NeonAuthSnapshot {\n /** The Neon Auth project id (`auth_provider_project_id` on the Neon API). */\n projectId: string;\n /** Public client key (`pub_client_key`), only present on create / rotate responses. */\n publishableClientKey?: string;\n /** Secret server key (`secret_server_key`), only present on create / rotate responses. */\n secretServerKey?: string;\n /** JWKS URL for verifying tokens issued by Neon Auth. */\n jwksUrl: string;\n /** Optional base URL of the Neon Auth deployment. */\n baseUrl?: string;\n}\n/**\n * Public, fetchable bits of a Neon Data API integration on a specific branch — the subset of\n * the Neon API `DataAPIReponse` we model. `settings` is only populated for SubZero-backed\n * integrations (the API returns `null` otherwise), so it is used for settings-drift diffing\n * when present and ignored when absent.\n */\ninterface NeonDataApiSnapshot {\n /** REST endpoint URL. */\n url: string;\n /** Deployment status (e.g. `\"ready\"`), when reported. */\n status?: string;\n /** Current runtime settings (SubZero only); `null`/absent when not reported. */\n settings?: DataApiSettings | null;\n}\n/**\n * Input for {@link NeonApi.enableProjectBranchDataApi} — the create-time wiring for a Data\n * API integration (the subset of the Neon API `DataAPICreateRequest` we expose; the\n * `add_default_grants` / `skip_auth_schema` create flags are intentionally not modeled).\n * `authProvider` is the friendly `\"neon\"` / `\"external\"` value (mapped to the API's\n * `neon_auth` / `external` by the adapter).\n */\ninterface EnableDataApiInput {\n authProvider?: DataApiAuthProvider;\n jwksUrl?: string;\n providerName?: string;\n jwtAudience?: string;\n settings?: DataApiSettings;\n}\n/**\n * A branchable object-storage bucket (Preview). Backed by the Neon Platform\n * branchable-storage service.\n */\ninterface NeonBucketSnapshot {\n name: string;\n accessLevel: BucketAccessLevel;\n}\n/**\n * S3-compatible connection details for a branch's object storage (Preview) — the\n * `BranchStorage` shape from `GET /projects/{id}/branches/{id}/storage`. Non-secret: it\n * carries the endpoint/region/addressing the S3 SDK needs, while the access keys come from\n * a minted {@link NeonCredentialSecret}. `forcePathStyle` is always `true` today (Neon's\n * wildcard TLS cert puts the branch id in the subdomain, so the bucket must travel in the\n * path).\n */\ninterface NeonBranchStorageSnapshot {\n /** S3-compatible endpoint URL, e.g. `https://br-….storage.<suffix>`. */\n s3Endpoint: string;\n /** AWS region string, normalized server-side (e.g. `us-east-2`, `us-east-1`). */\n region: string;\n /** Whether the S3 client must use path-style addressing (always `true` today). */\n forcePathStyle: boolean;\n}\n/**\n * Input for creating a bucket on a branch.\n */\ninterface CreateBucketInput {\n name: string;\n accessLevel?: BucketAccessLevel;\n}\n/**\n * A Neon Function on a branch (Preview). Mirrors the subset of the Functions API we model:\n * the immutable `slug`, the display `name`, and the active deployment id when one exists.\n */\ninterface NeonFunctionSnapshot {\n /** Opaque, stable function identifier. */\n id: string;\n /** Branch-unique slug (the invocation path segment). Immutable. */\n slug: string;\n /** Free-form display name. */\n name: string;\n /** URL at which the function is invoked. */\n invocationUrl: string;\n /** Id (platform version number) of the active deployment, when any code is deployed. */\n activeDeploymentId?: number;\n}\n/**\n * Input for deploying code to a function. `bundle` is the already-built ZIP archive of the\n * function source — building it (esbuild + zip) is an imperative step performed by the\n * caller, not by the {@link NeonApi} adapter.\n */\ninterface DeployFunctionInput {\n bundle: Uint8Array;\n runtime: FunctionRuntime;\n environment: Record<string, string>;\n}\n/**\n * A function deployment (Preview).\n */\ninterface NeonFunctionDeploymentSnapshot {\n /** The deployment id (monotonic per function). */\n id: number;\n status: \"pending\" | \"building\" | \"completed\" | \"failed\";\n}\n/**\n * Input for {@link NeonApi.createCredential}. Mirrors the Neon API `CreateCredentialRequest`\n * (`POST .../credentials`, `x-stability-level: beta`):\n *\n * - `scopes` — 1–16 capabilities the credential may exercise (derived from the policy's\n * enabled Preview features, never hand-authored).\n * - `principalType` — `user` (developer/app) or `function` (a deployed function).\n * - `functionId` — required when `principalType === \"function\"`.\n * - `name` — optional free-form label echoed back on the response.\n */\ninterface CreateCredentialInput {\n scopes: CredentialScope[];\n principalType: CredentialPrincipalType;\n functionId?: string;\n name?: string;\n}\n/**\n * The secret-bearing result of {@link NeonApi.createCredential} — the Neon API\n * `CreateCredentialResponse`. `apiToken` and `s3SecretAccessKey` are returned **exactly\n * once** (they are not stored server-side), so the caller must persist them immediately;\n * they can never be re-fetched (the list endpoint returns metadata only). `tokenIdShort`\n * is the public identifier embedded in `apiToken` (`nt_live_<tokenIdShort>_…`) and doubles\n * as the S3 access-key id.\n */\ninterface NeonCredentialSecret {\n tokenId: string;\n tokenIdShort: string;\n name?: string;\n /** Bearer token (`nt_live_…`); returned once. Used for AI Gateway / Functions invoke. */\n apiToken: string;\n /** 64-char hex S3 secret access key; returned once. Paired with `tokenIdShort` as the access-key id. */\n s3SecretAccessKey: string;\n scopes: CredentialScope[];\n branchId: string;\n createdAt: string;\n /** When the credential expires; absent means it never expires. */\n expiresAt?: string;\n}\n/**\n * Secret-free metadata for an issued credential — the Neon API `CredentialMeta` returned by\n * {@link NeonApi.listCredentials}. Never includes `apiToken` / `s3SecretAccessKey`.\n */\ninterface NeonCredentialMeta {\n tokenId: string;\n tokenIdShort: string;\n name?: string;\n scopes: CredentialScope[];\n principalType: CredentialPrincipalType;\n functionId?: string;\n branchId?: string;\n createdAt: string;\n lastUsedAt?: string;\n revokedAt?: string;\n expiresAt?: string;\n}\n/**\n * Parameters accepted by {@link NeonApi.getConnectionUri}. `branchId` and `endpointId`\n * are optional — when omitted, the API uses the project's default branch and that\n * branch's read-write endpoint, respectively.\n */\ninterface GetConnectionUriInput {\n branchId?: string;\n endpointId?: string;\n databaseName: string;\n roleName: string;\n /** When `true`, returns the pooled (PgBouncer) URI instead of the direct URI. */\n pooled?: boolean;\n}\n/**\n * Narrow façade over the Neon management API. `pullConfig`, `pushConfig`, and `fetchEnv`\n * depend on this interface — *not* on `@neondatabase/api-client` directly — which lets us\n * inject a real in-memory fake during tests without resorting to module mocks.\n */\ninterface NeonApi {\n listProjects(filter: {\n orgId?: string;\n }): Promise<NeonProjectSnapshot[]>;\n getProject(projectId: string): Promise<NeonProjectSnapshot>;\n createProject(input: CreateProjectInput): Promise<NeonProjectSnapshot>;\n updateProject(projectId: string, input: {\n name?: string;\n defaultEndpointSettings?: ComputeSettings;\n }): Promise<NeonProjectSnapshot>;\n listBranches(projectId: string): Promise<NeonBranchSnapshot[]>;\n createBranch(projectId: string, input: CreateBranchInput): Promise<{\n branch: NeonBranchSnapshot;\n endpoints: NeonEndpointSnapshot[];\n }>;\n updateBranch(projectId: string, branchId: string, input: UpdateBranchInput): Promise<NeonBranchSnapshot>;\n listEndpoints(projectId: string): Promise<NeonEndpointSnapshot[]>;\n updateEndpoint(projectId: string, endpointId: string, settings: ComputeSettings): Promise<NeonEndpointSnapshot>;\n /** List roles on a branch. Used by {@link fetchEnv} to auto-pick the role when only one exists. */\n listBranchRoles(projectId: string, branchId: string): Promise<NeonRoleSnapshot[]>;\n /** List databases on a branch. Used by {@link fetchEnv} to auto-pick the database when only one exists. */\n listBranchDatabases(projectId: string, branchId: string): Promise<NeonDatabaseSnapshot[]>;\n /**\n * Fetch a Postgres connection URI for the given role + database on a branch.\n * Returns the same string the Neon Console shows under \"Connection Details\".\n */\n getConnectionUri(projectId: string, input: GetConnectionUriInput): Promise<{\n uri: string;\n }>;\n /**\n * Fetch the Neon Auth integration attached to a specific branch. Returns `null` when\n * no integration is enabled — used by `fetchEnv` to decide whether the `env.auth`\n * namespace can be populated.\n */\n getNeonAuth(projectId: string, branchId: string): Promise<NeonAuthSnapshot | null>;\n /**\n * Enable the Neon Auth integration on a specific branch. Idempotent: if an integration\n * is already enabled, the existing snapshot is returned unchanged. Used by\n * `pushConfig` and `branch` to honour branch policy `auth: {}` / `auth.enabled: true`.\n */\n enableNeonAuth(projectId: string, branchId: string, input?: {\n databaseName?: string;\n }): Promise<NeonAuthSnapshot>;\n /**\n * Fetch the Neon Data API integration attached to a specific branch + database.\n * Returns `null` when no integration is enabled — used by `fetchEnv` to decide\n * whether the `env.dataApi` namespace can be populated.\n */\n getNeonDataApi(projectId: string, branchId: string, databaseName: string): Promise<NeonDataApiSnapshot | null>;\n /**\n * Enable the Neon Data API integration on a specific branch + database. Idempotent:\n * if an integration is already enabled, the existing snapshot is returned unchanged.\n * Used by `pushConfig` to honour branch policy `dataApi: {}` / `dataApi: { … }`. The\n * optional {@link EnableDataApiInput} carries the create-time auth wiring + initial\n * settings; omit it for an all-defaults, Neon-Auth integration.\n */\n enableProjectBranchDataApi(projectId: string, branchId: string, databaseName: string, input?: EnableDataApiInput): Promise<NeonDataApiSnapshot>;\n /**\n * Update the runtime {@link DataApiSettings} of an already-enabled Data API integration\n * (the Neon API `PATCH .../data-api/{db}`; always refreshes the schema cache). Only\n * `settings` are mutable post-create — the auth provider / JWKS wiring is fixed at\n * enable time. Used by `pushConfig` to reconcile settings drift under `updateExisting`.\n */\n updateProjectBranchDataApi(projectId: string, branchId: string, databaseName: string, settings: DataApiSettings): Promise<NeonDataApiSnapshot>;\n /** List branchable object-storage buckets visible on a branch. */\n listBranchBuckets(projectId: string, branchId: string): Promise<NeonBucketSnapshot[]>;\n /** Create a bucket on a branch. Used by `pushConfig` to honour `preview.buckets`. */\n createBranchBucket(projectId: string, branchId: string, input: CreateBucketInput): Promise<NeonBucketSnapshot>;\n /** Delete a bucket from a branch. */\n deleteBranchBucket(projectId: string, branchId: string, bucketName: string): Promise<void>;\n /**\n * Fetch the branch's S3-compatible object-storage connection details (endpoint, region,\n * path-style). Returns `null` when storage is not enabled for the branch (the API's 404\n * `BranchStorageNotEnabled`). Used by `fetchEnv` to populate the `AWS_*` storage env\n * alongside the minted credential's access keys.\n */\n getProjectBranchStorage(projectId: string, branchId: string): Promise<NeonBranchStorageSnapshot | null>;\n /** List functions on a branch. */\n listBranchFunctions(projectId: string, branchId: string): Promise<NeonFunctionSnapshot[]>;\n /** Delete a function (by slug) from a branch. */\n deleteBranchFunction(projectId: string, branchId: string, slug: string): Promise<void>;\n /**\n * Deploy a built bundle to a function, creating the function if it does not yet exist —\n * Neon has no separate create endpoint, so the first deployment to a slug creates the\n * function. The newest deployment becomes active. The `bundle` is built (esbuild + zip)\n * by the caller and passed in as bytes.\n */\n deployBranchFunction(projectId: string, branchId: string, slug: string, input: DeployFunctionInput): Promise<NeonFunctionDeploymentSnapshot>;\n /**\n * Mint a new scoped service credential on a branch (`POST .../credentials`). The\n * returned {@link NeonCredentialSecret} carries `apiToken` + `s3SecretAccessKey`\n * **once** — persist them immediately. Used by `fetchEnv` / `env pull` to issue the\n * unified credential for the branch's enabled Preview features (object storage, AI\n * Gateway, Functions).\n */\n createCredential(projectId: string, branchId: string, input: CreateCredentialInput): Promise<NeonCredentialSecret>;\n /**\n * List the secret-free metadata for credentials issued on a branch\n * (`GET .../credentials`). Used to report issued credentials (e.g. `config status`)\n * and to verify a persisted credential still exists / isn't revoked.\n */\n listCredentials(projectId: string, branchId: string): Promise<NeonCredentialMeta[]>;\n /**\n * Revoke (soft-delete) a credential by its `tokenId` (`DELETE .../credentials/{id}`).\n * Idempotent.\n */\n revokeCredential(projectId: string, branchId: string, tokenId: string): Promise<void>;\n}\n//#endregion\nexport { CreateBranchInput, CreateBucketInput, CreateCredentialInput, CreateProjectInput, DeployFunctionInput, EnableDataApiInput, GetConnectionUriInput, NeonApi, NeonAuthSnapshot, NeonBranchSnapshot, NeonBranchStorageSnapshot, NeonBucketSnapshot, NeonCredentialMeta, NeonCredentialSecret, NeonDataApiSnapshot, NeonDatabaseSnapshot, NeonEndpointSnapshot, NeonFunctionDeploymentSnapshot, NeonFunctionSnapshot, NeonProjectSnapshot, NeonRoleSnapshot, UpdateBranchInput };\n//# sourceMappingURL=neon-api.d.ts.map"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"neon-api.d.ts","names":["BucketAccessLevel","ComputeSettings","CredentialPrincipalType","CredentialScope","DataApiAuthProvider","DataApiSettings","FunctionRuntime","NeonProjectSnapshot","NeonBranchSnapshot","NeonEndpointSnapshot","CreateProjectInput","CreateBranchInput","UpdateBranchInput","NeonRoleSnapshot","NeonDatabaseSnapshot","NeonAuthSnapshot","NeonDataApiSnapshot","EnableDataApiInput","NeonBucketSnapshot","NeonBranchStorageSnapshot","CreateBucketInput","NeonFunctionSnapshot","DeployFunctionInput","Uint8Array","Record","NeonFunctionDeploymentSnapshot","CreateCredentialInput","NeonCredentialSecret","NeonCredentialMeta","GetConnectionUriInput","NeonApi","Promise"],"sources":["../../../../../config/dist/lib/neon-api.d.ts"],"sourcesContent":["import { BucketAccessLevel, ComputeSettings, CredentialPrincipalType, CredentialScope, DataApiAuthProvider, DataApiSettings, FunctionRuntime } from \"./types.js\";\n\n//#region src/lib/neon-api.d.ts\n\n/**\n * Snapshot of a Neon project field set we care about. Maps onto a subset of the upstream\n * `@neondatabase/api-client` `Project` type. We do **not** widen this to the full upstream\n * shape — keeping the surface narrow makes the in-memory fake practical to maintain.\n */\ninterface NeonProjectSnapshot {\n id: string;\n name: string;\n regionId: string;\n pgVersion: number;\n orgId?: string;\n defaultEndpointSettings?: ComputeSettings;\n}\ninterface NeonBranchSnapshot {\n id: string;\n name: string;\n parentId?: string;\n isDefault: boolean;\n /** Whether the branch is marked protected on Neon. */\n protected: boolean;\n expiresAt?: string;\n}\ninterface NeonEndpointSnapshot {\n id: string;\n branchId: string;\n type: \"read_only\" | \"read_write\";\n autoscalingLimitMinCu: ComputeSettings[\"autoscalingLimitMinCu\"];\n autoscalingLimitMaxCu: ComputeSettings[\"autoscalingLimitMaxCu\"];\n suspendTimeout: ComputeSettings[\"suspendTimeout\"];\n}\ninterface CreateProjectInput {\n name: string;\n regionId: string;\n pgVersion?: number;\n orgId?: string;\n defaultEndpointSettings?: ComputeSettings;\n /**\n * Optional name for the project's auto-created default branch. When omitted, Neon\n * uses its own default (`main`).\n */\n defaultBranchName?: string;\n}\ninterface CreateBranchInput {\n name: string;\n parentId?: string;\n expiresAt?: string;\n /** When `true`, the branch is created with the `protected` flag set on Neon. */\n protected?: boolean;\n computeSettings?: ComputeSettings;\n}\ninterface UpdateBranchInput {\n name?: string;\n expiresAt?: string | null;\n /** When set, toggles the branch's `protected` flag on Neon. */\n protected?: boolean;\n}\n/**\n * A role on a Neon branch (e.g. `neondb_owner`). Passwords are never returned by\n * {@link NeonApi.listBranchRoles}; use {@link NeonApi.getConnectionUri} to fetch a URI\n * with the role's password baked in.\n */\ninterface NeonRoleSnapshot {\n name: string;\n branchId: string;\n /** Whether the role is system-protected (cannot be deleted). */\n protected: boolean;\n}\n/**\n * A database on a Neon branch (e.g. `neondb`).\n */\ninterface NeonDatabaseSnapshot {\n name: string;\n branchId: string;\n /** The role that owns the database (one role can own multiple databases). */\n ownerName: string;\n}\n/**\n * Bits of a Neon Auth integration. The key fields are optional because the Neon API only\n * includes them on create / rotate responses; `GET /auth` returns the public fields.\n */\ninterface NeonAuthSnapshot {\n /** The Neon Auth project id (`auth_provider_project_id` on the Neon API). */\n projectId: string;\n /** Public client key (`pub_client_key`), only present on create / rotate responses. */\n publishableClientKey?: string;\n /** Secret server key (`secret_server_key`), only present on create / rotate responses. */\n secretServerKey?: string;\n /** JWKS URL for verifying tokens issued by Neon Auth. */\n jwksUrl: string;\n /** Optional base URL of the Neon Auth deployment. */\n baseUrl?: string;\n}\n/**\n * Public, fetchable bits of a Neon Data API integration on a specific branch — the subset of\n * the Neon API `DataAPIReponse` we model. `settings` is only populated for SubZero-backed\n * integrations (the API returns `null` otherwise), so it is used for settings-drift diffing\n * when present and ignored when absent.\n */\ninterface NeonDataApiSnapshot {\n /** REST endpoint URL. */\n url: string;\n /** Deployment status (e.g. `\"ready\"`), when reported. */\n status?: string;\n /** Current runtime settings (SubZero only); `null`/absent when not reported. */\n settings?: DataApiSettings | null;\n}\n/**\n * Input for {@link NeonApi.enableProjectBranchDataApi} — the create-time wiring for a Data\n * API integration (the subset of the Neon API `DataAPICreateRequest` we expose; the\n * `add_default_grants` / `skip_auth_schema` create flags are intentionally not modeled).\n * `authProvider` is the friendly `\"neon\"` / `\"external\"` value (mapped to the API's\n * `neon_auth` / `external` by the adapter).\n */\ninterface EnableDataApiInput {\n authProvider?: DataApiAuthProvider;\n jwksUrl?: string;\n providerName?: string;\n jwtAudience?: string;\n settings?: DataApiSettings;\n}\n/**\n * A branchable object-storage bucket (Preview). Backed by Neon's\n * branchable-storage service.\n */\ninterface NeonBucketSnapshot {\n name: string;\n accessLevel: BucketAccessLevel;\n}\n/**\n * S3-compatible connection details for a branch's object storage (Preview) — the\n * `BranchStorage` shape from `GET /projects/{id}/branches/{id}/storage`. Non-secret: it\n * carries the endpoint/region/addressing the S3 SDK needs, while the access keys come from\n * a minted {@link NeonCredentialSecret}. `forcePathStyle` is always `true` today (Neon's\n * wildcard TLS cert puts the branch id in the subdomain, so the bucket must travel in the\n * path).\n */\ninterface NeonBranchStorageSnapshot {\n /** S3-compatible endpoint URL, e.g. `https://br-….storage.<suffix>`. */\n s3Endpoint: string;\n /** AWS region string, normalized server-side (e.g. `us-east-2`, `us-east-1`). */\n region: string;\n /** Whether the S3 client must use path-style addressing (always `true` today). */\n forcePathStyle: boolean;\n}\n/**\n * Input for creating a bucket on a branch.\n */\ninterface CreateBucketInput {\n name: string;\n accessLevel?: BucketAccessLevel;\n}\n/**\n * A Neon Function on a branch (Preview). Mirrors the subset of the Functions API we model:\n * the immutable `slug`, the display `name`, and the active deployment id when one exists.\n */\ninterface NeonFunctionSnapshot {\n /** Opaque, stable function identifier. */\n id: string;\n /** Branch-unique slug (the invocation path segment). Immutable. */\n slug: string;\n /** Free-form display name. */\n name: string;\n /** URL at which the function is invoked. */\n invocationUrl: string;\n /** Id (platform version number) of the active deployment, when any code is deployed. */\n activeDeploymentId?: number;\n}\n/**\n * Input for deploying code to a function. `bundle` is the already-built ZIP archive of the\n * function source — building it (esbuild + zip) is an imperative step performed by the\n * caller, not by the {@link NeonApi} adapter.\n */\ninterface DeployFunctionInput {\n bundle: Uint8Array;\n runtime: FunctionRuntime;\n environment: Record<string, string>;\n}\n/**\n * A function deployment (Preview).\n */\ninterface NeonFunctionDeploymentSnapshot {\n /** The deployment id (monotonic per function). */\n id: number;\n status: \"pending\" | \"building\" | \"completed\" | \"failed\";\n}\n/**\n * Input for {@link NeonApi.createCredential}. Mirrors the Neon API `CreateCredentialRequest`\n * (`POST .../credentials`, `x-stability-level: beta`):\n *\n * - `scopes` — 1–16 capabilities the credential may exercise (derived from the policy's\n * enabled Preview features, never hand-authored).\n * - `principalType` — `user` (developer/app) or `function` (a deployed function).\n * - `functionId` — required when `principalType === \"function\"`.\n * - `name` — optional free-form label echoed back on the response.\n */\ninterface CreateCredentialInput {\n scopes: CredentialScope[];\n principalType: CredentialPrincipalType;\n functionId?: string;\n name?: string;\n}\n/**\n * The secret-bearing result of {@link NeonApi.createCredential} — the Neon API\n * `CreateCredentialResponse`. `apiToken` and `s3SecretAccessKey` are returned **exactly\n * once** (they are not stored server-side), so the caller must persist them immediately;\n * they can never be re-fetched (the list endpoint returns metadata only). `tokenIdShort`\n * is the public identifier embedded in `apiToken` (`nt_live_<tokenIdShort>_…`) and doubles\n * as the S3 access-key id.\n */\ninterface NeonCredentialSecret {\n tokenId: string;\n tokenIdShort: string;\n name?: string;\n /** Bearer token (`nt_live_…`); returned once. Used for AI Gateway / Functions invoke. */\n apiToken: string;\n /** 64-char hex S3 secret access key; returned once. Paired with `tokenIdShort` as the access-key id. */\n s3SecretAccessKey: string;\n scopes: CredentialScope[];\n branchId: string;\n createdAt: string;\n /** When the credential expires; absent means it never expires. */\n expiresAt?: string;\n}\n/**\n * Secret-free metadata for an issued credential — the Neon API `CredentialMeta` returned by\n * {@link NeonApi.listCredentials}. Never includes `apiToken` / `s3SecretAccessKey`.\n */\ninterface NeonCredentialMeta {\n tokenId: string;\n tokenIdShort: string;\n name?: string;\n scopes: CredentialScope[];\n principalType: CredentialPrincipalType;\n functionId?: string;\n branchId?: string;\n createdAt: string;\n lastUsedAt?: string;\n revokedAt?: string;\n expiresAt?: string;\n}\n/**\n * Parameters accepted by {@link NeonApi.getConnectionUri}. `branchId` and `endpointId`\n * are optional — when omitted, the API uses the project's default branch and that\n * branch's read-write endpoint, respectively.\n */\ninterface GetConnectionUriInput {\n branchId?: string;\n endpointId?: string;\n databaseName: string;\n roleName: string;\n /** When `true`, returns the pooled (PgBouncer) URI instead of the direct URI. */\n pooled?: boolean;\n}\n/**\n * Narrow façade over the Neon management API. `pullConfig`, `pushConfig`, and `fetchEnv`\n * depend on this interface — *not* on `@neondatabase/api-client` directly — which lets us\n * inject a real in-memory fake during tests without resorting to module mocks.\n */\ninterface NeonApi {\n listProjects(filter: {\n orgId?: string;\n }): Promise<NeonProjectSnapshot[]>;\n getProject(projectId: string): Promise<NeonProjectSnapshot>;\n createProject(input: CreateProjectInput): Promise<NeonProjectSnapshot>;\n updateProject(projectId: string, input: {\n name?: string;\n defaultEndpointSettings?: ComputeSettings;\n }): Promise<NeonProjectSnapshot>;\n listBranches(projectId: string): Promise<NeonBranchSnapshot[]>;\n createBranch(projectId: string, input: CreateBranchInput): Promise<{\n branch: NeonBranchSnapshot;\n endpoints: NeonEndpointSnapshot[];\n }>;\n updateBranch(projectId: string, branchId: string, input: UpdateBranchInput): Promise<NeonBranchSnapshot>;\n listEndpoints(projectId: string): Promise<NeonEndpointSnapshot[]>;\n updateEndpoint(projectId: string, endpointId: string, settings: ComputeSettings): Promise<NeonEndpointSnapshot>;\n /** List roles on a branch. Used by {@link fetchEnv} to auto-pick the role when only one exists. */\n listBranchRoles(projectId: string, branchId: string): Promise<NeonRoleSnapshot[]>;\n /** List databases on a branch. Used by {@link fetchEnv} to auto-pick the database when only one exists. */\n listBranchDatabases(projectId: string, branchId: string): Promise<NeonDatabaseSnapshot[]>;\n /**\n * Fetch a Postgres connection URI for the given role + database on a branch.\n * Returns the same string the Neon Console shows under \"Connection Details\".\n */\n getConnectionUri(projectId: string, input: GetConnectionUriInput): Promise<{\n uri: string;\n }>;\n /**\n * Fetch the Neon Auth integration attached to a specific branch. Returns `null` when\n * no integration is enabled — used by `fetchEnv` to decide whether the `env.auth`\n * namespace can be populated.\n */\n getNeonAuth(projectId: string, branchId: string): Promise<NeonAuthSnapshot | null>;\n /**\n * Enable the Neon Auth integration on a specific branch. Idempotent: if an integration\n * is already enabled, the existing snapshot is returned unchanged. Used by\n * `pushConfig` and `branch` to honour branch policy `auth: {}` / `auth.enabled: true`.\n */\n enableNeonAuth(projectId: string, branchId: string, input?: {\n databaseName?: string;\n }): Promise<NeonAuthSnapshot>;\n /**\n * Fetch the Neon Data API integration attached to a specific branch + database.\n * Returns `null` when no integration is enabled — used by `fetchEnv` to decide\n * whether the `env.dataApi` namespace can be populated.\n */\n getNeonDataApi(projectId: string, branchId: string, databaseName: string): Promise<NeonDataApiSnapshot | null>;\n /**\n * Enable the Neon Data API integration on a specific branch + database. Idempotent:\n * if an integration is already enabled, the existing snapshot is returned unchanged.\n * Used by `pushConfig` to honour branch policy `dataApi: {}` / `dataApi: { … }`. The\n * optional {@link EnableDataApiInput} carries the create-time auth wiring + initial\n * settings; omit it for an all-defaults, Neon-Auth integration.\n */\n enableProjectBranchDataApi(projectId: string, branchId: string, databaseName: string, input?: EnableDataApiInput): Promise<NeonDataApiSnapshot>;\n /**\n * Update the runtime {@link DataApiSettings} of an already-enabled Data API integration\n * (the Neon API `PATCH .../data-api/{db}`; always refreshes the schema cache). Only\n * `settings` are mutable post-create — the auth provider / JWKS wiring is fixed at\n * enable time. Used by `pushConfig` to reconcile settings drift under `updateExisting`.\n */\n updateProjectBranchDataApi(projectId: string, branchId: string, databaseName: string, settings: DataApiSettings): Promise<NeonDataApiSnapshot>;\n /** List branchable object-storage buckets visible on a branch. */\n listBranchBuckets(projectId: string, branchId: string): Promise<NeonBucketSnapshot[]>;\n /** Create a bucket on a branch. Used by `pushConfig` to honour `preview.buckets`. */\n createBranchBucket(projectId: string, branchId: string, input: CreateBucketInput): Promise<NeonBucketSnapshot>;\n /** Delete a bucket from a branch. */\n deleteBranchBucket(projectId: string, branchId: string, bucketName: string): Promise<void>;\n /**\n * Fetch the branch's S3-compatible object-storage connection details (endpoint, region,\n * path-style). Returns `null` when storage is not enabled for the branch (the API's 404\n * `BranchStorageNotEnabled`). Used by `fetchEnv` to populate the `AWS_*` storage env\n * alongside the minted credential's access keys.\n */\n getProjectBranchStorage(projectId: string, branchId: string): Promise<NeonBranchStorageSnapshot | null>;\n /** List functions on a branch. */\n listBranchFunctions(projectId: string, branchId: string): Promise<NeonFunctionSnapshot[]>;\n /** Delete a function (by slug) from a branch. */\n deleteBranchFunction(projectId: string, branchId: string, slug: string): Promise<void>;\n /**\n * Deploy a built bundle to a function, creating the function if it does not yet exist —\n * Neon has no separate create endpoint, so the first deployment to a slug creates the\n * function. The newest deployment becomes active. The `bundle` is built (esbuild + zip)\n * by the caller and passed in as bytes.\n */\n deployBranchFunction(projectId: string, branchId: string, slug: string, input: DeployFunctionInput): Promise<NeonFunctionDeploymentSnapshot>;\n /**\n * Mint a new scoped service credential on a branch (`POST .../credentials`). The\n * returned {@link NeonCredentialSecret} carries `apiToken` + `s3SecretAccessKey`\n * **once** — persist them immediately. Used by `fetchEnv` / `env pull` to issue the\n * unified credential for the branch's enabled Preview features (object storage, AI\n * Gateway, Functions).\n */\n createCredential(projectId: string, branchId: string, input: CreateCredentialInput): Promise<NeonCredentialSecret>;\n /**\n * List the secret-free metadata for credentials issued on a branch\n * (`GET .../credentials`). Used to report issued credentials (e.g. `config status`)\n * and to verify a persisted credential still exists / isn't revoked.\n */\n listCredentials(projectId: string, branchId: string): Promise<NeonCredentialMeta[]>;\n /**\n * Revoke (soft-delete) a credential by its `tokenId` (`DELETE .../credentials/{id}`).\n * Idempotent.\n */\n revokeCredential(projectId: string, branchId: string, tokenId: string): Promise<void>;\n}\n//#endregion\nexport { CreateBranchInput, CreateBucketInput, CreateCredentialInput, CreateProjectInput, DeployFunctionInput, EnableDataApiInput, GetConnectionUriInput, NeonApi, NeonAuthSnapshot, NeonBranchSnapshot, NeonBranchStorageSnapshot, NeonBucketSnapshot, NeonCredentialMeta, NeonCredentialSecret, NeonDataApiSnapshot, NeonDatabaseSnapshot, NeonEndpointSnapshot, NeonFunctionDeploymentSnapshot, NeonFunctionSnapshot, NeonProjectSnapshot, NeonRoleSnapshot, UpdateBranchInput };\n//# sourceMappingURL=neon-api.d.ts.map"],"mappings":"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"}
|
|
@@ -47,7 +47,7 @@ type DurationField<Suggestions extends DurationString> = Suggestions | (Duration
|
|
|
47
47
|
*
|
|
48
48
|
* Mirrors the subset of {@link https://api-docs.neon.tech/reference/getting-started-with-neon-api Neon endpoint}
|
|
49
49
|
* fields that we expose as IaC primitives. Anything left undefined falls back to the project's
|
|
50
|
-
* `default_endpoint_settings` (which themselves fall back to Neon
|
|
50
|
+
* `default_endpoint_settings` (which themselves fall back to Neon defaults).
|
|
51
51
|
*/
|
|
52
52
|
interface ComputeSettings {
|
|
53
53
|
/**
|
|
@@ -72,7 +72,7 @@ interface ComputeSettings {
|
|
|
72
72
|
* `<integer><unit>` (units: `s`, `m`, `h`, `d`, `w`). A **unit is required** — for raw
|
|
73
73
|
* seconds pass a `number`, not a string.
|
|
74
74
|
* - `number` — custom timeout in **seconds**, must be in `60`–`604800` (1 minute to 1 week)
|
|
75
|
-
* - `undefined` — use the Neon
|
|
75
|
+
* - `undefined` — use the Neon default (currently 300s / 5 minutes)
|
|
76
76
|
*
|
|
77
77
|
* Whichever form you use, the resolved timeout must fall in `60`–`604800` seconds (the Neon
|
|
78
78
|
* API limit); the suggestions are all within that band, anything else is checked at apply.
|
|
@@ -291,6 +291,42 @@ interface FunctionDef {
|
|
|
291
291
|
* @example { resendApiKey: process.env.RESEND_API_KEY ?? "" }
|
|
292
292
|
*/
|
|
293
293
|
env?: Record<string, string>;
|
|
294
|
+
/**
|
|
295
|
+
* Packages the bundler must leave alone, by name — the deploy-time equivalent of
|
|
296
|
+
* Next.js's `serverExternalPackages`. Every entry is passed to esbuild's `external`,
|
|
297
|
+
* so the import survives into the bundle instead of being followed.
|
|
298
|
+
*
|
|
299
|
+
* Reach for this when bundling a package is impossible rather than merely undesirable.
|
|
300
|
+
* The cases that come up: a native `.node` addon or a `node-gyp` dependency esbuild has
|
|
301
|
+
* no loader for, and an optional peer dependency a library references on a code path
|
|
302
|
+
* this function never takes. Both fail the deploy at bundle time with a resolve or
|
|
303
|
+
* loader error naming the package, and neither is fixable from the function's own
|
|
304
|
+
* source.
|
|
305
|
+
*
|
|
306
|
+
* **An external package is not resolvable at runtime.** The deployed archive is a
|
|
307
|
+
* single `index.mjs` with no `node_modules` beside it, so anything listed here throws
|
|
308
|
+
* `Cannot find module` if the function actually reaches it. This option therefore only
|
|
309
|
+
* unblocks an import that is never evaluated; it does not make a dependency usable.
|
|
310
|
+
*
|
|
311
|
+
* A dependency the handler actually calls has to be bundled, and whether that is
|
|
312
|
+
* possible depends on what it is. A pure-JavaScript package can be bundled, and a
|
|
313
|
+
* failure to do so is usually something specific and fixable. A package backed by a
|
|
314
|
+
* native `.node` binary cannot be bundled by anything — the binary is a compiled
|
|
315
|
+
* object the platform loads from a real path — so such a package cannot work on
|
|
316
|
+
* Functions until the deployed archive can carry files alongside the bundle. Do not
|
|
317
|
+
* reach for `externalPackages` to try: it moves the error from deploy to invoke.
|
|
318
|
+
*
|
|
319
|
+
* Note that a native package may bundle without ever needing this option. `sharp`, for
|
|
320
|
+
* instance, loads its binary through `createRequire`, which esbuild does not follow, so
|
|
321
|
+
* it bundles cleanly and then fails at invoke with "Could not load the sharp module".
|
|
322
|
+
*
|
|
323
|
+
* Entries are package names, optionally with a subpath (`pkg`, `@scope/pkg`,
|
|
324
|
+
* `pkg/sub`), matching esbuild. A relative or absolute path is rejected at validation
|
|
325
|
+
* time: those are local modules, and a local module that cannot be bundled is a
|
|
326
|
+
* different problem.
|
|
327
|
+
* @example ["microsandbox", "@mongodb-js/zstd"]
|
|
328
|
+
*/
|
|
329
|
+
externalPackages?: string[];
|
|
294
330
|
/**
|
|
295
331
|
* Local-development settings used by `neon dev` when serving every function from
|
|
296
332
|
* `neon.ts`. Ignored at deploy time. See {@link FunctionDevConfig}.
|
|
@@ -445,6 +481,12 @@ interface ResolvedFunctionConfig {
|
|
|
445
481
|
name: string;
|
|
446
482
|
source: string;
|
|
447
483
|
env: Record<string, string>;
|
|
484
|
+
/**
|
|
485
|
+
* Packages the bundler leaves unresolved, passed through from
|
|
486
|
+
* {@link FunctionDef.externalPackages}. Absent rather than empty when undeclared, so a
|
|
487
|
+
* policy that never mentions it resolves to the same shape it always did.
|
|
488
|
+
*/
|
|
489
|
+
externalPackages?: string[];
|
|
448
490
|
runtime: FunctionRuntime;
|
|
449
491
|
/**
|
|
450
492
|
* Local-development settings, passed through untouched from {@link FunctionDef.dev}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":["ComputeUnit","DurationUnit","DurationString","SuspendTimeoutSuggestion","TtlSuggestion","DurationField","Suggestions","NonNullable","ComputeSettings","BranchTarget","ServiceToggle","ServiceToggleInput","ServiceEnabled","T","PostgresConfig","DATA_API_AUTH_PROVIDERS","DataApiAuthProvider","DataApiSettings","DataApiConfigBase","DataApiNeonAuthConfig","DataApiExternalAuthConfig","DataApiConfig","DataApiInput","FunctionRuntime","FunctionDevConfig","FunctionDef","Record","CredentialScope","CredentialPrincipalType","BucketAccessLevel","BucketDef","PreviewInput","FunctionTuning","PreviewTuning","Slug","Partial","BranchTuning","FunctionSlugsOf","Preview","F","Extract","BranchTuningFn","Config","Auth","DataApi","ResolvedFunctionConfig","ResolvedBucketConfig","ResolvedPreviewConfig","ResolvedDataApiConfig","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: (branch) => … })` closure. 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;\n/**\n * Resolve a **static** service toggle (`true` / `false` / `{ enabled?: boolean }` / object /\n * `undefined`) to a type-level boolean. The tuple wrapping (`[T] extends […]`) disables\n * distribution so a union/`undefined` is judged as a single unit:\n *\n * - `false` / `{ enabled: false }` / `undefined` → `false`\n * - `true` / `{ enabled: true }` / any other object (`{}`, `{ enabled?: boolean }`) → `true`\n * (a present toggle defaults to enabled)\n * - the bare `boolean | … | undefined` (no literal info) → `false`\n *\n * Shared by the {@link Config} static cross-field checks and the `@neon/env`\n * `NeonEnv` namespace derivation, so both read \"is this service on?\" identically.\n */\ntype ServiceEnabled<T> = [T] extends [false] ? false : [T] extends [{\n enabled: false;\n}] ? false : [T] extends [undefined] ? false : [T] extends [true] ? true : [T] extends [{\n enabled: true;\n}] ? true : [T] extends [object] ? true : false;\ninterface PostgresConfig {\n computeSettings?: ComputeSettings;\n}\n/**\n * Authentication providers a Data API integration can verify JWTs against, as written in\n * `neon.ts`. Friendly authoring values (mapped to the Neon API's `neon_auth` / `external`\n * at the API boundary):\n *\n * - `\"neon\"` — verify tokens minted by **Neon Auth** on the same branch. Neon supplies the\n * JWKS URL / provider wiring for you, so the `jwksUrl` / `providerName` / `jwtAudience`\n * fields are forbidden (a type error) on this variant — and the policy must also enable\n * top-level `auth` (Neon Auth) so the tokens exist.\n * - `\"external\"` — verify tokens from a third-party IdP (Clerk, Stytch, Auth0, …). You\n * provide `jwksUrl` (and optionally `providerName` / `jwtAudience`).\n */\ndeclare const DATA_API_AUTH_PROVIDERS: readonly [\"neon\", \"external\"];\ntype DataApiAuthProvider = (typeof DATA_API_AUTH_PROVIDERS)[number];\n/**\n * Reusable runtime settings for a Data API integration (the Neon API `DataAPISettings`,\n * camelCased to match the rest of `neon.ts`). Every field is optional; omitted fields keep\n * the Neon defaults shown below. These are the **only** Data API fields that can change on\n * an already-enabled integration — drift here is reconciled as an *update* (requires\n * `updateExisting` / `--update-existing`); the create-only auth wiring above cannot.\n */\ninterface DataApiSettings {\n /** Enable the aggregates feature (`db_aggregates_enabled`). Default `true`. */\n dbAggregatesEnabled?: boolean;\n /** Database role used for anonymous requests (`db_anon_role`). Default `\"anonymous\"`. */\n dbAnonRole?: string;\n /** Extra schemas appended to the search path (`db_extra_search_path`). */\n dbExtraSearchPath?: string;\n /** Maximum rows returned in a single request (`db_max_rows`). */\n dbMaxRows?: number;\n /** Schemas exposed via the API (`db_schemas`). Default `[\"public\"]`. */\n dbSchemas?: string[];\n /** JWT claim key used for role extraction (`jwt_role_claim_key`). Default `\".role\"`. */\n jwtRoleClaimKey?: string;\n /** Maximum lifetime of the JWT cache, in seconds (`jwt_cache_max_lifetime`). */\n jwtCacheMaxLifetime?: number;\n /** OpenAPI spec mode (`openapi_mode`). Default `\"disabled\"`. */\n openapiMode?: \"ignore-privileges\" | \"disabled\";\n /** CORS allowed origins (`server_cors_allowed_origins`). */\n serverCorsAllowedOrigins?: string;\n /** Emit server-timing headers (`server_timing_enabled`). */\n serverTimingEnabled?: boolean;\n}\n/** Fields shared by every {@link DataApiConfig} variant. */\ninterface DataApiConfigBase {\n /** Defaults to `true` when the `dataApi` namespace is present. Set `false` to opt out. */\n enabled?: boolean;\n /** Reusable runtime settings. Drift here is reconciled as an update. */\n settings?: DataApiSettings;\n}\n/**\n * Data API verified by **Neon Auth** (`authProvider: \"neon\"`, the default). The external\n * IdP fields are statically forbidden (`?: never`) because Neon supplies them; declaring any\n * of them is a type error directing you to `authProvider: \"external\"`.\n */\ninterface DataApiNeonAuthConfig extends DataApiConfigBase {\n authProvider?: \"neon\";\n /** Forbidden with `authProvider: \"neon\"` — Neon provides the JWKS URL. */\n jwksUrl?: never;\n /** Forbidden with `authProvider: \"neon\"` — the provider is Neon Auth. */\n providerName?: never;\n /** Forbidden with `authProvider: \"neon\"` — Neon manages the audience. */\n jwtAudience?: never;\n}\n/**\n * Data API verified by an **external** IdP (`authProvider: \"external\"`). You provide the\n * JWKS URL (and optionally a provider label / expected audience).\n */\ninterface DataApiExternalAuthConfig extends DataApiConfigBase {\n authProvider: \"external\";\n /** URL that publishes the IdP's JWKS (JSON Web Key Set). */\n jwksUrl?: string;\n /** Human label for the IdP (e.g. \"Clerk\", \"Stytch\", \"Auth0\"). */\n providerName?: string;\n /**\n * Expected `aud` claim. ⚠️ This only **rejects** tokens carrying a *different* audience;\n * tokens with no `aud` claim are still accepted.\n */\n jwtAudience?: string;\n}\n/**\n * Object form of the `dataApi` toggle. A discriminated union on {@link DataApiAuthProvider}:\n * the `\"neon\"` variant forbids the external-IdP fields, the `\"external\"` variant allows them.\n */\ntype DataApiConfig = DataApiNeonAuthConfig | DataApiExternalAuthConfig;\n/**\n * How the Data API is toggled in a policy: a bare boolean (like the other service toggles)\n * or the richer {@link DataApiConfig} object. `true` / `{}` / `{ enabled: true }` enable it\n * with Neon defaults; `false` / `{ enabled: false }` opt out.\n */\ntype DataApiInput = boolean | DataApiConfig;\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 */\ninterface FunctionDevConfig {\n /**\n * Port the local server binds. Bound exactly (and `neon dev` fails loudly if it is taken)\n * when set; a free port is found automatically when omitted.\n */\n port?: number;\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/**\n * A single capability a branch-scoped service credential may exercise (Preview). A\n * credential is granted a set of these and may only perform the listed actions. Mirrors\n * the Neon API `CredentialScope` enum (`x-stability-level: beta`):\n *\n * - `storage:read` / `storage:write` — object-storage (bucket) access via the S3 key.\n * - `ai_gateway:invoke` — call the AI Gateway with the bearer `api_token`.\n * - `functions:invoke` — invoke Neon Functions with the bearer `api_token`.\n *\n * The set a policy needs is derived from its enabled Preview features (see\n * {@link deriveCredentialScopes}); it is never authored by hand.\n */\ntype CredentialScope = \"storage:read\" | \"storage:write\" | \"ai_gateway:invoke\" | \"functions:invoke\";\n/**\n * Who a credential acts as. `user` is the developer/app principal minted for local dev and\n * app bootstrap (`fetchEnv` / `env pull`); `function` is a deployed-function principal\n * (carries a `function_id`). The env tooling only mints `user` credentials today.\n */\ntype CredentialPrincipalType = \"user\" | \"function\";\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 DataApiInput | undefined = DataApiInput | undefined, Preview extends PreviewInput | undefined = PreviewInput | undefined> {\n /** Neon Auth integration toggle (GA). Static — drives `NeonEnv.auth`. */\n auth?: Auth;\n /**\n * Neon Data API integration (GA). Static — drives `NeonEnv.dataApi`. A boolean/toggle, or\n * a {@link DataApiConfig} object selecting the auth provider (`\"neon\"` / `\"external\"`) and\n * runtime {@link DataApiSettings}. With `authProvider: \"neon\"` the policy must also enable\n * top-level `auth`.\n */\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}\n/**\n * Normalized Data API integration. Present on {@link ResolvedBranchConfig} only when the\n * policy enables `dataApi`. `authProvider` always resolves (defaults to `\"neon\"`); the\n * external-IdP wiring is present only for `\"external\"`; `settings` carries the camelCase\n * runtime settings (reconciled as an update when they drift).\n */\ninterface ResolvedDataApiConfig {\n authProvider: DataApiAuthProvider;\n jwksUrl?: string;\n providerName?: string;\n jwtAudience?: string;\n settings?: DataApiSettings;\n}\ninterface ResolvedBranchConfig {\n parent?: string;\n ttlSeconds?: number;\n protected?: boolean;\n postgres?: PostgresConfig;\n authEnabled: boolean;\n dataApiEnabled: boolean;\n /**\n * Resolved Data API integration. Present iff {@link dataApiEnabled} is `true`. Carries the\n * create-time auth wiring and the updatable {@link DataApiSettings}.\n */\n dataApi?: ResolvedDataApiConfig;\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, CredentialPrincipalType, CredentialScope, DATA_API_AUTH_PROVIDERS, DataApiAuthProvider, DataApiConfig, DataApiExternalAuthConfig, DataApiInput, DataApiNeonAuthConfig, DataApiSettings, DurationString, DurationUnit, FunctionDef, FunctionDevConfig, FunctionRuntime, FunctionTuning, PostgresConfig, PreviewInput, PreviewTuning, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedDataApiConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceEnabled, ServiceToggle, ServiceToggleInput };\n//# sourceMappingURL=types.d.ts.map"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":["ComputeUnit","DurationUnit","DurationString","SuspendTimeoutSuggestion","TtlSuggestion","DurationField","Suggestions","NonNullable","ComputeSettings","BranchTarget","ServiceToggle","ServiceToggleInput","ServiceEnabled","T","PostgresConfig","DATA_API_AUTH_PROVIDERS","DataApiAuthProvider","DataApiSettings","DataApiConfigBase","DataApiNeonAuthConfig","DataApiExternalAuthConfig","DataApiConfig","DataApiInput","FunctionRuntime","FunctionDevConfig","FunctionDef","Record","CredentialScope","CredentialPrincipalType","BucketAccessLevel","BucketDef","PreviewInput","FunctionTuning","PreviewTuning","Slug","Partial","BranchTuning","FunctionSlugsOf","Preview","F","Extract","BranchTuningFn","Config","Auth","DataApi","ResolvedFunctionConfig","ResolvedBucketConfig","ResolvedPreviewConfig","ResolvedDataApiConfig","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 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 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: (branch) => … })` closure. 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;\n/**\n * Resolve a **static** service toggle (`true` / `false` / `{ enabled?: boolean }` / object /\n * `undefined`) to a type-level boolean. The tuple wrapping (`[T] extends […]`) disables\n * distribution so a union/`undefined` is judged as a single unit:\n *\n * - `false` / `{ enabled: false }` / `undefined` → `false`\n * - `true` / `{ enabled: true }` / any other object (`{}`, `{ enabled?: boolean }`) → `true`\n * (a present toggle defaults to enabled)\n * - the bare `boolean | … | undefined` (no literal info) → `false`\n *\n * Shared by the {@link Config} static cross-field checks and the `@neon/env`\n * `NeonEnv` namespace derivation, so both read \"is this service on?\" identically.\n */\ntype ServiceEnabled<T> = [T] extends [false] ? false : [T] extends [{\n enabled: false;\n}] ? false : [T] extends [undefined] ? false : [T] extends [true] ? true : [T] extends [{\n enabled: true;\n}] ? true : [T] extends [object] ? true : false;\ninterface PostgresConfig {\n computeSettings?: ComputeSettings;\n}\n/**\n * Authentication providers a Data API integration can verify JWTs against, as written in\n * `neon.ts`. Friendly authoring values (mapped to the Neon API's `neon_auth` / `external`\n * at the API boundary):\n *\n * - `\"neon\"` — verify tokens minted by **Neon Auth** on the same branch. Neon supplies the\n * JWKS URL / provider wiring for you, so the `jwksUrl` / `providerName` / `jwtAudience`\n * fields are forbidden (a type error) on this variant — and the policy must also enable\n * top-level `auth` (Neon Auth) so the tokens exist.\n * - `\"external\"` — verify tokens from a third-party IdP (Clerk, Stytch, Auth0, …). You\n * provide `jwksUrl` (and optionally `providerName` / `jwtAudience`).\n */\ndeclare const DATA_API_AUTH_PROVIDERS: readonly [\"neon\", \"external\"];\ntype DataApiAuthProvider = (typeof DATA_API_AUTH_PROVIDERS)[number];\n/**\n * Reusable runtime settings for a Data API integration (the Neon API `DataAPISettings`,\n * camelCased to match the rest of `neon.ts`). Every field is optional; omitted fields keep\n * the Neon defaults shown below. These are the **only** Data API fields that can change on\n * an already-enabled integration — drift here is reconciled as an *update* (requires\n * `updateExisting` / `--update-existing`); the create-only auth wiring above cannot.\n */\ninterface DataApiSettings {\n /** Enable the aggregates feature (`db_aggregates_enabled`). Default `true`. */\n dbAggregatesEnabled?: boolean;\n /** Database role used for anonymous requests (`db_anon_role`). Default `\"anonymous\"`. */\n dbAnonRole?: string;\n /** Extra schemas appended to the search path (`db_extra_search_path`). */\n dbExtraSearchPath?: string;\n /** Maximum rows returned in a single request (`db_max_rows`). */\n dbMaxRows?: number;\n /** Schemas exposed via the API (`db_schemas`). Default `[\"public\"]`. */\n dbSchemas?: string[];\n /** JWT claim key used for role extraction (`jwt_role_claim_key`). Default `\".role\"`. */\n jwtRoleClaimKey?: string;\n /** Maximum lifetime of the JWT cache, in seconds (`jwt_cache_max_lifetime`). */\n jwtCacheMaxLifetime?: number;\n /** OpenAPI spec mode (`openapi_mode`). Default `\"disabled\"`. */\n openapiMode?: \"ignore-privileges\" | \"disabled\";\n /** CORS allowed origins (`server_cors_allowed_origins`). */\n serverCorsAllowedOrigins?: string;\n /** Emit server-timing headers (`server_timing_enabled`). */\n serverTimingEnabled?: boolean;\n}\n/** Fields shared by every {@link DataApiConfig} variant. */\ninterface DataApiConfigBase {\n /** Defaults to `true` when the `dataApi` namespace is present. Set `false` to opt out. */\n enabled?: boolean;\n /** Reusable runtime settings. Drift here is reconciled as an update. */\n settings?: DataApiSettings;\n}\n/**\n * Data API verified by **Neon Auth** (`authProvider: \"neon\"`, the default). The external\n * IdP fields are statically forbidden (`?: never`) because Neon supplies them; declaring any\n * of them is a type error directing you to `authProvider: \"external\"`.\n */\ninterface DataApiNeonAuthConfig extends DataApiConfigBase {\n authProvider?: \"neon\";\n /** Forbidden with `authProvider: \"neon\"` — Neon provides the JWKS URL. */\n jwksUrl?: never;\n /** Forbidden with `authProvider: \"neon\"` — the provider is Neon Auth. */\n providerName?: never;\n /** Forbidden with `authProvider: \"neon\"` — Neon manages the audience. */\n jwtAudience?: never;\n}\n/**\n * Data API verified by an **external** IdP (`authProvider: \"external\"`). You provide the\n * JWKS URL (and optionally a provider label / expected audience).\n */\ninterface DataApiExternalAuthConfig extends DataApiConfigBase {\n authProvider: \"external\";\n /** URL that publishes the IdP's JWKS (JSON Web Key Set). */\n jwksUrl?: string;\n /** Human label for the IdP (e.g. \"Clerk\", \"Stytch\", \"Auth0\"). */\n providerName?: string;\n /**\n * Expected `aud` claim. ⚠️ This only **rejects** tokens carrying a *different* audience;\n * tokens with no `aud` claim are still accepted.\n */\n jwtAudience?: string;\n}\n/**\n * Object form of the `dataApi` toggle. A discriminated union on {@link DataApiAuthProvider}:\n * the `\"neon\"` variant forbids the external-IdP fields, the `\"external\"` variant allows them.\n */\ntype DataApiConfig = DataApiNeonAuthConfig | DataApiExternalAuthConfig;\n/**\n * How the Data API is toggled in a policy: a bare boolean (like the other service toggles)\n * or the richer {@link DataApiConfig} object. `true` / `{}` / `{ enabled: true }` enable it\n * with Neon defaults; `false` / `{ enabled: false }` opt out.\n */\ntype DataApiInput = boolean | DataApiConfig;\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 */\ninterface FunctionDevConfig {\n /**\n * Port the local server binds. Bound exactly (and `neon dev` fails loudly if it is taken)\n * when set; a free port is found automatically when omitted.\n */\n port?: number;\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 * Packages the bundler must leave alone, by name — the deploy-time equivalent of\n * Next.js's `serverExternalPackages`. Every entry is passed to esbuild's `external`,\n * so the import survives into the bundle instead of being followed.\n *\n * Reach for this when bundling a package is impossible rather than merely undesirable.\n * The cases that come up: a native `.node` addon or a `node-gyp` dependency esbuild has\n * no loader for, and an optional peer dependency a library references on a code path\n * this function never takes. Both fail the deploy at bundle time with a resolve or\n * loader error naming the package, and neither is fixable from the function's own\n * source.\n *\n * **An external package is not resolvable at runtime.** The deployed archive is a\n * single `index.mjs` with no `node_modules` beside it, so anything listed here throws\n * `Cannot find module` if the function actually reaches it. This option therefore only\n * unblocks an import that is never evaluated; it does not make a dependency usable.\n *\n * A dependency the handler actually calls has to be bundled, and whether that is\n * possible depends on what it is. A pure-JavaScript package can be bundled, and a\n * failure to do so is usually something specific and fixable. A package backed by a\n * native `.node` binary cannot be bundled by anything — the binary is a compiled\n * object the platform loads from a real path — so such a package cannot work on\n * Functions until the deployed archive can carry files alongside the bundle. Do not\n * reach for `externalPackages` to try: it moves the error from deploy to invoke.\n *\n * Note that a native package may bundle without ever needing this option. `sharp`, for\n * instance, loads its binary through `createRequire`, which esbuild does not follow, so\n * it bundles cleanly and then fails at invoke with \"Could not load the sharp module\".\n *\n * Entries are package names, optionally with a subpath (`pkg`, `@scope/pkg`,\n * `pkg/sub`), matching esbuild. A relative or absolute path is rejected at validation\n * time: those are local modules, and a local module that cannot be bundled is a\n * different problem.\n * @example [\"microsandbox\", \"@mongodb-js/zstd\"]\n */\n externalPackages?: 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/**\n * A single capability a branch-scoped service credential may exercise (Preview). A\n * credential is granted a set of these and may only perform the listed actions. Mirrors\n * the Neon API `CredentialScope` enum (`x-stability-level: beta`):\n *\n * - `storage:read` / `storage:write` — object-storage (bucket) access via the S3 key.\n * - `ai_gateway:invoke` — call the AI Gateway with the bearer `api_token`.\n * - `functions:invoke` — invoke Neon Functions with the bearer `api_token`.\n *\n * The set a policy needs is derived from its enabled Preview features (see\n * {@link deriveCredentialScopes}); it is never authored by hand.\n */\ntype CredentialScope = \"storage:read\" | \"storage:write\" | \"ai_gateway:invoke\" | \"functions:invoke\";\n/**\n * Who a credential acts as. `user` is the developer/app principal minted for local dev and\n * app bootstrap (`fetchEnv` / `env pull`); `function` is a deployed-function principal\n * (carries a `function_id`). The env tooling only mints `user` credentials today.\n */\ntype CredentialPrincipalType = \"user\" | \"function\";\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 DataApiInput | undefined = DataApiInput | undefined, Preview extends PreviewInput | undefined = PreviewInput | undefined> {\n /** Neon Auth integration toggle (GA). Static — drives `NeonEnv.auth`. */\n auth?: Auth;\n /**\n * Neon Data API integration (GA). Static — drives `NeonEnv.dataApi`. A boolean/toggle, or\n * a {@link DataApiConfig} object selecting the auth provider (`\"neon\"` / `\"external\"`) and\n * runtime {@link DataApiSettings}. With `authProvider: \"neon\"` the policy must also enable\n * top-level `auth`.\n */\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 /**\n * Packages the bundler leaves unresolved, passed through from\n * {@link FunctionDef.externalPackages}. Absent rather than empty when undeclared, so a\n * policy that never mentions it resolves to the same shape it always did.\n */\n externalPackages?: 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}\n/**\n * Normalized Data API integration. Present on {@link ResolvedBranchConfig} only when the\n * policy enables `dataApi`. `authProvider` always resolves (defaults to `\"neon\"`); the\n * external-IdP wiring is present only for `\"external\"`; `settings` carries the camelCase\n * runtime settings (reconciled as an update when they drift).\n */\ninterface ResolvedDataApiConfig {\n authProvider: DataApiAuthProvider;\n jwksUrl?: string;\n providerName?: string;\n jwtAudience?: string;\n settings?: DataApiSettings;\n}\ninterface ResolvedBranchConfig {\n parent?: string;\n ttlSeconds?: number;\n protected?: boolean;\n postgres?: PostgresConfig;\n authEnabled: boolean;\n dataApiEnabled: boolean;\n /**\n * Resolved Data API integration. Present iff {@link dataApiEnabled} is `true`. Carries the\n * create-time auth wiring and the updatable {@link DataApiSettings}.\n */\n dataApi?: ResolvedDataApiConfig;\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, CredentialPrincipalType, CredentialScope, DATA_API_AUTH_PROVIDERS, DataApiAuthProvider, DataApiConfig, DataApiExternalAuthConfig, DataApiInput, DataApiNeonAuthConfig, DataApiSettings, DurationString, DurationUnit, FunctionDef, FunctionDevConfig, FunctionRuntime, FunctionTuning, PostgresConfig, PreviewInput, PreviewTuning, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedDataApiConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceEnabled, ServiceToggle, ServiceToggleInput };\n//# sourceMappingURL=types.d.ts.map"],"mappings":"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"}
|
|
@@ -12,7 +12,8 @@ interface CommandEnv {
|
|
|
12
12
|
cwd: string;
|
|
13
13
|
/**
|
|
14
14
|
* When set, used directly as the NeonApi. When omitted, the real adapter is built from
|
|
15
|
-
* `
|
|
15
|
+
* the key {@link resolveApiKey} resolves (`--api-key` → `NEON_API_KEY` → the Neon CLI's
|
|
16
|
+
* stored credentials).
|
|
16
17
|
*/
|
|
17
18
|
api?: NeonApi;
|
|
18
19
|
}
|
|
@@ -28,8 +29,9 @@ interface CommandResult {
|
|
|
28
29
|
}
|
|
29
30
|
/**
|
|
30
31
|
* 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
|
|
32
|
-
*
|
|
32
|
+
* optional explicit `neon.ts` path, project/branch overrides, and an API key. Everything
|
|
33
|
+
* ambient — `.neon`, `NEON_*` env, the Neon CLI's stored credentials — is resolved by the
|
|
34
|
+
* CLI (see `resolveContext` and `resolveApiKey`), never by the library.
|
|
33
35
|
*/
|
|
34
36
|
interface EnvResolveOptions {
|
|
35
37
|
configPath?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","names":[],"sources":["../../../src/lib/cli/commands.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"commands.d.ts","names":[],"sources":["../../../src/lib/cli/commands.ts"],"mappings":";;;;;;;;AAuBA;AAUA;AAiBiB,UA3BA,UAAA,CA2BiB;EAOjB,GAAA,EAAA,MAAA;EAWK;AAAS;AACrB;AACJ;AACK;EAAR,GAAA,CAAA,EAzCI,OAyCJ;AAAO;AA2CO,UAjFA,aAAA,CAiFwB;EAWnB;EAAY,QAAA,EAAA,MAAA;EACxB;EACJ,MAAA,EAAA,MAAA;EACK;EAAR,MAAA,EAAA,MAAA;EAAO;;;;;;;;;UA9EO,iBAAA;;;;;;UAOA,oBAAA,SAA6B;;;;;;;;;;iBAWxB,SAAA,UACZ,2BACJ,aACH,QAAQ;UA2CM,uBAAA,SAAgC;;;;;;;;;;iBAW3B,YAAA,UACZ,8BACJ,aACH,QAAQ"}
|
package/dist/lib/cli/commands.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fetchEnvReusingSecrets } from "../reuse-secrets.js";
|
|
2
|
+
import { resolveApiKey } from "./resolve-api-key.js";
|
|
2
3
|
import { resolveContext } from "./resolve-context.js";
|
|
3
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
5
|
import { spawn } from "node:child_process";
|
|
@@ -97,6 +98,7 @@ async function loadConfigAndFetchEnv(options, ctx, resolved) {
|
|
|
97
98
|
});
|
|
98
99
|
const envFileSource = join(dirname(resolvedPath), DEFAULT_ENV_FILE);
|
|
99
100
|
const fileEnv = existsSync(envFileSource) ? parseEnvFile(readFileSync(envFileSource, "utf-8")) : {};
|
|
101
|
+
const apiKey = resolveApiKey({ ...options.apiKey ? { apiKey: options.apiKey } : {} });
|
|
100
102
|
const { vars } = await fetchEnvReusingSecrets(config, {
|
|
101
103
|
projectId: resolved.projectId,
|
|
102
104
|
branch: resolved.branch,
|
|
@@ -105,7 +107,7 @@ async function loadConfigAndFetchEnv(options, ctx, resolved) {
|
|
|
105
107
|
...fileEnv
|
|
106
108
|
},
|
|
107
109
|
...ctx.api ? { api: ctx.api } : {},
|
|
108
|
-
...
|
|
110
|
+
...apiKey ? { apiKey } : {}
|
|
109
111
|
});
|
|
110
112
|
return vars;
|
|
111
113
|
}
|
|
@@ -180,6 +182,12 @@ const EXIT_CODE_BY_PLATFORM_ERROR_CODE = {
|
|
|
180
182
|
function handleError(err) {
|
|
181
183
|
if (err instanceof MissingContextError) return errorResult(err, `Missing context: ${err.message}`, 3);
|
|
182
184
|
if (err instanceof ConfigLoadError) return errorResult(err, `Failed to load config: ${err.message}`, 4);
|
|
185
|
+
if (err instanceof PlatformError && err.code === ErrorCode.MissingApiKey) return errorResult(err, [
|
|
186
|
+
"No Neon API key. `neon-env` looks for one in this order:",
|
|
187
|
+
" - the `--api-key` flag",
|
|
188
|
+
" - the `NEON_API_KEY` environment variable",
|
|
189
|
+
" - `credentials.json` in `NEONCTL_CONFIG_DIR` (else `~/.config/neonctl`) — run `neon auth` to create it"
|
|
190
|
+
].join("\n"), EXIT_CODE_BY_PLATFORM_ERROR_CODE[ErrorCode.MissingApiKey] ?? 1);
|
|
183
191
|
if (err instanceof PlatformError) {
|
|
184
192
|
const exitCode = EXIT_CODE_BY_PLATFORM_ERROR_CODE[err.code];
|
|
185
193
|
if (exitCode !== void 0) return errorResult(err, err.message, exitCode);
|
|
@@ -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 \"@neon/config/v1\";\nimport { fetchEnvReusingSecrets } from \"../reuse-secrets.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\tinjected = await loadConfigAndFetchEnv(options, ctx, resolved.context);\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\tentries = await loadConfigAndFetchEnv(options, ctx, resolved.context);\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 resolve the branch env for the explicitly-resolved project + branch.\n * Layers `.env.local` (next to the config file) into the env source so re-runs keep the\n * one-time secrets the Neon API only returns once — the branch credential's, and any Auth\n * values a pre-`base_url` integration can no longer report. Uses\n * {@link fetchEnvReusingSecrets} rather than a bare `fetchEnv` so a run that already has a\n * working credential verifies and keeps it instead of minting another one per invocation.\n */\nasync function loadConfigAndFetchEnv(\n\toptions: EnvResolveOptions,\n\tctx: CommandEnv,\n\tresolved: { projectId: string; branch: string },\n): Promise<Record<string, string>> {\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\tconst { vars } = await fetchEnvReusingSecrets(config, {\n\t\tprojectId: resolved.projectId,\n\t\tbranch: resolved.branch,\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\treturn vars;\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":";;;;;;;;AAeA,MAAM,mBAAmB;;;;;;;AAkDzB,eAAsB,UACrB,SACA,KACyB;CACzB,IAAI,QAAQ,QAAQ,WAAW,GAC9B,OAAO,QACN;EACC;EACA;EACA;CACD,CAAC,CAAC,KAAK,IAAI,CACZ;CAKD,MAAM,WAAW,eAAe;EAC/B,KAAK,IAAI;EACT,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;EAC5D,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;CACpD,CAAC;CACD,IAAI,CAAC,SAAS,IACb,OAAO,QACN,CACC,4DACA,GAAG,SAAS,QAAQ,KAAK,MAAM,OAAO,GAAG,CAC1C,CAAC,CAAC,KAAK,IAAI,GACX,CACD;CAGD,IAAI;CACJ,IAAI;EACH,WAAW,MAAM,sBAAsB,SAAS,KAAK,SAAS,OAAO;CACtE,SAAS,KAAK;EACb,OAAO,YAAY,GAAG;CACvB;CAEA,MAAM,CAAC,YAAY,GAAG,QAAQ,QAAQ;CAKtC,OAAO;EAAE,UAAA,MAJc,aAAa,YAAY,MAAM;GACrD,KAAK,IAAI;GACT,KAAK;IAAE,GAAG,QAAQ;IAAK,GAAG;GAAS;EACpC,CAAC;EACkB,QAAQ;EAAI,QAAQ;CAAG;AAC3C;;;;;;;AAaA,eAAsB,aACrB,SACA,KACyB;CACzB,MAAM,WAAW,eAAe;EAC/B,KAAK,IAAI;EACT,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;EAC5D,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;CACpD,CAAC;CACD,IAAI,CAAC,SAAS,IACb,OAAO,QACN,CACC,+DACA,GAAG,SAAS,QAAQ,KAAK,MAAM,OAAO,GAAG,CAC1C,CAAC,CAAC,KAAK,IAAI,GACX,CACD;CAGD,IAAI;CACJ,IAAI;EACH,UAAU,MAAM,sBAAsB,SAAS,KAAK,SAAS,OAAO;CACrE,SAAS,KAAK;EACb,OAAO,YAAY,GAAG;CACvB;CAMA,OAAO;EAAE,UAAU;EAAG,QAHrB,QAAQ,WAAW,SAChB,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,MACpC,SAAS,OAAO;EACU,QAAQ;CAAG;AAC1C;;AAGA,SAAS,SAAS,SAAyC;CAC1D,MAAM,QAAQ,OAAO,QAAQ,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,WAChD,iBAAiB,KAAK,KAAK,CAC5B;CACA,OAAO,MAAM,SAAS,IAAI,GAAG,MAAM,KAAK,IAAI,EAAE,MAAM;AACrD;;;;;AAMA,SAAS,iBAAiB,KAAa,OAAuB;CAC7D,IAAI,CAAC,WAAW,KAAK,KAAK,GAAG,OAAO,GAAG,IAAI,GAAG;CAE9C,OAAO,GAAG,IAAI,IADE,MAAM,QAAQ,OAAO,MAAM,CAAC,CAAC,QAAQ,MAAM,MACnC,EAAE;AAC3B;;;;;;;;;AAUA,eAAe,sBACd,SACA,KACA,UACkC;CAClC,MAAM,EAAE,QAAQ,iBAAiB,MAAM,mBAAmB;EACzD,GAAI,QAAQ,aAAa,EAAE,MAAM,QAAQ,WAAW,IAAI,CAAC;EACzD,KAAK,IAAI;CACV,CAAC;CACD,MAAM,gBAAgB,KAAK,QAAQ,YAAY,GAAG,gBAAgB;CAClE,MAAM,UAAU,WAAW,aAAa,IACrC,aAAa,aAAa,eAAe,OAAO,CAAC,IACjD,CAAC;CACJ,MAAM,EAAE,SAAS,MAAM,uBAAuB,QAAQ;EACrD,WAAW,SAAS;EACpB,QAAQ,SAAS;EACjB,KAAK;GAAE,GAAG,QAAQ;GAAK,GAAG;EAAQ;EAClC,GAAI,IAAI,MAAM,EAAE,KAAK,IAAI,IAAI,IAAI,CAAC;EAClC,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;CACpD,CAAC;CACD,OAAO;AACR;;;;;;AAOA,SAAS,aACR,SACA,MACA,SACkB;CAClB,OAAO,IAAI,SAAS,YAAY;EAC/B,MAAM,QAAQ,MAAM,SAAS,MAAM;GAClC,KAAK,QAAQ;GACb,KAAK,QAAQ;GACb,OAAO;EACR,CAAC;EACD,MAAM,GAAG,UAAU,QAAQ;GAC1B,QAAQ,OAAO,MACd,kCAAkC,QAAQ,KAAK,IAAI,QAAQ,GAC5D;GACA,QAAQ,CAAC;EACV,CAAC;EACD,MAAM,GAAG,SAAS,MAAM,WAAW;GAClC,IAAI,OAAO,SAAS,UAAU;IAC7B,QAAQ,IAAI;IACZ;GACD;GACA,IAAI,QAAQ;IACX,QAAQ,OAAO,MACd,4CAA4C,OAAO,GACpD;IACA,QAAQ,CAAC;IACT;GACD;GACA,QAAQ,CAAC;EACV,CAAC;CACF,CAAC;AACF;AAEA,SAAS,aAAa,MAAiC;CACtD,MAAM,MAAyB,CAAC;CAChC,KAAK,MAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;EACpC,MAAM,SAAS,aAAa,IAAI;EAChC,IAAI,QAAQ,IAAI,OAAO,OAAO,OAAO;CACtC;CACA,OAAO;AACR;AAEA,SAAS,aAAa,MAAqD;CAC1E,MAAM,QAAQ,KAAK,MAClB,wDACD;CACA,MAAM,MAAM,QAAQ;CACpB,MAAM,WAAW,QAAQ;CACzB,IAAI,QAAQ,KAAA,KAAa,aAAa,KAAA,GAAW,OAAO;CACxD,OAAO;EAAE;EAAK,OAAO,iBAAiB,SAAS,KAAK,CAAC;CAAE;AACxD;AAEA,SAAS,iBAAiB,OAAuB;CAChD,IAAI,MAAM,UAAU,KAAK,MAAM,WAAW,IAAG,KAAK,MAAM,SAAS,IAAG,GACnE,OAAO,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC,QAAQ,QAAQ,IAAG,CAAC,CAAC,QAAQ,SAAS,IAAI;CAErE,IAAI,MAAM,UAAU,KAAK,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GACnE,OAAO,MAAM,MAAM,GAAG,EAAE;CAEzB,OAAO;AACR;;;;;AAMA,MAAM,mCAAqE;EACzE,UAAU,gBAAgB;EAC1B,UAAU,eAAe;EACzB,UAAU,YAAY;EACtB,UAAU,WAAW;EACrB,UAAU,cAAc;EACxB,UAAU,eAAe;EACzB,UAAU,cAAc;EACxB,UAAU,SAAS;EACnB,UAAU,gBAAgB;AAC5B;AAEA,SAAS,YAAY,KAA6B;CACjD,IAAI,eAAe,qBAClB,OAAO,YAAY,KAAK,oBAAoB,IAAI,WAAW,CAAC;CAC7D,IAAI,eAAe,iBAClB,OAAO,YAAY,KAAK,0BAA0B,IAAI,WAAW,CAAC;CACnE,IAAI,eAAe,eAAe;EACjC,MAAM,WAAW,iCAAiC,IAAI;EACtD,IAAI,aAAa,KAAA,GAChB,OAAO,YAAY,KAAK,IAAI,SAAS,QAAQ;EAC9C,OAAO,YAAY,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,WAAW,CAAC;CAC1D;CACA,IAAI,eAAe,OAAO,OAAO,YAAY,KAAK,IAAI,SAAS,CAAC;CAChE,OAAO,QAAQ,OAAO,GAAG,GAAG,CAAC;AAC9B;AAEA,SAAS,YACR,KACA,SACA,UACgB;CAChB,MAAM,SAAwB;EAC7B;EACA,QAAQ;EACR,QAAQ,GAAG,QAAQ;CACpB;CACA,MAAM,QAAQ,eAAe,GAAG;CAChC,IAAI,OAAO,OAAO,YAAY;CAC9B,OAAO;AACR;AAEA,SAAS,eAAe,KAAkC;CACzD,IAAI,EAAE,eAAe,QAAQ,OAAO,KAAA;CACpC,MAAM,QAAkB,CAAC;CACzB,IAAI,eAAe,eAAe;EACjC,MAAM,KAAK,cAAc,IAAI,MAAM;EACnC,IAAI,OAAO,KAAK,IAAI,OAAO,CAAC,CAAC,SAAS,GACrC,MAAM,KAAK,cAAc,KAAK,UAAU,IAAI,SAAS,MAAM,CAAC,GAAG;CAEjE;CACA,IAAI,IAAI,iBAAiB,OACxB,MAAM,KAAK,cAAc,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,SAAS;CAEhE,IAAI,IAAI,OACP,MAAM,KAAK,IAAI,KAAK;CAErB,OAAO,MAAM,SAAS,IAAI,MAAM,KAAK,IAAI,IAAI,KAAA;AAC9C;AAEA,SAAS,QAAQ,SAAiB,WAAW,GAAkB;CAC9D,OAAO;EAAE;EAAU,QAAQ;EAAI,QAAQ,GAAG,QAAQ;CAAI;AACvD"}
|
|
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 \"@neon/config/v1\";\nimport { fetchEnvReusingSecrets } from \"../reuse-secrets.js\";\nimport { resolveApiKey } from \"./resolve-api-key.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 * the key {@link resolveApiKey} resolves (`--api-key` → `NEON_API_KEY` → the Neon CLI's\n\t * stored credentials).\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. Everything\n * ambient — `.neon`, `NEON_*` env, the Neon CLI's stored credentials — is resolved by the\n * CLI (see `resolveContext` and `resolveApiKey`), never by the library.\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\tinjected = await loadConfigAndFetchEnv(options, ctx, resolved.context);\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\tentries = await loadConfigAndFetchEnv(options, ctx, resolved.context);\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 resolve the branch env for the explicitly-resolved project + branch.\n * Layers `.env.local` (next to the config file) into the env source so re-runs keep the\n * one-time secrets the Neon API only returns once — the branch credential's, and any Auth\n * values a pre-`base_url` integration can no longer report. Uses\n * {@link fetchEnvReusingSecrets} rather than a bare `fetchEnv` so a run that already has a\n * working credential verifies and keeps it instead of minting another one per invocation.\n */\nasync function loadConfigAndFetchEnv(\n\toptions: EnvResolveOptions,\n\tctx: CommandEnv,\n\tresolved: { projectId: string; branch: string },\n): Promise<Record<string, string>> {\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\tconst apiKey = resolveApiKey({\n\t\t...(options.apiKey ? { apiKey: options.apiKey } : {}),\n\t});\n\tconst { vars } = await fetchEnvReusingSecrets(config, {\n\t\tprojectId: resolved.projectId,\n\t\tbranch: resolved.branch,\n\t\tenv: { ...process.env, ...fileEnv },\n\t\t...(ctx.api ? { api: ctx.api } : {}),\n\t\t...(apiKey ? { apiKey } : {}),\n\t});\n\treturn vars;\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\t// The library's own wording is right for a library (\"this package never reads\n\t// NEON_API_KEY on your behalf\") and wrong here: `neon-env` does read it. Render the\n\t// chain this CLI actually implements, the same way an unresolved context is rendered.\n\tif (err instanceof PlatformError && err.code === ErrorCode.MissingApiKey) {\n\t\treturn errorResult(\n\t\t\terr,\n\t\t\t[\n\t\t\t\t\"No Neon API key. `neon-env` looks for one in this order:\",\n\t\t\t\t\" - the `--api-key` flag\",\n\t\t\t\t\" - the `NEON_API_KEY` environment variable\",\n\t\t\t\t\" - `credentials.json` in `NEONCTL_CONFIG_DIR` (else `~/.config/neonctl`) — run `neon auth` to create it\",\n\t\t\t].join(\"\\n\"),\n\t\t\tEXIT_CODE_BY_PLATFORM_ERROR_CODE[ErrorCode.MissingApiKey] ?? 1,\n\t\t);\n\t}\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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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/lib/cli/resolve-api-key.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the Neon API key for a `neon-env` CLI invocation. Precedence (each wins over the
|
|
4
|
+
* next): `--api-key` flag → `NEON_API_KEY` → `access_token` from the Neon CLI's
|
|
5
|
+
* `credentials.json`.
|
|
6
|
+
*
|
|
7
|
+
* The CLI owns this resolution — `@neon/config` and `@neon/env` are deliberately
|
|
8
|
+
* environment- and filesystem-agnostic and only ever accept an explicit `apiKey`, so the
|
|
9
|
+
* ambient sources a *user* expects have to be read here. This mirrors `resolveContext`,
|
|
10
|
+
* which does the same for project and branch.
|
|
11
|
+
*
|
|
12
|
+
* Returns `undefined` rather than throwing when nothing provides a key: the caller passes
|
|
13
|
+
* it straight through, and the library raises the uniform `PLATFORM_MISSING_API_KEY` error.
|
|
14
|
+
*/
|
|
15
|
+
declare function resolveApiKey(options: {
|
|
16
|
+
apiKey?: string;
|
|
17
|
+
env?: NodeJS.ProcessEnv;
|
|
18
|
+
}): string | undefined;
|
|
19
|
+
//#endregion
|
|
20
|
+
export { resolveApiKey };
|
|
21
|
+
//# sourceMappingURL=resolve-api-key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-api-key.d.ts","names":[],"sources":["../../../src/lib/cli/resolve-api-key.ts"],"mappings":";;AAgBA;;;;;;;;;;;;iBAAgB,aAAA;;QAET,MAAA,CAAO"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
//#region src/lib/cli/resolve-api-key.ts
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the Neon API key for a `neon-env` CLI invocation. Precedence (each wins over the
|
|
6
|
+
* next): `--api-key` flag → `NEON_API_KEY` → `access_token` from the Neon CLI's
|
|
7
|
+
* `credentials.json`.
|
|
8
|
+
*
|
|
9
|
+
* The CLI owns this resolution — `@neon/config` and `@neon/env` are deliberately
|
|
10
|
+
* environment- and filesystem-agnostic and only ever accept an explicit `apiKey`, so the
|
|
11
|
+
* ambient sources a *user* expects have to be read here. This mirrors `resolveContext`,
|
|
12
|
+
* which does the same for project and branch.
|
|
13
|
+
*
|
|
14
|
+
* Returns `undefined` rather than throwing when nothing provides a key: the caller passes
|
|
15
|
+
* it straight through, and the library raises the uniform `PLATFORM_MISSING_API_KEY` error.
|
|
16
|
+
*/
|
|
17
|
+
function resolveApiKey(options) {
|
|
18
|
+
const env = options.env ?? process.env;
|
|
19
|
+
return nonEmpty(options.apiKey) ?? nonEmpty(env.NEON_API_KEY) ?? readStoredAccessToken(env);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Read `access_token` from the Neon CLI's credentials file, the same location and
|
|
23
|
+
* precedence `neon auth` writes to: `NEONCTL_CONFIG_DIR` → `<home>/.config/neonctl`
|
|
24
|
+
* (`HOME`, falling back to `USERPROFILE` for Windows parity).
|
|
25
|
+
*
|
|
26
|
+
* Never throws — a missing, unreadable, malformed, or token-less file is simply "no key",
|
|
27
|
+
* so this can sit in a resolution chain without try/catch noise.
|
|
28
|
+
*/
|
|
29
|
+
function readStoredAccessToken(env) {
|
|
30
|
+
const home = env.HOME ?? env.USERPROFILE;
|
|
31
|
+
const configDir = nonEmpty(env.NEONCTL_CONFIG_DIR) ?? (home ? resolve(home, ".config", "neonctl") : void 0);
|
|
32
|
+
if (!configDir) return void 0;
|
|
33
|
+
const credentialsPath = resolve(configDir, "credentials.json");
|
|
34
|
+
if (!existsSync(credentialsPath)) return void 0;
|
|
35
|
+
let parsed;
|
|
36
|
+
try {
|
|
37
|
+
parsed = JSON.parse(readFileSync(credentialsPath, "utf-8"));
|
|
38
|
+
} catch {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
42
|
+
return nonEmpty(parsed.access_token);
|
|
43
|
+
}
|
|
44
|
+
function nonEmpty(value) {
|
|
45
|
+
if (typeof value !== "string") return void 0;
|
|
46
|
+
const trimmed = value.trim();
|
|
47
|
+
return trimmed === "" ? void 0 : trimmed;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { resolveApiKey };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=resolve-api-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-api-key.js","names":[],"sources":["../../../src/lib/cli/resolve-api-key.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\n/**\n * Resolve the Neon API key for a `neon-env` CLI invocation. Precedence (each wins over the\n * next): `--api-key` flag → `NEON_API_KEY` → `access_token` from the Neon CLI's\n * `credentials.json`.\n *\n * The CLI owns this resolution — `@neon/config` and `@neon/env` are deliberately\n * environment- and filesystem-agnostic and only ever accept an explicit `apiKey`, so the\n * ambient sources a *user* expects have to be read here. This mirrors `resolveContext`,\n * which does the same for project and branch.\n *\n * Returns `undefined` rather than throwing when nothing provides a key: the caller passes\n * it straight through, and the library raises the uniform `PLATFORM_MISSING_API_KEY` error.\n */\nexport function resolveApiKey(options: {\n\tapiKey?: string;\n\tenv?: NodeJS.ProcessEnv;\n}): string | undefined {\n\tconst env = options.env ?? process.env;\n\treturn (\n\t\tnonEmpty(options.apiKey) ??\n\t\tnonEmpty(env.NEON_API_KEY) ??\n\t\treadStoredAccessToken(env)\n\t);\n}\n\n/**\n * Read `access_token` from the Neon CLI's credentials file, the same location and\n * precedence `neon auth` writes to: `NEONCTL_CONFIG_DIR` → `<home>/.config/neonctl`\n * (`HOME`, falling back to `USERPROFILE` for Windows parity).\n *\n * Never throws — a missing, unreadable, malformed, or token-less file is simply \"no key\",\n * so this can sit in a resolution chain without try/catch noise.\n */\nfunction readStoredAccessToken(env: NodeJS.ProcessEnv): string | undefined {\n\tconst home = env.HOME ?? env.USERPROFILE;\n\tconst configDir =\n\t\tnonEmpty(env.NEONCTL_CONFIG_DIR) ??\n\t\t(home ? resolve(home, \".config\", \"neonctl\") : undefined);\n\tif (!configDir) return undefined;\n\n\tconst credentialsPath = resolve(configDir, \"credentials.json\");\n\tif (!existsSync(credentialsPath)) return undefined;\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(readFileSync(credentialsPath, \"utf-8\"));\n\t} catch {\n\t\treturn undefined;\n\t}\n\n\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed))\n\t\treturn undefined;\n\treturn nonEmpty((parsed as Record<string, unknown>).access_token as string);\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":";;;;;;;;;;;;;;;;AAgBA,SAAgB,cAAc,SAGP;CACtB,MAAM,MAAM,QAAQ,OAAO,QAAQ;CACnC,OACC,SAAS,QAAQ,MAAM,KACvB,SAAS,IAAI,YAAY,KACzB,sBAAsB,GAAG;AAE3B;;;;;;;;;AAUA,SAAS,sBAAsB,KAA4C;CAC1E,MAAM,OAAO,IAAI,QAAQ,IAAI;CAC7B,MAAM,YACL,SAAS,IAAI,kBAAkB,MAC9B,OAAO,QAAQ,MAAM,WAAW,SAAS,IAAI,KAAA;CAC/C,IAAI,CAAC,WAAW,OAAO,KAAA;CAEvB,MAAM,kBAAkB,QAAQ,WAAW,kBAAkB;CAC7D,IAAI,CAAC,WAAW,eAAe,GAAG,OAAO,KAAA;CAEzC,IAAI;CACJ,IAAI;EACH,SAAS,KAAK,MAAM,aAAa,iBAAiB,OAAO,CAAC;CAC3D,QAAQ;EACP;CACD;CAEA,IAAI,WAAW,QAAQ,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GACxE,OAAO,KAAA;CACR,OAAO,SAAU,OAAmC,YAAsB;AAC3E;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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neondatabase/env",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Resolve and inject Neon connection strings for the branch selected by your neon.ts policy. fetchEnv / parseEnv plus a `neon-env` CLI with `run` and `export`.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"zod": "^4.4.3",
|
|
58
58
|
"yargs": "^18.0.0",
|
|
59
|
-
"@neon/config": "0.
|
|
59
|
+
"@neon/config": "0.12.0"
|
|
60
60
|
},
|
|
61
61
|
"engines": {
|
|
62
62
|
"node": ">=20.19.0"
|