@neondatabase/config 0.4.2 → 0.7.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.
@@ -1 +1 @@
1
- {"version":3,"file":"neon-api-real.js","names":[],"sources":["../../src/lib/neon-api-real.ts"],"sourcesContent":["import {\n\ttype Branch,\n\ttype BranchCreateRequest,\n\ttype BranchCreateRequestEndpointOptions,\n\ttype BranchUpdateRequest,\n\tcreateApiClient,\n\ttype Database,\n\ttype DefaultEndpointSettings,\n\ttype Endpoint,\n\tEndpointType,\n\ttype EndpointUpdateRequest,\n\ttype PgVersion,\n\ttype Project,\n\ttype ProjectCreateRequest,\n\ttype ProjectListItem,\n\ttype ProjectUpdateRequest,\n\ttype Role,\n} from \"@neondatabase/api-client\";\nimport { z } from \"zod\";\nimport { formatSuspendTimeout, parseSuspendTimeout } from \"./duration.js\";\nimport { ErrorCode, PlatformError } from \"./errors.js\";\nimport type {\n\tCreateBranchInput,\n\tCreateBucketInput,\n\tCreateProjectInput,\n\tDeployFunctionInput,\n\tGetConnectionUriInput,\n\tNeonApi,\n\tNeonAuthSnapshot,\n\tNeonBranchSnapshot,\n\tNeonBucketSnapshot,\n\tNeonDataApiSnapshot,\n\tNeonDatabaseSnapshot,\n\tNeonEndpointSnapshot,\n\tNeonFunctionDeploymentSnapshot,\n\tNeonFunctionSnapshot,\n\tNeonProjectSnapshot,\n\tNeonRoleSnapshot,\n\tUpdateBranchInput,\n} from \"./neon-api.js\";\nimport type { BucketAccessLevel, ComputeSettings } from \"./types.js\";\nimport { wrapNeonError } from \"./wrap-neon-error.js\";\n\ntype ApiClient = ReturnType<typeof createApiClient>;\nconst DEFAULT_NEON_API_BASE_URL = \"https://console.neon.tech/api/v2\";\n\nconst neonAuthResponseSchema = z.object({\n\tauth_provider_project_id: z.string(),\n\tpub_client_key: z.string().optional(),\n\tsecret_server_key: z.string().optional(),\n\tjwks_url: z.string(),\n\tbase_url: z.string().optional(),\n});\n\n// ─── Preview: buckets ──────────────────────────────────────────────────────\n\nconst bucketSchema = z.object({\n\tname: z.string(),\n\taccess_level: z.string().optional(),\n});\nconst bucketResponseSchema = z.object({ bucket: bucketSchema });\nconst bucketsListResponseSchema = z.object({ buckets: z.array(bucketSchema) });\n\n// ─── Preview: functions ────────────────────────────────────────────────────\n\nconst functionDeploymentSchema = z.object({\n\tid: z.number(),\n\tstatus: z.string(),\n});\nconst neonFunctionSchema = z.object({\n\tid: z.string(),\n\tslug: z.string(),\n\tname: z.string(),\n\tinvocation_url: z.string(),\n\tactive_deployment: functionDeploymentSchema.optional(),\n});\nconst functionResponseSchema = z.object({ function: neonFunctionSchema });\nconst functionsListResponseSchema = z.object({\n\tfunctions: z.array(neonFunctionSchema),\n});\nconst functionDeploymentResponseSchema = z.object({\n\tdeployment: functionDeploymentSchema,\n});\n\ninterface CreateNeonAuthRestInput {\n\tauth_provider: \"better_auth\";\n\tdatabase_name?: string;\n}\n\ninterface RestConfig {\n\tapiKey: string;\n\tbaseUrl: string;\n}\n\n/**\n * Adapt `@neondatabase/api-client` to the narrow {@link NeonApi} façade used by the rest of\n * this package. Constructs are restricted to whole-object read/write of just the fields we\n * model in {@link Config}; anything else stays untouched on the remote.\n */\nexport function createRealNeonApi(options: {\n\tapiKey: string;\n\tbaseUrl?: string;\n\t/**\n\t * Tuning knob for the built-in 423 retry. Defaults: ~30s of total wait spread across\n\t * 12 attempts with exponential backoff capped at 5s. Lowering this is mostly useful in\n\t * tests; raising it is rarely needed because Neon operations are usually sub-second.\n\t */\n\tretryOnLocked?: {\n\t\tmaxAttempts?: number;\n\t\tinitialDelayMs?: number;\n\t\tmaxDelayMs?: number;\n\t};\n}): NeonApi {\n\tif (!options.apiKey || options.apiKey.trim() === \"\") {\n\t\tthrow new PlatformError(\n\t\t\tErrorCode.MissingApiKey,\n\t\t\t[\n\t\t\t\t\"createRealNeonApi requires a non-empty `apiKey`.\",\n\t\t\t\t\"Generate one at https://console.neon.tech/app/settings/api-keys and pass it as { apiKey: process.env.NEON_API_KEY }.\",\n\t\t\t].join(\" \"),\n\t\t);\n\t}\n\n\tconst client = createApiClient({\n\t\tapiKey: options.apiKey,\n\t\t...(options.baseUrl ? { baseURL: options.baseUrl } : {}),\n\t});\n\n\treturn new RealNeonApi(\n\t\tclient,\n\t\t{\n\t\t\tmaxAttempts: options.retryOnLocked?.maxAttempts ?? 12,\n\t\t\tinitialDelayMs: options.retryOnLocked?.initialDelayMs ?? 250,\n\t\t\tmaxDelayMs: options.retryOnLocked?.maxDelayMs ?? 5_000,\n\t\t},\n\t\t{\n\t\t\tapiKey: options.apiKey,\n\t\t\tbaseUrl: options.baseUrl ?? DEFAULT_NEON_API_BASE_URL,\n\t\t},\n\t);\n}\n\ninterface RetryConfig {\n\tmaxAttempts: number;\n\tinitialDelayMs: number;\n\tmaxDelayMs: number;\n}\n\n/**\n * Retry a function whenever it throws an HTTP 423 (Locked) — Neon's signal that a prior\n * mutation on the same resource is still in flight. Uses exponential backoff capped at\n * `maxDelayMs`. Any other error (and the last attempt) propagates.\n *\n * Exported only for tests; production callers go through the wrapped {@link NeonApi}.\n */\nexport async function retryOnLocked<T>(\n\tfn: () => Promise<T>,\n\tconfig: RetryConfig,\n): Promise<T> {\n\tlet delay = config.initialDelayMs;\n\tlet lastError: unknown;\n\tfor (let attempt = 1; attempt <= config.maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} catch (err) {\n\t\t\tlastError = err;\n\t\t\tconst status = readHttpStatusFromError(err);\n\t\t\tif (status !== 423 || attempt === config.maxAttempts) throw err;\n\t\t\tawait sleep(delay);\n\t\t\tdelay = Math.min(delay * 2, config.maxDelayMs);\n\t\t}\n\t}\n\tthrow lastError;\n}\n\nfunction readHttpStatusFromError(err: unknown): number | undefined {\n\tif (err === null || typeof err !== \"object\") return undefined;\n\tconst response = (err as { response?: unknown }).response;\n\tif (response === null || typeof response !== \"object\") return undefined;\n\tconst status = (response as { status?: unknown }).status;\n\treturn typeof status === \"number\" ? status : undefined;\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nclass RealNeonApi implements NeonApi {\n\tconstructor(\n\t\tprivate readonly client: ApiClient,\n\t\tprivate readonly retryConfig: RetryConfig,\n\t\tprivate readonly restConfig: RestConfig,\n\t) {}\n\n\tprivate retry<T>(fn: () => Promise<T>): Promise<T> {\n\t\treturn retryOnLocked(fn, this.retryConfig);\n\t}\n\n\tprivate async call<T>(\n\t\top: string,\n\t\tfn: () => Promise<T>,\n\t\toptions: { projectId?: string; mutating?: boolean } = {},\n\t): Promise<T> {\n\t\ttry {\n\t\t\treturn options.mutating ? await this.retry(fn) : await fn();\n\t\t} catch (err) {\n\t\t\tconst wrapped = wrapNeonError(\n\t\t\t\terr,\n\t\t\t\toptions.projectId\n\t\t\t\t\t? { op, projectId: options.projectId }\n\t\t\t\t\t: { op },\n\t\t\t);\n\t\t\tthrow wrapped;\n\t\t}\n\t}\n\n\tasync listProjects(filter: {\n\t\torgId?: string;\n\t}): Promise<NeonProjectSnapshot[]> {\n\t\treturn this.call(\n\t\t\tfilter.orgId ? `listProjects(org=${filter.orgId})` : \"listProjects\",\n\t\t\tasync () => {\n\t\t\t\tconst projects: ProjectListItem[] = [];\n\t\t\t\tlet cursor: string | undefined;\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst res = await this.client.listProjects({\n\t\t\t\t\t\t...(filter.orgId ? { org_id: filter.orgId } : {}),\n\t\t\t\t\t\t...(cursor ? { cursor } : {}),\n\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t});\n\t\t\t\t\tprojects.push(...res.data.projects);\n\t\t\t\t\tconst next = (\n\t\t\t\t\t\tres.data as { pagination?: { next?: string } }\n\t\t\t\t\t).pagination?.next;\n\t\t\t\t\tif (!next || next === cursor) break;\n\t\t\t\t\tcursor = next;\n\t\t\t\t}\n\t\t\t\treturn projects.map(projectToSnapshot);\n\t\t\t},\n\t\t);\n\t}\n\n\tasync getProject(projectId: string): Promise<NeonProjectSnapshot> {\n\t\treturn this.call(\n\t\t\t`getProject(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.getProject(projectId);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync createProject(\n\t\tinput: CreateProjectInput,\n\t): Promise<NeonProjectSnapshot> {\n\t\tconst body: ProjectCreateRequest = {\n\t\t\tproject: {\n\t\t\t\tname: input.name,\n\t\t\t\tregion_id: input.regionId,\n\t\t\t\t...(input.pgVersion !== undefined\n\t\t\t\t\t? { pg_version: input.pgVersion as PgVersion }\n\t\t\t\t\t: {}),\n\t\t\t\t...(input.orgId ? { org_id: input.orgId } : {}),\n\t\t\t\t...(input.defaultEndpointSettings\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tdefault_endpoint_settings:\n\t\t\t\t\t\t\t\tcomputeSettingsToDefaults(\n\t\t\t\t\t\t\t\t\tinput.defaultEndpointSettings,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\t...(input.defaultBranchName\n\t\t\t\t\t? { branch: { name: input.defaultBranchName } }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t};\n\t\treturn this.call(\n\t\t\t`createProject(${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.createProject(body);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ mutating: true },\n\t\t);\n\t}\n\n\tasync updateProject(\n\t\tprojectId: string,\n\t\tinput: { name?: string; defaultEndpointSettings?: ComputeSettings },\n\t): Promise<NeonProjectSnapshot> {\n\t\tconst body: ProjectUpdateRequest = {\n\t\t\tproject: {\n\t\t\t\t...(input.name !== undefined ? { name: input.name } : {}),\n\t\t\t\t...(input.defaultEndpointSettings\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tdefault_endpoint_settings:\n\t\t\t\t\t\t\t\tcomputeSettingsToDefaults(\n\t\t\t\t\t\t\t\t\tinput.defaultEndpointSettings,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t};\n\t\treturn this.call(\n\t\t\t`updateProject(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProject(projectId, body);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listBranches(projectId: string): Promise<NeonBranchSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranches(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst branches: Branch[] = [];\n\t\t\t\tlet cursor: string | undefined;\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst res = await this.client.listProjectBranches({\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t\t...(cursor ? { cursor } : {}),\n\t\t\t\t\t});\n\t\t\t\t\tbranches.push(...(res.data.branches as Branch[]));\n\t\t\t\t\tconst next = (\n\t\t\t\t\t\tres.data as { pagination?: { next?: string } }\n\t\t\t\t\t).pagination?.next;\n\t\t\t\t\tif (!next || next === cursor) break;\n\t\t\t\t\tcursor = next;\n\t\t\t\t}\n\t\t\t\treturn branches.map(branchToSnapshot);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync createBranch(\n\t\tprojectId: string,\n\t\tinput: CreateBranchInput,\n\t): Promise<{\n\t\tbranch: NeonBranchSnapshot;\n\t\tendpoints: NeonEndpointSnapshot[];\n\t}> {\n\t\tconst endpointOptions: BranchCreateRequestEndpointOptions | undefined =\n\t\t\tinput.computeSettings\n\t\t\t\t? {\n\t\t\t\t\t\ttype: EndpointType.ReadWrite,\n\t\t\t\t\t\t...computeSettingsToEndpointOptions(\n\t\t\t\t\t\t\tinput.computeSettings,\n\t\t\t\t\t\t),\n\t\t\t\t\t}\n\t\t\t\t: { type: EndpointType.ReadWrite };\n\n\t\tconst body: BranchCreateRequest = {\n\t\t\tbranch: {\n\t\t\t\tname: input.name,\n\t\t\t\t...(input.parentId ? { parent_id: input.parentId } : {}),\n\t\t\t\t...(input.expiresAt ? { expires_at: input.expiresAt } : {}),\n\t\t\t\t...(input.protected !== undefined\n\t\t\t\t\t? { protected: input.protected }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\tendpoints: [endpointOptions],\n\t\t};\n\t\treturn this.call(\n\t\t\t`createBranch(${projectId}/${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.createProjectBranch(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbody,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tbranch: branchToSnapshot(res.data.branch),\n\t\t\t\t\tendpoints: (res.data.endpoints ?? []).map(\n\t\t\t\t\t\tendpointToSnapshot,\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync updateBranch(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: UpdateBranchInput,\n\t): Promise<NeonBranchSnapshot> {\n\t\tconst branch: BranchUpdateRequest[\"branch\"] = {};\n\t\tif (input.name !== undefined) branch.name = input.name;\n\t\tif (input.expiresAt !== undefined) branch.expires_at = input.expiresAt;\n\t\tif (input.protected !== undefined) branch.protected = input.protected;\n\t\treturn this.call(\n\t\t\t`updateBranch(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProjectBranch(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t\t{ branch },\n\t\t\t\t);\n\t\t\t\treturn branchToSnapshot(res.data.branch);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listEndpoints(projectId: string): Promise<NeonEndpointSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listEndpoints(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectEndpoints(projectId);\n\t\t\t\treturn (res.data.endpoints as Endpoint[]).map(\n\t\t\t\t\tendpointToSnapshot,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync updateEndpoint(\n\t\tprojectId: string,\n\t\tendpointId: string,\n\t\tsettings: ComputeSettings,\n\t): Promise<NeonEndpointSnapshot> {\n\t\tconst endpoint: EndpointUpdateRequest[\"endpoint\"] =\n\t\t\tcomputeSettingsToEndpointOptions(settings);\n\t\treturn this.call(\n\t\t\t`updateEndpoint(${projectId}/${endpointId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProjectEndpoint(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tendpointId,\n\t\t\t\t\t{ endpoint },\n\t\t\t\t);\n\t\t\t\treturn endpointToSnapshot(res.data.endpoint);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listBranchRoles(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonRoleSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranchRoles(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectBranchRoles(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t);\n\t\t\t\treturn (res.data.roles as Role[]).map(roleToSnapshot);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync listBranchDatabases(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonDatabaseSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranchDatabases(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectBranchDatabases(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t);\n\t\t\t\treturn (res.data.databases as Database[]).map(\n\t\t\t\t\tdatabaseToSnapshot,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync getConnectionUri(\n\t\tprojectId: string,\n\t\tinput: GetConnectionUriInput,\n\t): Promise<{ uri: string }> {\n\t\tconst op = `getConnectionUri(${projectId}/${input.databaseName}@${input.roleName}${input.pooled ? \" pooled\" : \"\"})`;\n\t\t// Always send `pooled` explicitly. The Neon API has switched its default\n\t\t// to returning the pooled URI when the parameter is omitted, so we have\n\t\t// to be explicit to get the direct URI back.\n\t\tconst pooled = input.pooled === true;\n\t\treturn this.call(\n\t\t\top,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.getConnectionUri({\n\t\t\t\t\tprojectId,\n\t\t\t\t\tdatabase_name: input.databaseName,\n\t\t\t\t\trole_name: input.roleName,\n\t\t\t\t\t...(input.branchId ? { branch_id: input.branchId } : {}),\n\t\t\t\t\t...(input.endpointId\n\t\t\t\t\t\t? { endpoint_id: input.endpointId }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\tpooled,\n\t\t\t\t});\n\t\t\t\treturn { uri: res.data.uri };\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync getNeonAuth(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonAuthSnapshot | null> {\n\t\t// `GET /projects/:pid/branches/:bid/auth` returns 404 when no integration exists.\n\t\t// Surface that as `null` so callers can branch cleanly instead of try/catch.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getNeonAuth(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.getNeonAuth(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t);\n\t\t\t\t\treturn neonAuthResponseToSnapshot(res.data);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (err instanceof PlatformError && err.code === ErrorCode.NotFound)\n\t\t\t\treturn null;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableNeonAuth(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: { databaseName?: string } = {},\n\t): Promise<NeonAuthSnapshot> {\n\t\t// Idempotent: if an integration already exists on the branch, the POST returns 409\n\t\t// (`Conflict`). We swallow that and re-fetch the existing snapshot so callers can\n\t\t// rely on `enableNeonAuth` to be safe to invoke from any push, including no-ops.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`enableNeonAuth(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\t// TODO: switch back to `this.client.createNeonAuth` once\n\t\t\t\t\t// @neondatabase/api-client narrows this branch endpoint to `better_auth`.\n\t\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\t\t`/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/auth`,\n\t\t\t\t\t\tcreateNeonAuthRestInput(input),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = neonAuthResponseSchema.parse(data);\n\t\t\t\t\treturn neonAuthResponseToSnapshot(parsed);\n\t\t\t\t},\n\t\t\t\t{ projectId, mutating: true },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\terr instanceof PlatformError &&\n\t\t\t\terr.code === ErrorCode.Conflict\n\t\t\t) {\n\t\t\t\tconst existing = await this.getNeonAuth(projectId, branchId);\n\t\t\t\tif (existing) return existing;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tprivate async postJson(path: string, body: unknown): Promise<unknown> {\n\t\treturn this.request(\"POST\", path, {\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(body),\n\t\t});\n\t}\n\n\tprivate async getJson(path: string): Promise<unknown> {\n\t\treturn this.request(\"GET\", path);\n\t}\n\n\tprivate async deleteJson(path: string): Promise<unknown> {\n\t\treturn this.request(\"DELETE\", path);\n\t}\n\n\t/**\n\t * Upload a built function bundle via `multipart/form-data` to the deploy endpoint\n\t * (`POST .../functions/{slug}/deployments`). Body shape lives in the pure\n\t * {@link buildFunctionDeployForm} helper so it can be unit-tested against the spec.\n\t */\n\tprivate async postMultipart(\n\t\tpath: string,\n\t\tinput: DeployFunctionInput,\n\t): Promise<unknown> {\n\t\treturn this.request(\"POST\", path, {\n\t\t\tbody: buildFunctionDeployForm(input),\n\t\t});\n\t}\n\n\tprivate async request(\n\t\tmethod: \"GET\" | \"POST\" | \"DELETE\",\n\t\tpath: string,\n\t\tinit: { headers?: Record<string, string>; body?: BodyInit } = {},\n\t): Promise<unknown> {\n\t\tconst url = `${this.restConfig.baseUrl.replace(/\\/+$/, \"\")}${path}`;\n\t\tconst res = await fetch(url, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${this.restConfig.apiKey}`,\n\t\t\t\t...(init.headers ?? {}),\n\t\t\t},\n\t\t\t...(init.body !== undefined ? { body: init.body } : {}),\n\t\t});\n\t\tconst data = await readJsonBody(res);\n\t\tif (!res.ok) {\n\t\t\tthrow {\n\t\t\t\tresponse: {\n\t\t\t\t\tstatus: res.status,\n\t\t\t\t\tdata,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn data;\n\t}\n\n\tasync getNeonDataApi(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tdatabaseName: string,\n\t): Promise<NeonDataApiSnapshot | null> {\n\t\t// Same shape as getNeonAuth — 404 means \"no integration on this branch/db\", which\n\t\t// we translate to `null` for the caller.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getNeonDataApi(${projectId}/${branchId}/${databaseName})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.getProjectBranchDataApi(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t\tdatabaseName,\n\t\t\t\t\t);\n\t\t\t\t\treturn { url: res.data.url };\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (err instanceof PlatformError && err.code === ErrorCode.NotFound)\n\t\t\t\treturn null;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableProjectBranchDataApi(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tdatabaseName: string,\n\t): Promise<NeonDataApiSnapshot> {\n\t\t// Idempotent in the same shape as `enableNeonAuth`: if an integration already\n\t\t// exists, the POST returns 409 and we re-fetch the existing snapshot.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`enableProjectBranchDataApi(${projectId}/${branchId}/${databaseName})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.createProjectBranchDataApi(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t\tdatabaseName,\n\t\t\t\t\t\t// Empty body — pick up Neon defaults (auth_provider inferred from\n\t\t\t\t\t\t// whether Neon Auth is also enabled; default schemas/grants).\n\t\t\t\t\t\t{},\n\t\t\t\t\t);\n\t\t\t\t\treturn { url: res.data.url };\n\t\t\t\t},\n\t\t\t\t{ projectId, mutating: true },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\terr instanceof PlatformError &&\n\t\t\t\terr.code === ErrorCode.Conflict\n\t\t\t) {\n\t\t\t\tconst existing = await this.getNeonDataApi(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t\tdatabaseName,\n\t\t\t\t);\n\t\t\t\tif (existing) return existing;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t// ─── Preview: buckets ──────────────────────────────────────────────────────\n\n\tasync listBranchBuckets(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonBucketSnapshot[]> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`listBranchBuckets(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"buckets\"),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = bucketsListResponseSchema.parse(data);\n\t\t\t\t\treturn parsed.buckets.map(bucketToSnapshot);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow previewUnavailableError(err, \"Object storage (buckets)\");\n\t\t}\n\t}\n\n\tasync createBranchBucket(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: CreateBucketInput,\n\t): Promise<NeonBucketSnapshot> {\n\t\treturn this.call(\n\t\t\t`createBranchBucket(${projectId}/${branchId}/${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"buckets\"),\n\t\t\t\t\t{\n\t\t\t\t\t\tname: input.name,\n\t\t\t\t\t\t...(input.accessLevel\n\t\t\t\t\t\t\t? { access_level: input.accessLevel }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst parsed = bucketResponseSchema.parse(data);\n\t\t\t\treturn bucketToSnapshot(parsed.bucket);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deleteBranchBucket(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tbucketName: string,\n\t): Promise<void> {\n\t\tawait this.call(\n\t\t\t`deleteBranchBucket(${projectId}/${branchId}/${bucketName})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"buckets\")}/${encodeURIComponent(bucketName)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\t// ─── Preview: functions ────────────────────────────────────────────────────\n\n\tasync listBranchFunctions(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonFunctionSnapshot[]> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`listBranchFunctions(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"functions\"),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = functionsListResponseSchema.parse(data);\n\t\t\t\t\treturn parsed.functions.map(functionToSnapshot);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow previewUnavailableError(err, \"Functions\");\n\t\t}\n\t}\n\n\tasync createBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: { slug: string; name: string },\n\t): Promise<NeonFunctionSnapshot> {\n\t\treturn this.call(\n\t\t\t`createBranchFunction(${projectId}/${branchId}/${input.slug})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"functions\"),\n\t\t\t\t\t{ slug: input.slug, name: input.name },\n\t\t\t\t);\n\t\t\t\tconst parsed = functionResponseSchema.parse(data);\n\t\t\t\treturn functionToSnapshot(parsed.function);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deleteBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tslug: string,\n\t): Promise<void> {\n\t\tawait this.call(\n\t\t\t`deleteBranchFunction(${projectId}/${branchId}/${slug})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"functions\")}/${encodeURIComponent(slug)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deployBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tslug: string,\n\t\tinput: DeployFunctionInput,\n\t): Promise<NeonFunctionDeploymentSnapshot> {\n\t\treturn this.call(\n\t\t\t`deployBranchFunction(${projectId}/${branchId}/${slug})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postMultipart(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"functions\")}/${encodeURIComponent(slug)}/deployments`,\n\t\t\t\t\tinput,\n\t\t\t\t);\n\t\t\t\tconst parsed = functionDeploymentResponseSchema.parse(data);\n\t\t\t\treturn deploymentToSnapshot(parsed.deployment);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\t// ─── Preview: AI Gateway ───────────────────────────────────────────────────\n\t//\n\t// TODO(neon-deploy): the AI Gateway routes are not yet in the public API spec we wired\n\t// the rest of this adapter against. The paths below follow the established branch-scoped\n\t// convention (`/projects/{p}/branches/{b}/ai-gateway`); confirm them against the real\n\t// API (and the exact enable/disable verb + response shape) before relying on this in\n\t// production, and swap to the typed `@neondatabase/api-client` method once it exists.\n\n\tasync getAiGatewayEnabled(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<boolean> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getAiGatewayEnabled(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\taiGatewayPath(projectId, branchId),\n\t\t\t\t\t);\n\t\t\t\t\treturn aiGatewayEnabledFromResponse(data);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\t// A \"feature unavailable\" signal (route not deployed / \"not available\")\n\t\t\t// is a hard error — surface it rather than reporting \"disabled\". A plain\n\t\t\t// NotFound *without* that signal means the route exists but AI Gateway is\n\t\t\t// simply not enabled on this branch, which is `false`.\n\t\t\tif (isPreviewFeatureUnavailable(err)) {\n\t\t\t\tthrow previewUnavailableError(err, \"AI Gateway\");\n\t\t\t}\n\t\t\tif (\n\t\t\t\terr instanceof PlatformError &&\n\t\t\t\terr.code === ErrorCode.NotFound\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableAiGateway(projectId: string, branchId: string): Promise<void> {\n\t\tawait this.call(\n\t\t\t`enableAiGateway(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.postJson(aiGatewayPath(projectId, branchId), {\n\t\t\t\t\tenabled: true,\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync disableAiGateway(projectId: string, branchId: string): Promise<void> {\n\t\tawait this.call(\n\t\t\t`disableAiGateway(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(aiGatewayPath(projectId, branchId));\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n}\n\nfunction branchPreviewPath(\n\tprojectId: string,\n\tbranchId: string,\n\tresource: \"buckets\" | \"functions\",\n): string {\n\treturn `/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/${resource}`;\n}\n\nfunction aiGatewayPath(projectId: string, branchId: string): string {\n\treturn `/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/ai-gateway`;\n}\n\nfunction bucketToSnapshot(\n\tbucket: z.infer<typeof bucketSchema>,\n): NeonBucketSnapshot {\n\treturn {\n\t\tname: bucket.name,\n\t\taccessLevel: normalizeBucketAccessLevel(bucket.access_level),\n\t};\n}\n\n/**\n * The Neon API returns `access_level` as a free-form string (per the API guidelines:\n * responses use plain strings, not enums). Map the known values onto our union and treat\n * anything else as `private` — the safe default for an unrecognised access level.\n */\nfunction normalizeBucketAccessLevel(\n\tvalue: string | undefined,\n): BucketAccessLevel {\n\treturn value === \"public_read\" ? \"public_read\" : \"private\";\n}\n\nfunction functionToSnapshot(\n\tfn: z.infer<typeof neonFunctionSchema>,\n): NeonFunctionSnapshot {\n\tconst snapshot: NeonFunctionSnapshot = {\n\t\tid: fn.id,\n\t\tslug: fn.slug,\n\t\tname: fn.name,\n\t\tinvocationUrl: fn.invocation_url,\n\t};\n\tif (fn.active_deployment) {\n\t\tsnapshot.activeDeploymentId = fn.active_deployment.id;\n\t}\n\treturn snapshot;\n}\n\nfunction deploymentToSnapshot(\n\tdeployment: z.infer<typeof functionDeploymentSchema>,\n): NeonFunctionDeploymentSnapshot {\n\treturn {\n\t\tid: deployment.id,\n\t\tstatus: normalizeDeploymentStatus(deployment.status),\n\t};\n}\n\nfunction normalizeDeploymentStatus(\n\tvalue: string,\n): NeonFunctionDeploymentSnapshot[\"status\"] {\n\tswitch (value) {\n\t\tcase \"pending\":\n\t\tcase \"building\":\n\t\tcase \"completed\":\n\t\tcase \"failed\":\n\t\t\treturn value;\n\t\tdefault:\n\t\t\t// Unknown status from a newer server — surface as `pending` rather than throwing,\n\t\t\t// matching the API guideline that clients treat undocumented enum values leniently.\n\t\t\treturn \"pending\";\n\t}\n}\n\nfunction aiGatewayEnabledFromResponse(data: unknown): boolean {\n\tif (data !== null && typeof data === \"object\" && \"enabled\" in data) {\n\t\treturn (data as { enabled?: unknown }).enabled === true;\n\t}\n\treturn false;\n}\n\n/**\n * Whether an error from a Preview-feature read means the feature simply isn't available\n * for this project/branch/region (as opposed to a real, transient failure). Neon signals\n * this a few ways: a 404 \"this route does not exist\" (the route isn't deployed at all), or\n * a 503/4xx whose message says the platform feature is \"not available\" / \"not enabled\".\n *\n * Callers do **not** swallow this into an empty result — touching a Preview feature that\n * isn't available is surfaced as a {@link previewUnavailableError} so `plan` / `status` /\n * `pull` (and `neon dev`) fail clearly instead of, say, planning to create resources the\n * API will refuse to create.\n */\nexport function isPreviewFeatureUnavailable(err: unknown): boolean {\n\tif (!(err instanceof PlatformError)) return false;\n\tconst status = err.details.status;\n\tconst message =\n\t\ttypeof err.details.neonMessage === \"string\"\n\t\t\t? err.details.neonMessage.toLowerCase()\n\t\t\t: \"\";\n\tconst mentionsUnavailable =\n\t\tmessage.includes(\"not available\") ||\n\t\tmessage.includes(\"does not exist\") ||\n\t\tmessage.includes(\"not enabled\");\n\treturn (\n\t\tmentionsUnavailable &&\n\t\t(status === 503 || status === 404 || status === 501)\n\t);\n}\n\n/**\n * Convert a Preview-feature error into a clear {@link PlatformError} when the feature is\n * unavailable for the project; otherwise pass the original error through unchanged so a\n * genuine failure (auth, transient 5xx, …) keeps its specific code and message.\n */\nexport function previewUnavailableError(\n\terr: unknown,\n\tfeatureLabel: string,\n): unknown {\n\tif (!isPreviewFeatureUnavailable(err)) return err;\n\tconst neonMessage =\n\t\terr instanceof PlatformError &&\n\t\ttypeof err.details.neonMessage === \"string\"\n\t\t\t? ` (Neon API said: \"${err.details.neonMessage}\")`\n\t\t\t: \"\";\n\treturn new PlatformError(\n\t\tErrorCode.FeatureUnavailable,\n\t\t`${featureLabel} is a Preview feature that is not available for this project or region${neonMessage}. ` +\n\t\t\t\"Enable it for your Neon account/project first, then re-run.\",\n\t\t{ cause: err, details: { feature: featureLabel } },\n\t);\n}\n\nfunction neonAuthResponseToSnapshot(\n\tdata: z.infer<typeof neonAuthResponseSchema>,\n): NeonAuthSnapshot {\n\tconst snapshot: NeonAuthSnapshot = {\n\t\tprojectId: data.auth_provider_project_id,\n\t\tjwksUrl: data.jwks_url,\n\t};\n\tif (data.pub_client_key !== undefined) {\n\t\tsnapshot.publishableClientKey = data.pub_client_key;\n\t}\n\tif (data.secret_server_key !== undefined) {\n\t\tsnapshot.secretServerKey = data.secret_server_key;\n\t}\n\tif (data.base_url) snapshot.baseUrl = data.base_url;\n\treturn snapshot;\n}\n\nexport function createNeonAuthRestInput(input: {\n\tdatabaseName?: string;\n}): CreateNeonAuthRestInput {\n\treturn {\n\t\tauth_provider: \"better_auth\",\n\t\t...(input.databaseName ? { database_name: input.databaseName } : {}),\n\t};\n}\n\n/**\n * Build the `multipart/form-data` body for a function deployment, matching the public\n * `FunctionDeployRequest` schema (`POST .../functions/{slug}/deployments`):\n *\n * - `zip` — the bundle as a binary part (named `bundle.zip`).\n * - `runtime` — the function runtime.\n * - `environment` — a single JSON-encoded string→string map (multipart can't carry a typed\n * object part), omitted entirely when there are no env vars.\n *\n * Pure (no I/O) so it can be unit-tested against the spec without stubbing `fetch`.\n */\nexport function buildFunctionDeployForm(input: DeployFunctionInput): FormData {\n\tconst form = new FormData();\n\tform.set(\n\t\t\"zip\",\n\t\tnew Blob([input.bundle as BlobPart], { type: \"application/zip\" }),\n\t\t\"bundle.zip\",\n\t);\n\tform.set(\"runtime\", input.runtime);\n\tif (Object.keys(input.environment).length > 0) {\n\t\tform.set(\"environment\", JSON.stringify(input.environment));\n\t}\n\treturn form;\n}\n\n/**\n * Read a response body as JSON, tolerating non-JSON. Some Neon routes return a plain-text\n * body (e.g. a 404 `\"this route does not exist\"` for a Preview feature not enabled in the\n * project/region). Parsing that with `JSON.parse` used to throw a cryptic\n * `SyntaxError: Unexpected token …`, which — because parsing happens before the `res.ok`\n * check in {@link request} — masked the real HTTP status. We instead return the raw text\n * wrapped as `{ message }` so the status-based error path in `request` / `wrapNeonError`\n * runs and produces a proper {@link PlatformError} (e.g. `NotFound`), and a non-error body\n * that simply isn't JSON degrades to text rather than crashing.\n */\nexport async function readJsonBody(res: Response): Promise<unknown> {\n\tconst text = await res.text();\n\tif (text.trim() === \"\") return {};\n\ttry {\n\t\treturn JSON.parse(text);\n\t} catch {\n\t\treturn { message: text.trim() };\n\t}\n}\n\nfunction projectToSnapshot(\n\tproject: Project | ProjectListItem,\n): NeonProjectSnapshot {\n\tconst defaults = project.default_endpoint_settings;\n\tconst snapshot: NeonProjectSnapshot = {\n\t\tid: project.id,\n\t\tname: project.name,\n\t\tregionId: project.region_id,\n\t\tpgVersion: project.pg_version,\n\t};\n\tif (project.org_id) snapshot.orgId = project.org_id;\n\tif (defaults) {\n\t\tconst compute = defaultsToComputeSettings(defaults);\n\t\tif (compute) snapshot.defaultEndpointSettings = compute;\n\t}\n\treturn snapshot;\n}\n\nfunction branchToSnapshot(branch: Branch): NeonBranchSnapshot {\n\tconst snapshot: NeonBranchSnapshot = {\n\t\tid: branch.id,\n\t\tname: branch.name,\n\t\tisDefault: branch.default,\n\t\tprotected: branch.protected === true,\n\t};\n\tif (branch.parent_id) snapshot.parentId = branch.parent_id;\n\tif (branch.expires_at) snapshot.expiresAt = branch.expires_at;\n\treturn snapshot;\n}\n\nfunction endpointToSnapshot(endpoint: Endpoint): NeonEndpointSnapshot {\n\treturn {\n\t\tid: endpoint.id,\n\t\tbranchId: endpoint.branch_id,\n\t\ttype:\n\t\t\tendpoint.type === EndpointType.ReadOnly\n\t\t\t\t? \"read_only\"\n\t\t\t\t: \"read_write\",\n\t\tautoscalingLimitMinCu:\n\t\t\tendpoint.autoscaling_limit_min_cu as ComputeSettings[\"autoscalingLimitMinCu\"],\n\t\tautoscalingLimitMaxCu:\n\t\t\tendpoint.autoscaling_limit_max_cu as ComputeSettings[\"autoscalingLimitMaxCu\"],\n\t\tsuspendTimeout: formatSuspendTimeout(endpoint.suspend_timeout_seconds),\n\t};\n}\n\nfunction roleToSnapshot(role: Role): NeonRoleSnapshot {\n\treturn {\n\t\tname: role.name,\n\t\tbranchId: role.branch_id,\n\t\tprotected: role.protected ?? false,\n\t};\n}\n\nfunction databaseToSnapshot(database: Database): NeonDatabaseSnapshot {\n\treturn {\n\t\tname: database.name,\n\t\tbranchId: database.branch_id,\n\t\townerName: database.owner_name,\n\t};\n}\n\nfunction computeSettingsToDefaults(\n\tsettings: ComputeSettings,\n): DefaultEndpointSettings {\n\tconst out: DefaultEndpointSettings = {};\n\tif (settings.autoscalingLimitMinCu !== undefined)\n\t\tout.autoscaling_limit_min_cu = settings.autoscalingLimitMinCu;\n\tif (settings.autoscalingLimitMaxCu !== undefined)\n\t\tout.autoscaling_limit_max_cu = settings.autoscalingLimitMaxCu;\n\tif (settings.suspendTimeout !== undefined) {\n\t\tconst parsed = parseSuspendTimeout(settings.suspendTimeout);\n\t\tif (\"error\" in parsed) {\n\t\t\tthrow new PlatformError(\n\t\t\t\tErrorCode.InvalidConfig,\n\t\t\t\t`Invalid suspendTimeout: ${parsed.error}`,\n\t\t\t);\n\t\t}\n\t\tout.suspend_timeout_seconds = parsed.seconds;\n\t}\n\treturn out;\n}\n\nfunction computeSettingsToEndpointOptions(settings: ComputeSettings): {\n\tautoscaling_limit_min_cu?: number;\n\tautoscaling_limit_max_cu?: number;\n\tsuspend_timeout_seconds?: number;\n} {\n\tconst out: {\n\t\tautoscaling_limit_min_cu?: number;\n\t\tautoscaling_limit_max_cu?: number;\n\t\tsuspend_timeout_seconds?: number;\n\t} = {};\n\tif (settings.autoscalingLimitMinCu !== undefined)\n\t\tout.autoscaling_limit_min_cu = settings.autoscalingLimitMinCu;\n\tif (settings.autoscalingLimitMaxCu !== undefined)\n\t\tout.autoscaling_limit_max_cu = settings.autoscalingLimitMaxCu;\n\tif (settings.suspendTimeout !== undefined) {\n\t\tconst parsed = parseSuspendTimeout(settings.suspendTimeout);\n\t\tif (\"error\" in parsed) {\n\t\t\tthrow new PlatformError(\n\t\t\t\tErrorCode.InvalidConfig,\n\t\t\t\t`Invalid suspendTimeout: ${parsed.error}`,\n\t\t\t);\n\t\t}\n\t\tout.suspend_timeout_seconds = parsed.seconds;\n\t}\n\treturn out;\n}\n\nfunction defaultsToComputeSettings(\n\tdefaults: DefaultEndpointSettings,\n): ComputeSettings | undefined {\n\tconst out: ComputeSettings = {};\n\tif (defaults.autoscaling_limit_min_cu !== undefined)\n\t\tout.autoscalingLimitMinCu =\n\t\t\tdefaults.autoscaling_limit_min_cu as ComputeSettings[\"autoscalingLimitMinCu\"];\n\tif (defaults.autoscaling_limit_max_cu !== undefined)\n\t\tout.autoscalingLimitMaxCu =\n\t\t\tdefaults.autoscaling_limit_max_cu as ComputeSettings[\"autoscalingLimitMaxCu\"];\n\tif (defaults.suspend_timeout_seconds !== undefined)\n\t\tout.suspendTimeout = formatSuspendTimeout(\n\t\t\tdefaults.suspend_timeout_seconds,\n\t\t);\n\treturn Object.keys(out).length > 0 ? out : undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"neon-api-real.js","names":[],"sources":["../../src/lib/neon-api-real.ts"],"sourcesContent":["import {\n\ttype Branch,\n\ttype BranchCreateRequest,\n\ttype BranchCreateRequestEndpointOptions,\n\ttype BranchUpdateRequest,\n\tcreateApiClient,\n\ttype Database,\n\ttype DefaultEndpointSettings,\n\ttype Endpoint,\n\tEndpointType,\n\ttype EndpointUpdateRequest,\n\ttype PgVersion,\n\ttype Project,\n\ttype ProjectCreateRequest,\n\ttype ProjectListItem,\n\ttype ProjectUpdateRequest,\n\ttype Role,\n} from \"@neondatabase/api-client\";\nimport { z } from \"zod\";\nimport { formatSuspendTimeout, parseSuspendTimeout } from \"./duration.js\";\nimport { ErrorCode, PlatformError } from \"./errors.js\";\nimport type {\n\tCreateBranchInput,\n\tCreateBucketInput,\n\tCreateCredentialInput,\n\tCreateProjectInput,\n\tDeployFunctionInput,\n\tGetConnectionUriInput,\n\tNeonApi,\n\tNeonAuthSnapshot,\n\tNeonBranchSnapshot,\n\tNeonBranchStorageSnapshot,\n\tNeonBucketSnapshot,\n\tNeonCredentialMeta,\n\tNeonCredentialSecret,\n\tNeonDataApiSnapshot,\n\tNeonDatabaseSnapshot,\n\tNeonEndpointSnapshot,\n\tNeonFunctionDeploymentSnapshot,\n\tNeonFunctionSnapshot,\n\tNeonProjectSnapshot,\n\tNeonRoleSnapshot,\n\tUpdateBranchInput,\n} from \"./neon-api.js\";\nimport type { BucketAccessLevel, ComputeSettings } from \"./types.js\";\nimport { wrapNeonError } from \"./wrap-neon-error.js\";\n\ntype ApiClient = ReturnType<typeof createApiClient>;\nconst DEFAULT_NEON_API_BASE_URL = \"https://console.neon.tech/api/v2\";\n\nconst neonAuthResponseSchema = z.object({\n\tauth_provider_project_id: z.string(),\n\tpub_client_key: z.string().optional(),\n\tsecret_server_key: z.string().optional(),\n\tjwks_url: z.string(),\n\tbase_url: z.string().optional(),\n});\n\n// ─── Preview: buckets ──────────────────────────────────────────────────────\n\nconst bucketSchema = z.object({\n\tname: z.string(),\n\taccess_level: z.string().optional(),\n});\nconst bucketResponseSchema = z.object({ bucket: bucketSchema });\nconst bucketsListResponseSchema = z.object({ buckets: z.array(bucketSchema) });\nconst branchStorageSchema = z.object({\n\tenabled: z.boolean().optional(),\n\ts3_endpoint: z.string(),\n\tregion: z.string(),\n\tforce_path_style: z.boolean(),\n});\n\n// ─── Preview: functions ────────────────────────────────────────────────────\n\nconst functionDeploymentSchema = z.object({\n\tid: z.number(),\n\tstatus: z.string(),\n});\nconst neonFunctionSchema = z.object({\n\tid: z.string(),\n\tslug: z.string(),\n\tname: z.string(),\n\tinvocation_url: z.string(),\n\tactive_deployment: functionDeploymentSchema.optional(),\n});\nconst functionsListResponseSchema = z.object({\n\tfunctions: z.array(neonFunctionSchema),\n});\nconst functionDeploymentResponseSchema = z.object({\n\tdeployment: functionDeploymentSchema,\n});\n\n// ─── Preview: branch-scoped credentials ─────────────────────────────────────\n\nconst credentialScopeSchema = z.enum([\n\t\"storage:read\",\n\t\"storage:write\",\n\t\"ai_gateway:invoke\",\n\t\"functions:invoke\",\n]);\nconst createCredentialResponseSchema = z.object({\n\ttoken_id: z.string(),\n\ttoken_id_short: z.string(),\n\tname: z.string().optional(),\n\tapi_token: z.string(),\n\ts3_secret_access_key: z.string(),\n\tscopes: z.array(credentialScopeSchema),\n\tbranch_id: z.string(),\n\tcreated_at: z.string(),\n\texpires_at: z.string().optional(),\n});\nconst credentialMetaSchema = z.object({\n\ttoken_id: z.string(),\n\ttoken_id_short: z.string(),\n\tname: z.string().optional(),\n\tscopes: z.array(credentialScopeSchema),\n\tprincipal_type: z.enum([\"user\", \"function\"]),\n\tfunction_id: z.string().optional(),\n\tbranch_id: z.string().optional(),\n\tcreated_at: z.string(),\n\tlast_used_at: z.string().optional(),\n\trevoked_at: z.string().optional(),\n\texpires_at: z.string().optional(),\n});\nconst listCredentialsResponseSchema = z.object({\n\tcredentials: z.array(credentialMetaSchema),\n});\n\ninterface CreateNeonAuthRestInput {\n\tauth_provider: \"better_auth\";\n\tdatabase_name?: string;\n}\n\ninterface RestConfig {\n\tapiKey: string;\n\tbaseUrl: string;\n}\n\n/**\n * Adapt `@neondatabase/api-client` to the narrow {@link NeonApi} façade used by the rest of\n * this package. Constructs are restricted to whole-object read/write of just the fields we\n * model in {@link Config}; anything else stays untouched on the remote.\n */\nexport function createRealNeonApi(options: {\n\tapiKey: string;\n\tbaseUrl?: string;\n\t/**\n\t * Tuning knob for the built-in 423 retry. Defaults: ~30s of total wait spread across\n\t * 12 attempts with exponential backoff capped at 5s. Lowering this is mostly useful in\n\t * tests; raising it is rarely needed because Neon operations are usually sub-second.\n\t */\n\tretryOnLocked?: {\n\t\tmaxAttempts?: number;\n\t\tinitialDelayMs?: number;\n\t\tmaxDelayMs?: number;\n\t};\n}): NeonApi {\n\tif (!options.apiKey || options.apiKey.trim() === \"\") {\n\t\tthrow new PlatformError(\n\t\t\tErrorCode.MissingApiKey,\n\t\t\t[\n\t\t\t\t\"createRealNeonApi requires a non-empty `apiKey`.\",\n\t\t\t\t\"Generate one at https://console.neon.tech/app/settings/api-keys and pass it as { apiKey: process.env.NEON_API_KEY }.\",\n\t\t\t].join(\" \"),\n\t\t);\n\t}\n\n\tconst client = createApiClient({\n\t\tapiKey: options.apiKey,\n\t\t...(options.baseUrl ? { baseURL: options.baseUrl } : {}),\n\t});\n\n\treturn new RealNeonApi(\n\t\tclient,\n\t\t{\n\t\t\tmaxAttempts: options.retryOnLocked?.maxAttempts ?? 12,\n\t\t\tinitialDelayMs: options.retryOnLocked?.initialDelayMs ?? 250,\n\t\t\tmaxDelayMs: options.retryOnLocked?.maxDelayMs ?? 5_000,\n\t\t},\n\t\t{\n\t\t\tapiKey: options.apiKey,\n\t\t\tbaseUrl: options.baseUrl ?? DEFAULT_NEON_API_BASE_URL,\n\t\t},\n\t);\n}\n\ninterface RetryConfig {\n\tmaxAttempts: number;\n\tinitialDelayMs: number;\n\tmaxDelayMs: number;\n}\n\n/**\n * Retry a function whenever it throws an HTTP 423 (Locked) — Neon's signal that a prior\n * mutation on the same resource is still in flight. Uses exponential backoff capped at\n * `maxDelayMs`. Any other error (and the last attempt) propagates.\n *\n * Exported only for tests; production callers go through the wrapped {@link NeonApi}.\n */\nexport async function retryOnLocked<T>(\n\tfn: () => Promise<T>,\n\tconfig: RetryConfig,\n): Promise<T> {\n\tlet delay = config.initialDelayMs;\n\tlet lastError: unknown;\n\tfor (let attempt = 1; attempt <= config.maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} catch (err) {\n\t\t\tlastError = err;\n\t\t\tconst status = readHttpStatusFromError(err);\n\t\t\tif (status !== 423 || attempt === config.maxAttempts) throw err;\n\t\t\tawait sleep(delay);\n\t\t\tdelay = Math.min(delay * 2, config.maxDelayMs);\n\t\t}\n\t}\n\tthrow lastError;\n}\n\nfunction readHttpStatusFromError(err: unknown): number | undefined {\n\tif (err === null || typeof err !== \"object\") return undefined;\n\tconst response = (err as { response?: unknown }).response;\n\tif (response === null || typeof response !== \"object\") return undefined;\n\tconst status = (response as { status?: unknown }).status;\n\treturn typeof status === \"number\" ? status : undefined;\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nclass RealNeonApi implements NeonApi {\n\tconstructor(\n\t\tprivate readonly client: ApiClient,\n\t\tprivate readonly retryConfig: RetryConfig,\n\t\tprivate readonly restConfig: RestConfig,\n\t) {}\n\n\tprivate retry<T>(fn: () => Promise<T>): Promise<T> {\n\t\treturn retryOnLocked(fn, this.retryConfig);\n\t}\n\n\tprivate async call<T>(\n\t\top: string,\n\t\tfn: () => Promise<T>,\n\t\toptions: { projectId?: string; mutating?: boolean } = {},\n\t): Promise<T> {\n\t\ttry {\n\t\t\treturn options.mutating ? await this.retry(fn) : await fn();\n\t\t} catch (err) {\n\t\t\tconst wrapped = wrapNeonError(\n\t\t\t\terr,\n\t\t\t\toptions.projectId\n\t\t\t\t\t? { op, projectId: options.projectId }\n\t\t\t\t\t: { op },\n\t\t\t);\n\t\t\tthrow wrapped;\n\t\t}\n\t}\n\n\tasync listProjects(filter: {\n\t\torgId?: string;\n\t}): Promise<NeonProjectSnapshot[]> {\n\t\treturn this.call(\n\t\t\tfilter.orgId ? `listProjects(org=${filter.orgId})` : \"listProjects\",\n\t\t\tasync () => {\n\t\t\t\tconst projects: ProjectListItem[] = [];\n\t\t\t\tlet cursor: string | undefined;\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst res = await this.client.listProjects({\n\t\t\t\t\t\t...(filter.orgId ? { org_id: filter.orgId } : {}),\n\t\t\t\t\t\t...(cursor ? { cursor } : {}),\n\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t});\n\t\t\t\t\tprojects.push(...res.data.projects);\n\t\t\t\t\tconst next = (\n\t\t\t\t\t\tres.data as { pagination?: { next?: string } }\n\t\t\t\t\t).pagination?.next;\n\t\t\t\t\tif (!next || next === cursor) break;\n\t\t\t\t\tcursor = next;\n\t\t\t\t}\n\t\t\t\treturn projects.map(projectToSnapshot);\n\t\t\t},\n\t\t);\n\t}\n\n\tasync getProject(projectId: string): Promise<NeonProjectSnapshot> {\n\t\treturn this.call(\n\t\t\t`getProject(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.getProject(projectId);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync createProject(\n\t\tinput: CreateProjectInput,\n\t): Promise<NeonProjectSnapshot> {\n\t\tconst body: ProjectCreateRequest = {\n\t\t\tproject: {\n\t\t\t\tname: input.name,\n\t\t\t\tregion_id: input.regionId,\n\t\t\t\t...(input.pgVersion !== undefined\n\t\t\t\t\t? { pg_version: input.pgVersion as PgVersion }\n\t\t\t\t\t: {}),\n\t\t\t\t...(input.orgId ? { org_id: input.orgId } : {}),\n\t\t\t\t...(input.defaultEndpointSettings\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tdefault_endpoint_settings:\n\t\t\t\t\t\t\t\tcomputeSettingsToDefaults(\n\t\t\t\t\t\t\t\t\tinput.defaultEndpointSettings,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\t...(input.defaultBranchName\n\t\t\t\t\t? { branch: { name: input.defaultBranchName } }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t};\n\t\treturn this.call(\n\t\t\t`createProject(${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.createProject(body);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ mutating: true },\n\t\t);\n\t}\n\n\tasync updateProject(\n\t\tprojectId: string,\n\t\tinput: { name?: string; defaultEndpointSettings?: ComputeSettings },\n\t): Promise<NeonProjectSnapshot> {\n\t\tconst body: ProjectUpdateRequest = {\n\t\t\tproject: {\n\t\t\t\t...(input.name !== undefined ? { name: input.name } : {}),\n\t\t\t\t...(input.defaultEndpointSettings\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tdefault_endpoint_settings:\n\t\t\t\t\t\t\t\tcomputeSettingsToDefaults(\n\t\t\t\t\t\t\t\t\tinput.defaultEndpointSettings,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t};\n\t\treturn this.call(\n\t\t\t`updateProject(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProject(projectId, body);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listBranches(projectId: string): Promise<NeonBranchSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranches(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst branches: Branch[] = [];\n\t\t\t\tlet cursor: string | undefined;\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst res = await this.client.listProjectBranches({\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t\t...(cursor ? { cursor } : {}),\n\t\t\t\t\t});\n\t\t\t\t\tbranches.push(...(res.data.branches as Branch[]));\n\t\t\t\t\tconst next = (\n\t\t\t\t\t\tres.data as { pagination?: { next?: string } }\n\t\t\t\t\t).pagination?.next;\n\t\t\t\t\tif (!next || next === cursor) break;\n\t\t\t\t\tcursor = next;\n\t\t\t\t}\n\t\t\t\treturn branches.map(branchToSnapshot);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync createBranch(\n\t\tprojectId: string,\n\t\tinput: CreateBranchInput,\n\t): Promise<{\n\t\tbranch: NeonBranchSnapshot;\n\t\tendpoints: NeonEndpointSnapshot[];\n\t}> {\n\t\tconst endpointOptions: BranchCreateRequestEndpointOptions | undefined =\n\t\t\tinput.computeSettings\n\t\t\t\t? {\n\t\t\t\t\t\ttype: EndpointType.ReadWrite,\n\t\t\t\t\t\t...computeSettingsToEndpointOptions(\n\t\t\t\t\t\t\tinput.computeSettings,\n\t\t\t\t\t\t),\n\t\t\t\t\t}\n\t\t\t\t: { type: EndpointType.ReadWrite };\n\n\t\tconst body: BranchCreateRequest = {\n\t\t\tbranch: {\n\t\t\t\tname: input.name,\n\t\t\t\t...(input.parentId ? { parent_id: input.parentId } : {}),\n\t\t\t\t...(input.expiresAt ? { expires_at: input.expiresAt } : {}),\n\t\t\t\t...(input.protected !== undefined\n\t\t\t\t\t? { protected: input.protected }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\tendpoints: [endpointOptions],\n\t\t};\n\t\treturn this.call(\n\t\t\t`createBranch(${projectId}/${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.createProjectBranch(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbody,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tbranch: branchToSnapshot(res.data.branch),\n\t\t\t\t\tendpoints: (res.data.endpoints ?? []).map(\n\t\t\t\t\t\tendpointToSnapshot,\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync updateBranch(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: UpdateBranchInput,\n\t): Promise<NeonBranchSnapshot> {\n\t\tconst branch: BranchUpdateRequest[\"branch\"] = {};\n\t\tif (input.name !== undefined) branch.name = input.name;\n\t\tif (input.expiresAt !== undefined) branch.expires_at = input.expiresAt;\n\t\tif (input.protected !== undefined) branch.protected = input.protected;\n\t\treturn this.call(\n\t\t\t`updateBranch(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProjectBranch(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t\t{ branch },\n\t\t\t\t);\n\t\t\t\treturn branchToSnapshot(res.data.branch);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listEndpoints(projectId: string): Promise<NeonEndpointSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listEndpoints(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectEndpoints(projectId);\n\t\t\t\treturn (res.data.endpoints as Endpoint[]).map(\n\t\t\t\t\tendpointToSnapshot,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync updateEndpoint(\n\t\tprojectId: string,\n\t\tendpointId: string,\n\t\tsettings: ComputeSettings,\n\t): Promise<NeonEndpointSnapshot> {\n\t\tconst endpoint: EndpointUpdateRequest[\"endpoint\"] =\n\t\t\tcomputeSettingsToEndpointOptions(settings);\n\t\treturn this.call(\n\t\t\t`updateEndpoint(${projectId}/${endpointId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProjectEndpoint(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tendpointId,\n\t\t\t\t\t{ endpoint },\n\t\t\t\t);\n\t\t\t\treturn endpointToSnapshot(res.data.endpoint);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listBranchRoles(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonRoleSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranchRoles(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectBranchRoles(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t);\n\t\t\t\treturn (res.data.roles as Role[]).map(roleToSnapshot);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync listBranchDatabases(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonDatabaseSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranchDatabases(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectBranchDatabases(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t);\n\t\t\t\treturn (res.data.databases as Database[]).map(\n\t\t\t\t\tdatabaseToSnapshot,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync getConnectionUri(\n\t\tprojectId: string,\n\t\tinput: GetConnectionUriInput,\n\t): Promise<{ uri: string }> {\n\t\tconst op = `getConnectionUri(${projectId}/${input.databaseName}@${input.roleName}${input.pooled ? \" pooled\" : \"\"})`;\n\t\t// Always send `pooled` explicitly. The Neon API has switched its default\n\t\t// to returning the pooled URI when the parameter is omitted, so we have\n\t\t// to be explicit to get the direct URI back.\n\t\tconst pooled = input.pooled === true;\n\t\treturn this.call(\n\t\t\top,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.getConnectionUri({\n\t\t\t\t\tprojectId,\n\t\t\t\t\tdatabase_name: input.databaseName,\n\t\t\t\t\trole_name: input.roleName,\n\t\t\t\t\t...(input.branchId ? { branch_id: input.branchId } : {}),\n\t\t\t\t\t...(input.endpointId\n\t\t\t\t\t\t? { endpoint_id: input.endpointId }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\tpooled,\n\t\t\t\t});\n\t\t\t\treturn { uri: res.data.uri };\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync getNeonAuth(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonAuthSnapshot | null> {\n\t\t// `GET /projects/:pid/branches/:bid/auth` returns 404 when no integration exists.\n\t\t// Surface that as `null` so callers can branch cleanly instead of try/catch.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getNeonAuth(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.getNeonAuth(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t);\n\t\t\t\t\treturn neonAuthResponseToSnapshot(res.data);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (err instanceof PlatformError && err.code === ErrorCode.NotFound)\n\t\t\t\treturn null;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableNeonAuth(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: { databaseName?: string } = {},\n\t): Promise<NeonAuthSnapshot> {\n\t\t// Idempotent: if an integration already exists on the branch, the POST returns 409\n\t\t// (`Conflict`). We swallow that and re-fetch the existing snapshot so callers can\n\t\t// rely on `enableNeonAuth` to be safe to invoke from any push, including no-ops.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`enableNeonAuth(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\t// TODO: switch back to `this.client.createNeonAuth` once\n\t\t\t\t\t// @neondatabase/api-client narrows this branch endpoint to `better_auth`.\n\t\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\t\t`/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/auth`,\n\t\t\t\t\t\tcreateNeonAuthRestInput(input),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = neonAuthResponseSchema.parse(data);\n\t\t\t\t\treturn neonAuthResponseToSnapshot(parsed);\n\t\t\t\t},\n\t\t\t\t{ projectId, mutating: true },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\terr instanceof PlatformError &&\n\t\t\t\terr.code === ErrorCode.Conflict\n\t\t\t) {\n\t\t\t\tconst existing = await this.getNeonAuth(projectId, branchId);\n\t\t\t\tif (existing) return existing;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tprivate async postJson(path: string, body: unknown): Promise<unknown> {\n\t\treturn this.request(\"POST\", path, {\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(body),\n\t\t});\n\t}\n\n\tprivate async getJson(path: string): Promise<unknown> {\n\t\treturn this.request(\"GET\", path);\n\t}\n\n\tprivate async deleteJson(path: string): Promise<unknown> {\n\t\treturn this.request(\"DELETE\", path);\n\t}\n\n\t/**\n\t * Upload a built function bundle via `multipart/form-data` to the deploy endpoint\n\t * (`POST .../functions/{slug}/deployments`). Body shape lives in the pure\n\t * {@link buildFunctionDeployForm} helper so it can be unit-tested against the spec.\n\t */\n\tprivate async postMultipart(\n\t\tpath: string,\n\t\tinput: DeployFunctionInput,\n\t): Promise<unknown> {\n\t\treturn this.request(\"POST\", path, {\n\t\t\tbody: buildFunctionDeployForm(input),\n\t\t});\n\t}\n\n\tprivate async request(\n\t\tmethod: \"GET\" | \"POST\" | \"DELETE\",\n\t\tpath: string,\n\t\tinit: { headers?: Record<string, string>; body?: BodyInit } = {},\n\t): Promise<unknown> {\n\t\tconst url = `${this.restConfig.baseUrl.replace(/\\/+$/, \"\")}${path}`;\n\t\tconst res = await fetch(url, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${this.restConfig.apiKey}`,\n\t\t\t\t...(init.headers ?? {}),\n\t\t\t},\n\t\t\t...(init.body !== undefined ? { body: init.body } : {}),\n\t\t});\n\t\tconst data = await readJsonBody(res);\n\t\tif (!res.ok) {\n\t\t\tthrow {\n\t\t\t\tresponse: {\n\t\t\t\t\tstatus: res.status,\n\t\t\t\t\tdata,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn data;\n\t}\n\n\tasync getNeonDataApi(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tdatabaseName: string,\n\t): Promise<NeonDataApiSnapshot | null> {\n\t\t// Same shape as getNeonAuth — 404 means \"no integration on this branch/db\", which\n\t\t// we translate to `null` for the caller.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getNeonDataApi(${projectId}/${branchId}/${databaseName})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.getProjectBranchDataApi(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t\tdatabaseName,\n\t\t\t\t\t);\n\t\t\t\t\treturn { url: res.data.url };\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (err instanceof PlatformError && err.code === ErrorCode.NotFound)\n\t\t\t\treturn null;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableProjectBranchDataApi(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tdatabaseName: string,\n\t): Promise<NeonDataApiSnapshot> {\n\t\t// Idempotent in the same shape as `enableNeonAuth`: if an integration already\n\t\t// exists, the POST returns 409 and we re-fetch the existing snapshot.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`enableProjectBranchDataApi(${projectId}/${branchId}/${databaseName})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.createProjectBranchDataApi(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t\tdatabaseName,\n\t\t\t\t\t\t// Empty body — pick up Neon defaults (auth_provider inferred from\n\t\t\t\t\t\t// whether Neon Auth is also enabled; default schemas/grants).\n\t\t\t\t\t\t{},\n\t\t\t\t\t);\n\t\t\t\t\treturn { url: res.data.url };\n\t\t\t\t},\n\t\t\t\t{ projectId, mutating: true },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\terr instanceof PlatformError &&\n\t\t\t\terr.code === ErrorCode.Conflict\n\t\t\t) {\n\t\t\t\tconst existing = await this.getNeonDataApi(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t\tdatabaseName,\n\t\t\t\t);\n\t\t\t\tif (existing) return existing;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t// ─── Preview: buckets ──────────────────────────────────────────────────────\n\n\tasync listBranchBuckets(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonBucketSnapshot[]> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`listBranchBuckets(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"buckets\"),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = bucketsListResponseSchema.parse(data);\n\t\t\t\t\treturn parsed.buckets.map(bucketToSnapshot);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow previewUnavailableError(err, \"Object storage (buckets)\");\n\t\t}\n\t}\n\n\tasync createBranchBucket(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: CreateBucketInput,\n\t): Promise<NeonBucketSnapshot> {\n\t\treturn this.call(\n\t\t\t`createBranchBucket(${projectId}/${branchId}/${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"buckets\"),\n\t\t\t\t\t{\n\t\t\t\t\t\tname: input.name,\n\t\t\t\t\t\t...(input.accessLevel\n\t\t\t\t\t\t\t? { access_level: input.accessLevel }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst parsed = bucketResponseSchema.parse(data);\n\t\t\t\treturn bucketToSnapshot(parsed.bucket);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deleteBranchBucket(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tbucketName: string,\n\t): Promise<void> {\n\t\tawait this.call(\n\t\t\t`deleteBranchBucket(${projectId}/${branchId}/${bucketName})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"buckets\")}/${encodeURIComponent(bucketName)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync getProjectBranchStorage(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonBranchStorageSnapshot | null> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getProjectBranchStorage(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\t`/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/storage`,\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = branchStorageSchema.parse(data);\n\t\t\t\t\treturn {\n\t\t\t\t\t\ts3Endpoint: parsed.s3_endpoint,\n\t\t\t\t\t\tregion: parsed.region,\n\t\t\t\t\t\tforcePathStyle: parsed.force_path_style,\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\t// 404 BranchStorageNotEnabled → storage not usable on this branch; let the\n\t\t\t// caller decide (fetchEnv throws a clear \"enable storage first\" error).\n\t\t\tif (err instanceof PlatformError && err.code === ErrorCode.NotFound)\n\t\t\t\treturn null;\n\t\t\tthrow previewUnavailableError(err, \"Object storage\");\n\t\t}\n\t}\n\n\t// ─── Preview: functions ────────────────────────────────────────────────────\n\n\tasync listBranchFunctions(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonFunctionSnapshot[]> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`listBranchFunctions(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"functions\"),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = functionsListResponseSchema.parse(data);\n\t\t\t\t\treturn parsed.functions.map(functionToSnapshot);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow previewUnavailableError(err, \"Functions\");\n\t\t}\n\t}\n\n\tasync deleteBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tslug: string,\n\t): Promise<void> {\n\t\tawait this.call(\n\t\t\t`deleteBranchFunction(${projectId}/${branchId}/${slug})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"functions\")}/${encodeURIComponent(slug)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deployBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tslug: string,\n\t\tinput: DeployFunctionInput,\n\t): Promise<NeonFunctionDeploymentSnapshot> {\n\t\treturn this.call(\n\t\t\t`deployBranchFunction(${projectId}/${branchId}/${slug})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postMultipart(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"functions\")}/${encodeURIComponent(slug)}/deployments`,\n\t\t\t\t\tinput,\n\t\t\t\t);\n\t\t\t\tconst parsed = functionDeploymentResponseSchema.parse(data);\n\t\t\t\treturn deploymentToSnapshot(parsed.deployment);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\t// ─── Preview: AI Gateway ───────────────────────────────────────────────────\n\t//\n\t// No methods: the AI Gateway is always available on a branch (credential-gated, not\n\t// per-branch provisioned). There is no control-plane enable/disable/status route — the\n\t// gateway is reached at the branch host with a credential carrying `ai_gateway:invoke`.\n\t// `preview.aiGateway` only drives that credential scope and the `OPENAI_*` /\n\t// `NEON_AI_GATEWAY_*` env vars (see `@neondatabase/env`); nothing is provisioned here, so\n\t// `plan` / `apply` never touch an AI Gateway route and can't fail on its availability.\n\n\t// ─── Preview: branch-scoped credentials ──────────────────────────────────\n\n\tasync createCredential(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: CreateCredentialInput,\n\t): Promise<NeonCredentialSecret> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`createCredential(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\t\tcredentialsPath(projectId, branchId),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tscopes: input.scopes,\n\t\t\t\t\t\t\tprincipal_type: input.principalType,\n\t\t\t\t\t\t\t...(input.functionId\n\t\t\t\t\t\t\t\t? { function_id: input.functionId }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t...(input.name ? { name: input.name } : {}),\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = createCredentialResponseSchema.parse(data);\n\t\t\t\t\treturn createCredentialToSnapshot(parsed);\n\t\t\t\t},\n\t\t\t\t{ projectId, mutating: true },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow previewUnavailableError(err, \"Branch credentials\");\n\t\t}\n\t}\n\n\tasync listCredentials(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonCredentialMeta[]> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`listCredentials(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\tcredentialsPath(projectId, branchId),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = listCredentialsResponseSchema.parse(data);\n\t\t\t\t\treturn parsed.credentials.map(credentialMetaToSnapshot);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow previewUnavailableError(err, \"Branch credentials\");\n\t\t}\n\t}\n\n\tasync revokeCredential(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\ttokenId: string,\n\t): Promise<void> {\n\t\tawait this.call(\n\t\t\t`revokeCredential(${projectId}/${branchId}/${tokenId})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(\n\t\t\t\t\t`${credentialsPath(projectId, branchId)}/${encodeURIComponent(tokenId)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n}\n\nfunction branchPreviewPath(\n\tprojectId: string,\n\tbranchId: string,\n\tresource: \"buckets\" | \"functions\",\n): string {\n\treturn `/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/${resource}`;\n}\n\nfunction credentialsPath(projectId: string, branchId: string): string {\n\treturn `/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/credentials`;\n}\n\nfunction createCredentialToSnapshot(\n\tdata: z.infer<typeof createCredentialResponseSchema>,\n): NeonCredentialSecret {\n\tconst snapshot: NeonCredentialSecret = {\n\t\ttokenId: data.token_id,\n\t\ttokenIdShort: data.token_id_short,\n\t\tapiToken: data.api_token,\n\t\ts3SecretAccessKey: data.s3_secret_access_key,\n\t\tscopes: data.scopes,\n\t\tbranchId: data.branch_id,\n\t\tcreatedAt: data.created_at,\n\t};\n\tif (data.name !== undefined) snapshot.name = data.name;\n\tif (data.expires_at !== undefined) snapshot.expiresAt = data.expires_at;\n\treturn snapshot;\n}\n\nfunction credentialMetaToSnapshot(\n\tdata: z.infer<typeof credentialMetaSchema>,\n): NeonCredentialMeta {\n\tconst snapshot: NeonCredentialMeta = {\n\t\ttokenId: data.token_id,\n\t\ttokenIdShort: data.token_id_short,\n\t\tscopes: data.scopes,\n\t\tprincipalType: data.principal_type,\n\t\tcreatedAt: data.created_at,\n\t};\n\tif (data.name !== undefined) snapshot.name = data.name;\n\tif (data.function_id !== undefined) snapshot.functionId = data.function_id;\n\tif (data.branch_id !== undefined) snapshot.branchId = data.branch_id;\n\tif (data.last_used_at !== undefined)\n\t\tsnapshot.lastUsedAt = data.last_used_at;\n\tif (data.revoked_at !== undefined) snapshot.revokedAt = data.revoked_at;\n\tif (data.expires_at !== undefined) snapshot.expiresAt = data.expires_at;\n\treturn snapshot;\n}\n\nfunction bucketToSnapshot(\n\tbucket: z.infer<typeof bucketSchema>,\n): NeonBucketSnapshot {\n\treturn {\n\t\tname: bucket.name,\n\t\taccessLevel: normalizeBucketAccessLevel(bucket.access_level),\n\t};\n}\n\n/**\n * The Neon API returns `access_level` as a free-form string (per the API guidelines:\n * responses use plain strings, not enums). Map the known values onto our union and treat\n * anything else as `private` — the safe default for an unrecognised access level.\n */\nfunction normalizeBucketAccessLevel(\n\tvalue: string | undefined,\n): BucketAccessLevel {\n\treturn value === \"public_read\" ? \"public_read\" : \"private\";\n}\n\nfunction functionToSnapshot(\n\tfn: z.infer<typeof neonFunctionSchema>,\n): NeonFunctionSnapshot {\n\tconst snapshot: NeonFunctionSnapshot = {\n\t\tid: fn.id,\n\t\tslug: fn.slug,\n\t\tname: fn.name,\n\t\tinvocationUrl: fn.invocation_url,\n\t};\n\tif (fn.active_deployment) {\n\t\tsnapshot.activeDeploymentId = fn.active_deployment.id;\n\t}\n\treturn snapshot;\n}\n\nfunction deploymentToSnapshot(\n\tdeployment: z.infer<typeof functionDeploymentSchema>,\n): NeonFunctionDeploymentSnapshot {\n\treturn {\n\t\tid: deployment.id,\n\t\tstatus: normalizeDeploymentStatus(deployment.status),\n\t};\n}\n\nfunction normalizeDeploymentStatus(\n\tvalue: string,\n): NeonFunctionDeploymentSnapshot[\"status\"] {\n\tswitch (value) {\n\t\tcase \"pending\":\n\t\tcase \"building\":\n\t\tcase \"completed\":\n\t\tcase \"failed\":\n\t\t\treturn value;\n\t\tdefault:\n\t\t\t// Unknown status from a newer server — surface as `pending` rather than throwing,\n\t\t\t// matching the API guideline that clients treat undocumented enum values leniently.\n\t\t\treturn \"pending\";\n\t}\n}\n\n/**\n * Whether an error from a Preview-feature read means the feature simply isn't available\n * for this project/branch/region (as opposed to a real, transient failure). Neon signals\n * this a few ways: a 404 \"this route does not exist\" (the route isn't deployed at all), or\n * a 503/4xx whose message says the platform feature is \"not available\" / \"not enabled\".\n *\n * Callers do **not** swallow this into an empty result — touching a Preview feature that\n * isn't available is surfaced as a {@link previewUnavailableError} so `plan` / `status` /\n * `pull` (and `neon dev`) fail clearly instead of, say, planning to create resources the\n * API will refuse to create.\n */\nexport function isPreviewFeatureUnavailable(err: unknown): boolean {\n\tif (!(err instanceof PlatformError)) return false;\n\tconst status = err.details.status;\n\tconst message =\n\t\ttypeof err.details.neonMessage === \"string\"\n\t\t\t? err.details.neonMessage.toLowerCase()\n\t\t\t: \"\";\n\tconst mentionsUnavailable =\n\t\tmessage.includes(\"not available\") ||\n\t\tmessage.includes(\"does not exist\") ||\n\t\tmessage.includes(\"not enabled\");\n\treturn (\n\t\tmentionsUnavailable &&\n\t\t(status === 503 || status === 404 || status === 501)\n\t);\n}\n\n/**\n * Reason phrase for the handful of HTTP statuses a Preview-feature read can surface as\n * \"unavailable\". Used to print a short `HTTP <status> <reason>` line (not a stack trace),\n * so the message reads like the API response the user would see in a tool like curl.\n */\nconst HTTP_STATUS_TEXT: Record<number, string> = {\n\t401: \"Unauthorized\",\n\t403: \"Forbidden\",\n\t404: \"Not Found\",\n\t500: \"Internal Server Error\",\n\t501: \"Not Implemented\",\n\t503: \"Service Unavailable\",\n};\n\n/**\n * Per-status guidance for a Preview feature that came back \"unavailable\". A preview can be\n * gated several different ways and the HTTP status is the best signal for which, so we tailor\n * the next step instead of emitting one catch-all — valuable while these features are in\n * preview and rolling out region by region:\n *\n * - 404 / 501 — the route isn't deployed for this project's region (or the account isn't in\n * the private preview): create a project in a region where the preview is enabled, and\n * confirm your account has preview access.\n * - 503 — the route exists but is refusing right now: either the preview is still coming up,\n * or Neon is having a transient incident. Retry; if it persists it's likely an incident.\n * - anything else — generic \"not enabled for your account/region; request access\".\n *\n * Only statuses {@link isPreviewFeatureUnavailable} accepts (404/501/503) actually reach\n * this, so there is intentionally no 401/403 branch — those never classify as \"unavailable\".\n */\nfunction previewUnavailableHint(status: number | undefined): string {\n\tswitch (status) {\n\t\tcase 404:\n\t\tcase 501:\n\t\t\treturn (\n\t\t\t\t\"This usually means the preview isn't available in your project's region yet, or \" +\n\t\t\t\t\"your Neon account isn't in the private preview: create a project in a region where \" +\n\t\t\t\t\"the preview is enabled, and make sure your account has access to the preview.\"\n\t\t\t);\n\t\tcase 503:\n\t\t\treturn (\n\t\t\t\t\"The endpoint is reachable but refused the request — the preview may still be \" +\n\t\t\t\t\"coming up, or Neon may be having a transient incident. Retry shortly; if it keeps \" +\n\t\t\t\t\"failing, check https://neonstatus.com and report it to Neon support.\"\n\t\t\t);\n\t\tdefault:\n\t\t\treturn (\n\t\t\t\t\"This usually means the preview isn't enabled for your Neon account or the project's \" +\n\t\t\t\t\"region. Request access to the preview, or use a project in a region where it's available.\"\n\t\t\t);\n\t}\n}\n\n/**\n * Convert a Preview-feature error into a clear {@link PlatformError} when the feature is\n * unavailable for the project; otherwise pass the original error through unchanged so a\n * genuine failure (auth, transient 5xx, …) keeps its specific code and message.\n *\n * The message names the failing feature, summarizes the response in one short\n * `HTTP <status> <reason>` line, includes the raw Neon API message + request id (valuable\n * signal while the feature is in preview), gives status-specific guidance (see\n * {@link previewUnavailableHint}), and offers removing the feature from the policy as an\n * escape hatch. `status`/`requestId` are also kept on `details` for programmatic consumers.\n */\nexport function previewUnavailableError(\n\terr: unknown,\n\tfeatureLabel: string,\n): unknown {\n\tif (!isPreviewFeatureUnavailable(err)) return err;\n\tconst details = err instanceof PlatformError ? err.details : {};\n\tconst status =\n\t\ttypeof details.status === \"number\" ? details.status : undefined;\n\tconst neonMessage =\n\t\ttypeof details.neonMessage === \"string\"\n\t\t\t? details.neonMessage\n\t\t\t: undefined;\n\tconst requestId =\n\t\ttypeof details.requestId === \"string\" ? details.requestId : undefined;\n\n\t// One short status line + the raw API message + request id — never a stack trace.\n\tconst statusText = status ? HTTP_STATUS_TEXT[status] : undefined;\n\tconst apiParts = [\n\t\tstatus\n\t\t\t? `HTTP ${status}${statusText ? ` ${statusText}` : \"\"}`\n\t\t\t: undefined,\n\t\tneonMessage ? `Neon API said: \"${neonMessage}\"` : undefined,\n\t\trequestId ? `request id ${requestId}` : undefined,\n\t].filter((part): part is string => part !== undefined);\n\tconst apiContext = apiParts.length > 0 ? ` (${apiParts.join(\"; \")})` : \"\";\n\n\treturn new PlatformError(\n\t\tErrorCode.FeatureUnavailable,\n\t\t[\n\t\t\t`${featureLabel} is a Preview feature and isn't available for this Neon project${apiContext}.`,\n\t\t\tpreviewUnavailableHint(status),\n\t\t\t\"If you don't need it, remove the corresponding feature from the `preview` block of your neon.ts and re-run.\",\n\t\t].join(\" \"),\n\t\t{\n\t\t\tcause: err,\n\t\t\tdetails: {\n\t\t\t\tfeature: featureLabel,\n\t\t\t\t...(status !== undefined ? { status } : {}),\n\t\t\t\t...(requestId !== undefined ? { requestId } : {}),\n\t\t\t},\n\t\t},\n\t);\n}\n\nfunction neonAuthResponseToSnapshot(\n\tdata: z.infer<typeof neonAuthResponseSchema>,\n): NeonAuthSnapshot {\n\tconst snapshot: NeonAuthSnapshot = {\n\t\tprojectId: data.auth_provider_project_id,\n\t\tjwksUrl: data.jwks_url,\n\t};\n\tif (data.pub_client_key !== undefined) {\n\t\tsnapshot.publishableClientKey = data.pub_client_key;\n\t}\n\tif (data.secret_server_key !== undefined) {\n\t\tsnapshot.secretServerKey = data.secret_server_key;\n\t}\n\tif (data.base_url) snapshot.baseUrl = data.base_url;\n\treturn snapshot;\n}\n\nexport function createNeonAuthRestInput(input: {\n\tdatabaseName?: string;\n}): CreateNeonAuthRestInput {\n\treturn {\n\t\tauth_provider: \"better_auth\",\n\t\t...(input.databaseName ? { database_name: input.databaseName } : {}),\n\t};\n}\n\n/**\n * Build the `multipart/form-data` body for a function deployment, matching the public\n * `FunctionDeployRequest` schema (`POST .../functions/{slug}/deployments`):\n *\n * - `zip` — the bundle as a binary part (named `bundle.zip`).\n * - `runtime` — the function runtime.\n * - `environment` — a single JSON-encoded string→string map (multipart can't carry a typed\n * object part), omitted entirely when there are no env vars.\n *\n * Pure (no I/O) so it can be unit-tested against the spec without stubbing `fetch`.\n */\nexport function buildFunctionDeployForm(input: DeployFunctionInput): FormData {\n\tconst form = new FormData();\n\tform.set(\n\t\t\"zip\",\n\t\tnew Blob([input.bundle as BlobPart], { type: \"application/zip\" }),\n\t\t\"bundle.zip\",\n\t);\n\tform.set(\"runtime\", input.runtime);\n\tif (Object.keys(input.environment).length > 0) {\n\t\tform.set(\"environment\", JSON.stringify(input.environment));\n\t}\n\treturn form;\n}\n\n/**\n * Read a response body as JSON, tolerating non-JSON. Some Neon routes return a plain-text\n * body (e.g. a 404 `\"this route does not exist\"` for a Preview feature not enabled in the\n * project/region). Parsing that with `JSON.parse` used to throw a cryptic\n * `SyntaxError: Unexpected token …`, which — because parsing happens before the `res.ok`\n * check in {@link request} — masked the real HTTP status. We instead return the raw text\n * wrapped as `{ message }` so the status-based error path in `request` / `wrapNeonError`\n * runs and produces a proper {@link PlatformError} (e.g. `NotFound`), and a non-error body\n * that simply isn't JSON degrades to text rather than crashing.\n */\nexport async function readJsonBody(res: Response): Promise<unknown> {\n\tconst text = await res.text();\n\tif (text.trim() === \"\") return {};\n\ttry {\n\t\treturn JSON.parse(text);\n\t} catch {\n\t\treturn { message: text.trim() };\n\t}\n}\n\nfunction projectToSnapshot(\n\tproject: Project | ProjectListItem,\n): NeonProjectSnapshot {\n\tconst defaults = project.default_endpoint_settings;\n\tconst snapshot: NeonProjectSnapshot = {\n\t\tid: project.id,\n\t\tname: project.name,\n\t\tregionId: project.region_id,\n\t\tpgVersion: project.pg_version,\n\t};\n\tif (project.org_id) snapshot.orgId = project.org_id;\n\tif (defaults) {\n\t\tconst compute = defaultsToComputeSettings(defaults);\n\t\tif (compute) snapshot.defaultEndpointSettings = compute;\n\t}\n\treturn snapshot;\n}\n\nfunction branchToSnapshot(branch: Branch): NeonBranchSnapshot {\n\tconst snapshot: NeonBranchSnapshot = {\n\t\tid: branch.id,\n\t\tname: branch.name,\n\t\tisDefault: branch.default,\n\t\tprotected: branch.protected === true,\n\t};\n\tif (branch.parent_id) snapshot.parentId = branch.parent_id;\n\tif (branch.expires_at) snapshot.expiresAt = branch.expires_at;\n\treturn snapshot;\n}\n\nfunction endpointToSnapshot(endpoint: Endpoint): NeonEndpointSnapshot {\n\treturn {\n\t\tid: endpoint.id,\n\t\tbranchId: endpoint.branch_id,\n\t\ttype:\n\t\t\tendpoint.type === EndpointType.ReadOnly\n\t\t\t\t? \"read_only\"\n\t\t\t\t: \"read_write\",\n\t\tautoscalingLimitMinCu:\n\t\t\tendpoint.autoscaling_limit_min_cu as ComputeSettings[\"autoscalingLimitMinCu\"],\n\t\tautoscalingLimitMaxCu:\n\t\t\tendpoint.autoscaling_limit_max_cu as ComputeSettings[\"autoscalingLimitMaxCu\"],\n\t\tsuspendTimeout: formatSuspendTimeout(endpoint.suspend_timeout_seconds),\n\t};\n}\n\nfunction roleToSnapshot(role: Role): NeonRoleSnapshot {\n\treturn {\n\t\tname: role.name,\n\t\tbranchId: role.branch_id,\n\t\tprotected: role.protected ?? false,\n\t};\n}\n\nfunction databaseToSnapshot(database: Database): NeonDatabaseSnapshot {\n\treturn {\n\t\tname: database.name,\n\t\tbranchId: database.branch_id,\n\t\townerName: database.owner_name,\n\t};\n}\n\nfunction computeSettingsToDefaults(\n\tsettings: ComputeSettings,\n): DefaultEndpointSettings {\n\tconst out: DefaultEndpointSettings = {};\n\tif (settings.autoscalingLimitMinCu !== undefined)\n\t\tout.autoscaling_limit_min_cu = settings.autoscalingLimitMinCu;\n\tif (settings.autoscalingLimitMaxCu !== undefined)\n\t\tout.autoscaling_limit_max_cu = settings.autoscalingLimitMaxCu;\n\tif (settings.suspendTimeout !== undefined) {\n\t\tconst parsed = parseSuspendTimeout(settings.suspendTimeout);\n\t\tif (\"error\" in parsed) {\n\t\t\tthrow new PlatformError(\n\t\t\t\tErrorCode.InvalidConfig,\n\t\t\t\t`Invalid suspendTimeout: ${parsed.error}`,\n\t\t\t);\n\t\t}\n\t\tout.suspend_timeout_seconds = parsed.seconds;\n\t}\n\treturn out;\n}\n\nfunction computeSettingsToEndpointOptions(settings: ComputeSettings): {\n\tautoscaling_limit_min_cu?: number;\n\tautoscaling_limit_max_cu?: number;\n\tsuspend_timeout_seconds?: number;\n} {\n\tconst out: {\n\t\tautoscaling_limit_min_cu?: number;\n\t\tautoscaling_limit_max_cu?: number;\n\t\tsuspend_timeout_seconds?: number;\n\t} = {};\n\tif (settings.autoscalingLimitMinCu !== undefined)\n\t\tout.autoscaling_limit_min_cu = settings.autoscalingLimitMinCu;\n\tif (settings.autoscalingLimitMaxCu !== undefined)\n\t\tout.autoscaling_limit_max_cu = settings.autoscalingLimitMaxCu;\n\tif (settings.suspendTimeout !== undefined) {\n\t\tconst parsed = parseSuspendTimeout(settings.suspendTimeout);\n\t\tif (\"error\" in parsed) {\n\t\t\tthrow new PlatformError(\n\t\t\t\tErrorCode.InvalidConfig,\n\t\t\t\t`Invalid suspendTimeout: ${parsed.error}`,\n\t\t\t);\n\t\t}\n\t\tout.suspend_timeout_seconds = parsed.seconds;\n\t}\n\treturn out;\n}\n\nfunction defaultsToComputeSettings(\n\tdefaults: DefaultEndpointSettings,\n): ComputeSettings | undefined {\n\tconst out: ComputeSettings = {};\n\tif (defaults.autoscaling_limit_min_cu !== undefined)\n\t\tout.autoscalingLimitMinCu =\n\t\t\tdefaults.autoscaling_limit_min_cu as ComputeSettings[\"autoscalingLimitMinCu\"];\n\tif (defaults.autoscaling_limit_max_cu !== undefined)\n\t\tout.autoscalingLimitMaxCu =\n\t\t\tdefaults.autoscaling_limit_max_cu as ComputeSettings[\"autoscalingLimitMaxCu\"];\n\tif (defaults.suspend_timeout_seconds !== undefined)\n\t\tout.suspendTimeout = formatSuspendTimeout(\n\t\t\tdefaults.suspend_timeout_seconds,\n\t\t);\n\treturn Object.keys(out).length > 0 ? out : undefined;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { BucketAccessLevel, ComputeSettings, FunctionRuntime } from "./types.js";
1
+ import { BucketAccessLevel, ComputeSettings, CredentialPrincipalType, CredentialScope, FunctionRuntime } from "./types.js";
2
2
 
3
3
  //#region src/lib/neon-api.d.ts
4
4
 
@@ -109,6 +109,22 @@ interface NeonBucketSnapshot {
109
109
  name: string;
110
110
  accessLevel: BucketAccessLevel;
111
111
  }
112
+ /**
113
+ * S3-compatible connection details for a branch's object storage (Preview) — the
114
+ * `BranchStorage` shape from `GET /projects/{id}/branches/{id}/storage`. Non-secret: it
115
+ * carries the endpoint/region/addressing the S3 SDK needs, while the access keys come from
116
+ * a minted {@link NeonCredentialSecret}. `forcePathStyle` is always `true` today (Neon's
117
+ * wildcard TLS cert puts the branch id in the subdomain, so the bucket must travel in the
118
+ * path).
119
+ */
120
+ interface NeonBranchStorageSnapshot {
121
+ /** S3-compatible endpoint URL, e.g. `https://br-….storage.<suffix>`. */
122
+ s3Endpoint: string;
123
+ /** AWS region string, normalized server-side (e.g. `us-east-2`, `us-east-1`). */
124
+ region: string;
125
+ /** Whether the S3 client must use path-style addressing (always `true` today). */
126
+ forcePathStyle: boolean;
127
+ }
112
128
  /**
113
129
  * Input for creating a bucket on a branch.
114
130
  */
@@ -150,6 +166,61 @@ interface NeonFunctionDeploymentSnapshot {
150
166
  id: number;
151
167
  status: "pending" | "building" | "completed" | "failed";
152
168
  }
169
+ /**
170
+ * Input for {@link NeonApi.createCredential}. Mirrors the Neon API `CreateCredentialRequest`
171
+ * (`POST .../credentials`, `x-stability-level: beta`):
172
+ *
173
+ * - `scopes` — 1–16 capabilities the credential may exercise (derived from the policy's
174
+ * enabled Preview features, never hand-authored).
175
+ * - `principalType` — `user` (developer/app) or `function` (a deployed function).
176
+ * - `functionId` — required when `principalType === "function"`.
177
+ * - `name` — optional free-form label echoed back on the response.
178
+ */
179
+ interface CreateCredentialInput {
180
+ scopes: CredentialScope[];
181
+ principalType: CredentialPrincipalType;
182
+ functionId?: string;
183
+ name?: string;
184
+ }
185
+ /**
186
+ * The secret-bearing result of {@link NeonApi.createCredential} — the Neon API
187
+ * `CreateCredentialResponse`. `apiToken` and `s3SecretAccessKey` are returned **exactly
188
+ * once** (they are not stored server-side), so the caller must persist them immediately;
189
+ * they can never be re-fetched (the list endpoint returns metadata only). `tokenIdShort`
190
+ * is the public identifier embedded in `apiToken` (`nt_live_<tokenIdShort>_…`) and doubles
191
+ * as the S3 access-key id.
192
+ */
193
+ interface NeonCredentialSecret {
194
+ tokenId: string;
195
+ tokenIdShort: string;
196
+ name?: string;
197
+ /** Bearer token (`nt_live_…`); returned once. Used for AI Gateway / Functions invoke. */
198
+ apiToken: string;
199
+ /** 64-char hex S3 secret access key; returned once. Paired with `tokenIdShort` as the access-key id. */
200
+ s3SecretAccessKey: string;
201
+ scopes: CredentialScope[];
202
+ branchId: string;
203
+ createdAt: string;
204
+ /** When the credential expires; absent means it never expires. */
205
+ expiresAt?: string;
206
+ }
207
+ /**
208
+ * Secret-free metadata for an issued credential — the Neon API `CredentialMeta` returned by
209
+ * {@link NeonApi.listCredentials}. Never includes `apiToken` / `s3SecretAccessKey`.
210
+ */
211
+ interface NeonCredentialMeta {
212
+ tokenId: string;
213
+ tokenIdShort: string;
214
+ name?: string;
215
+ scopes: CredentialScope[];
216
+ principalType: CredentialPrincipalType;
217
+ functionId?: string;
218
+ branchId?: string;
219
+ createdAt: string;
220
+ lastUsedAt?: string;
221
+ revokedAt?: string;
222
+ expiresAt?: string;
223
+ }
153
224
  /**
154
225
  * Parameters accepted by {@link NeonApi.getConnectionUri}. `branchId` and `endpointId`
155
226
  * are optional — when omitted, the API uses the project's default branch and that
@@ -229,33 +300,44 @@ interface NeonApi {
229
300
  createBranchBucket(projectId: string, branchId: string, input: CreateBucketInput): Promise<NeonBucketSnapshot>;
230
301
  /** Delete a bucket from a branch. */
231
302
  deleteBranchBucket(projectId: string, branchId: string, bucketName: string): Promise<void>;
232
- /** List functions on a branch. */
233
- listBranchFunctions(projectId: string, branchId: string): Promise<NeonFunctionSnapshot[]>;
234
303
  /**
235
- * Create a function on a branch. The function has no deployment until code is deployed
236
- * to it with {@link deployBranchFunction}.
304
+ * Fetch the branch's S3-compatible object-storage connection details (endpoint, region,
305
+ * path-style). Returns `null` when storage is not enabled for the branch (the API's 404
306
+ * `BranchStorageNotEnabled`). Used by `fetchEnv` to populate the `AWS_*` storage env
307
+ * alongside the minted credential's access keys.
237
308
  */
238
- createBranchFunction(projectId: string, branchId: string, input: {
239
- slug: string;
240
- name: string;
241
- }): Promise<NeonFunctionSnapshot>;
309
+ getProjectBranchStorage(projectId: string, branchId: string): Promise<NeonBranchStorageSnapshot | null>;
310
+ /** List functions on a branch. */
311
+ listBranchFunctions(projectId: string, branchId: string): Promise<NeonFunctionSnapshot[]>;
242
312
  /** Delete a function (by slug) from a branch. */
243
313
  deleteBranchFunction(projectId: string, branchId: string, slug: string): Promise<void>;
244
314
  /**
245
- * Deploy a built bundle to a function. The newest deployment becomes active. The
246
- * `bundle` is built (esbuild + zip) by the caller and passed in as bytes.
315
+ * Deploy a built bundle to a function, creating the function if it does not yet exist —
316
+ * Neon has no separate create endpoint, so the first deployment to a slug creates the
317
+ * function. The newest deployment becomes active. The `bundle` is built (esbuild + zip)
318
+ * by the caller and passed in as bytes.
247
319
  */
248
320
  deployBranchFunction(projectId: string, branchId: string, slug: string, input: DeployFunctionInput): Promise<NeonFunctionDeploymentSnapshot>;
249
321
  /**
250
- * Whether the AI Gateway is enabled on a branch. Toggle-style, like Neon Auth / Data
251
- * API: used by both `fetchEnv` (to decide visibility) and `pushConfig` (to diff intent).
322
+ * Mint a new scoped service credential on a branch (`POST .../credentials`). The
323
+ * returned {@link NeonCredentialSecret} carries `apiToken` + `s3SecretAccessKey`
324
+ * **once** — persist them immediately. Used by `fetchEnv` / `env pull` to issue the
325
+ * unified credential for the branch's enabled Preview features (object storage, AI
326
+ * Gateway, Functions).
327
+ */
328
+ createCredential(projectId: string, branchId: string, input: CreateCredentialInput): Promise<NeonCredentialSecret>;
329
+ /**
330
+ * List the secret-free metadata for credentials issued on a branch
331
+ * (`GET .../credentials`). Used to report issued credentials (e.g. `config status`)
332
+ * and to verify a persisted credential still exists / isn't revoked.
333
+ */
334
+ listCredentials(projectId: string, branchId: string): Promise<NeonCredentialMeta[]>;
335
+ /**
336
+ * Revoke (soft-delete) a credential by its `tokenId` (`DELETE .../credentials/{id}`).
337
+ * Idempotent.
252
338
  */
253
- getAiGatewayEnabled(projectId: string, branchId: string): Promise<boolean>;
254
- /** Enable the AI Gateway on a branch. Idempotent. */
255
- enableAiGateway(projectId: string, branchId: string): Promise<void>;
256
- /** Disable the AI Gateway on a branch. Idempotent. */
257
- disableAiGateway(projectId: string, branchId: string): Promise<void>;
339
+ revokeCredential(projectId: string, branchId: string, tokenId: string): Promise<void>;
258
340
  }
259
341
  //#endregion
260
- export { CreateBranchInput, CreateBucketInput, CreateProjectInput, DeployFunctionInput, GetConnectionUriInput, NeonApi, NeonAuthSnapshot, NeonBranchSnapshot, NeonBucketSnapshot, NeonDataApiSnapshot, NeonDatabaseSnapshot, NeonEndpointSnapshot, NeonFunctionDeploymentSnapshot, NeonFunctionSnapshot, NeonProjectSnapshot, NeonRoleSnapshot, UpdateBranchInput };
342
+ export { CreateBranchInput, CreateBucketInput, CreateCredentialInput, CreateProjectInput, DeployFunctionInput, GetConnectionUriInput, NeonApi, NeonAuthSnapshot, NeonBranchSnapshot, NeonBranchStorageSnapshot, NeonBucketSnapshot, NeonCredentialMeta, NeonCredentialSecret, NeonDataApiSnapshot, NeonDatabaseSnapshot, NeonEndpointSnapshot, NeonFunctionDeploymentSnapshot, NeonFunctionSnapshot, NeonProjectSnapshot, NeonRoleSnapshot, UpdateBranchInput };
261
343
  //# sourceMappingURL=neon-api.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"neon-api.d.ts","names":[],"sources":["../../src/lib/neon-api.ts"],"mappings":";;;;;;AAWA;AASA;AAUA;AAAqC,UAnBpB,mBAAA,CAmBoB;MAIb,MAAA;MACA,EAAA,MAAA;UACP,EAAA,MAAA;EAAe,SAAA,EAAA,MAAA;EAGf,KAAA,CAAA,EAAA,MAAA;EAaA,uBAAiB,CAAA,EAnCP,eAyCR;AAGnB;AAYiB,UArDA,kBAAA,CAqDgB;EAUhB,EAAA,EAAA,MAAA;EAWA,IAAA,EAAA,MAAA;EAgBA,QAAA,CAAA,EAAA,MAAA;EASA,SAAA,EAAA,OAAA;EAQA;EASA,SAAA,EAAA,OAAA;EAkBA,SAAA,CAAA,EAAA,MAAA;;AACR,UA7HQ,oBAAA,CA6HR;MACC,MAAA;UACI,EAAA,MAAA;EAAM,IAAA,EAAA,WAAA,GAAA,YAAA;EAMH,qBAAA,EAjIO,eAiIuB,CAAA,uBAAA,CAAA;EAW9B,qBAAA,EA3IO,eA2Ic,CAAA,uBAAA,CAAA;EAcrB,cAAO,EAxJP,eAwJO,CAAA,gBAAA,CAAA;;AAC2B,UAtJlC,kBAAA,CAsJkC;MAAR,EAAA,MAAA;UACH,EAAA,MAAA;WAAR,CAAA,EAAA,MAAA;OACV,CAAA,EAAA,MAAA;yBAA6B,CAAA,EAnJxB,eAmJwB;;;;;mBAMT,CAAA,EAAA,MAAA;;AAGjC,UApJQ,iBAAA,CAoJR;MAEC,EAAA,MAAA;UACG,CAAA,EAAA,MAAA;WAFT,CAAA,EAAA,MAAA;;WAQQ,CAAA,EAAA,OAAA;iBAAR,CAAA,EAvJe,eAuJf;;AAE+B,UAtJlB,iBAAA,CAsJkB;MAIvB,CAAA,EAAA,MAAA;WACA,CAAA,EAAA,MAAA,GAAA,IAAA;;WAMA,CAAA,EAAA,OAAA;;;;;;;AAyBR,UA9Ka,gBAAA,CA8Kb;MAWQ,EAAA,MAAA;UAAR,EAAA,MAAA;;WAWA,EAAA,OAAA;;;;;AAyBK,UAnNQ,oBAAA,CAmNR;MACG,EAAA,MAAA;UAAR,EAAA,MAAA;;WAeQ,EAAA,MAAA;;;;;;AA4BA,UApPK,gBAAA,CAoPL;;WAQ+C,EAAA,MAAA;;sBAMH,CAAA,EAAA,MAAA;EAAO;;;;;;;;;;UAlP9C,mBAAA;;;;;;;;UASA,kBAAA;;eAEH;;;;;UAMG,iBAAA;;gBAEF;;;;;;UAOE,oBAAA;;;;;;;;;;;;;;;;;UAkBA,mBAAA;UACR;WACC;eACI;;;;;UAMG,8BAAA;;;;;;;;;;UAWA,qBAAA;;;;;;;;;;;;;UAcA,OAAA;;;MAC0B,QAAQ;iCACnB,QAAQ;uBAClB,qBAAqB,QAAQ;;;8BAGC;MAChD,QAAQ;mCAEsB,QAAQ;yCAGjC,oBACL;YACM;eACG;;2DAKJ,oBACL,QAAQ;oCAEuB,QAAQ;kEAI/B,kBACR,QAAQ;;wDAMR,QAAQ;;4DAMR,QAAQ;;;;;6CAQH,wBACL;;;;;;;;oDAUA,QAAQ;;;;;;;;MAWR,QAAQ;;;;;;6EAWR,QAAQ;;;;;;yFAWR,QAAQ;;0DAQR,QAAQ;;iEAMH,oBACL,QAAQ;;+EAOR;;4DAQA,QAAQ;;;;;;;;MAUR,QAAQ;;2EAOR;;;;;iFAUK,sBACL,QAAQ;;;;;4DAQ+C;;wDAGJ;;yDAGC"}
1
+ {"version":3,"file":"neon-api.d.ts","names":[],"sources":["../../src/lib/neon-api.ts"],"mappings":";;;;;;AAaA;AASA;AAUA;AAAqC,UAnBpB,mBAAA,CAmBoB;MAIb,MAAA;MACA,EAAA,MAAA;UACP,EAAA,MAAA;EAAe,SAAA,EAAA,MAAA;EAGf,KAAA,CAAA,EAAA,MAAA;EAaA,uBAAiB,CAAA,EAnCP,eAyCR;AAGnB;AAYiB,UArDA,kBAAA,CAqDgB;EAUhB,EAAA,EAAA,MAAA;EAWA,IAAA,EAAA,MAAA;EAgBA,QAAA,CAAA,EAAA,MAAA;EASA,SAAA,EAAA,OAAA;EAaA;EAYA,SAAA,EAAA,OAAA;EASA,SAAA,CAAA,EAAA,MAAA;AAkBjB;AAAoC,UA7InB,oBAAA,CA6ImB;MAC3B,MAAA;UACC,EAAA,MAAA;MACI,EAAA,WAAA,GAAA,YAAA;EAAM,qBAAA,EA5II,eA4IJ,CAAA,uBAAA,CAAA;EAMH,qBAAA,EAjJO,eAiJuB,CAAA,uBAAA,CAAA;EAkB9B,cAAA,EAlKA,eAkKqB,CAAA,gBAAA,CAAA;;AAC7B,UAhKQ,kBAAA,CAgKR;MACO,EAAA,MAAA;EAAuB,QAAA,EAAA,MAAA;EAatB,SAAA,CAAA,EAAA,MAAA;EAmBA,KAAA,CAAA,EAAA,MAAA;EAAkB,uBAAA,CAAA,EA5LR,eA4LQ;;;AAKI;AAcvC;EAciB,iBAAO,CAAA,EAAA,MAAA;;AAC2B,UAtNlC,iBAAA,CAsNkC;MAAR,EAAA,MAAA;UACH,CAAA,EAAA,MAAA;WAAR,CAAA,EAAA,MAAA;;WACmB,CAAA,EAAA,OAAA;iBAAR,CAAA,EAlNxB,eAkNwB;;AAI/B,UAnNK,iBAAA,CAmNL;MAAR,CAAA,EAAA,MAAA;WAEsC,CAAA,EAAA,MAAA,GAAA,IAAA;;WAGjC,CAAA,EAAA,OAAA;;;;;;;AAWkC,UAvN1B,gBAAA,CAuN0B;MAAR,EAAA,MAAA;UAIvB,EAAA,MAAA;;WACR,EAAA,OAAA;;;;;AAoBK,UAtOQ,oBAAA,CAsOR;MACL,EAAA,MAAA;UAUQ,EAAA,MAAA;;WAWA,EAAA,MAAA;;;;;;AA8BA,UA/QK,gBAAA,CA+QL;;WAMH,EAAA,MAAA;;sBACL,CAAA,EAAA,MAAA;;iBAkBQ,CAAA,EAAA,MAAA;;SAQA,EAAA,MAAA;;SAOR,CAAA,EAAA,MAAA;;;;;AAqCQ,UA5UK,mBAAA,CA4UL;;KAUA,EAAA,MAAA;;;AAUD;;;UAvVM,kBAAA;;eAEH;;;;;;;;;;UAWG,yBAAA;;;;;;;;;;;UAYA,iBAAA;;gBAEF;;;;;;UAOE,oBAAA;;;;;;;;;;;;;;;;;UAkBA,mBAAA;UACR;WACC;eACI;;;;;UAMG,8BAAA;;;;;;;;;;;;;;;UAkBA,qBAAA;UACR;iBACO;;;;;;;;;;;;UAaC,oBAAA;;;;;;;;UAQR;;;;;;;;;;UAWQ,kBAAA;;;;UAIR;iBACO;;;;;;;;;;;;;UAcC,qBAAA;;;;;;;;;;;;;UAcA,OAAA;;;MAC0B,QAAQ;iCACnB,QAAQ;uBAClB,qBAAqB,QAAQ;;;8BAGC;MAChD,QAAQ;mCAEsB,QAAQ;yCAGjC,oBACL;YACM;eACG;;2DAKJ,oBACL,QAAQ;oCAEuB,QAAQ;kEAI/B,kBACR,QAAQ;;wDAMR,QAAQ;;4DAMR,QAAQ;;;;;6CAQH,wBACL;;;;;;;;oDAUA,QAAQ;;;;;;;;MAWR,QAAQ;;;;;;6EAWR,QAAQ;;;;;;yFAWR,QAAQ;;0DAQR,QAAQ;;iEAMH,oBACL,QAAQ;;+EAOR;;;;;;;gEAWA,QAAQ;;4DAQR,QAAQ;;2EAOR;;;;;;;iFAYK,sBACL,QAAQ;;;;;;;;+DAuBH,wBACL,QAAQ;;;;;;wDAUR,QAAQ;;;;;0EAUR"}
@@ -1 +1 @@
1
- {"version":3,"file":"patterns.js","names":[],"sources":["../../src/lib/patterns.ts"],"sourcesContent":["/**\n * Branch-name pattern helpers. Patterns are GitHub-branch-protection style globs:\n * `*` matches one or more characters within a name segment. `**` is not supported (branch\n * names cannot contain `/` in Neon).\n */\n\n/** Returns `true` when the pattern contains an unescaped wildcard. */\nexport function isWildcardPattern(pattern: string): boolean {\n\treturn pattern.includes(\"*\");\n}\n\n/**\n * Returns `true` if `branchName` matches `pattern`. Anchors at both ends.\n */\nexport function matchPattern(pattern: string, branchName: string): boolean {\n\tconst regex = patternToRegex(pattern);\n\treturn regex.test(branchName);\n}\n\n/**\n * Substitute every `*` in `pattern` with `replacement`. When the pattern has no `*`, the\n * replacement is appended with a `-` separator so the caller still gets a unique name.\n *\n * Pure function. The returned string is **not** validated — callers compose it from\n * sources that already passed {@link validatePattern} (the pattern) and\n * {@link normalizeGitBranch}-style sanitization (the replacement).\n *\n * @example\n * fillPattern(\"preview-*\", \"andre-feature-a1b2c3\") // → \"preview-andre-feature-a1b2c3\"\n * fillPattern(\"feat-*-staging\", \"x\") // → \"feat-x-staging\"\n * fillPattern(\"specific\", \"x\") // → \"specific-x\"\n */\nexport function fillPattern(pattern: string, replacement: string): string {\n\tif (!isWildcardPattern(pattern)) return `${pattern}-${replacement}`;\n\treturn pattern.replaceAll(\"*\", replacement);\n}\n\n/**\n * Validate a branch pattern. Pure — returns either `{ ok: true }` or `{ error: string }`.\n *\n * Rules:\n * - Non-empty after trim, no leading/trailing whitespace.\n * - Length <= 256 (Neon branch name max).\n * - May contain `*`, ASCII letters/digits, and the punctuation Neon allows in branch names:\n * `-`, `_`, `.`, `/`. Whitespace and regex meta-characters other than `*` are rejected.\n */\nexport function validatePattern(\n\tpattern: string,\n): { ok: true } | { error: string } {\n\tconst trimmed = pattern.trim();\n\tif (trimmed === \"\") return { error: \"branch pattern is empty\" };\n\tif (trimmed !== pattern) {\n\t\treturn {\n\t\t\terror: `branch pattern has leading or trailing whitespace: ${JSON.stringify(pattern)}`,\n\t\t};\n\t}\n\tif (trimmed.length > 256) {\n\t\treturn {\n\t\t\terror: `branch pattern exceeds 256 characters: ${trimmed.length} chars`,\n\t\t};\n\t}\n\tif (!/^[A-Za-z0-9._\\-*/]+$/.test(trimmed)) {\n\t\treturn {\n\t\t\terror: `branch pattern contains unsupported characters; allowed: letters, digits, '-', '_', '.', '/', '*' (got ${JSON.stringify(pattern)})`,\n\t\t};\n\t}\n\treturn { ok: true };\n}\n\nfunction patternToRegex(pattern: string): RegExp {\n\tlet body = \"\";\n\tfor (const ch of pattern) {\n\t\tif (ch === \"*\") {\n\t\t\tbody += \".*\";\n\t\t} else if (REGEX_META.has(ch)) {\n\t\t\tbody += `\\\\${ch}`;\n\t\t} else {\n\t\t\tbody += ch;\n\t\t}\n\t}\n\treturn new RegExp(`^${body}$`);\n}\n\nconst REGEX_META = new Set([\n\t\".\",\n\t\"+\",\n\t\"?\",\n\t\"^\",\n\t\"$\",\n\t\"(\",\n\t\")\",\n\t\"[\",\n\t\"]\",\n\t\"{\",\n\t\"}\",\n\t\"|\",\n\t\"\\\\\",\n]);\n"],"mappings":";;;;;;;AAOA,SAAgB,kBAAkB,SAA0B;CAC3D,OAAO,QAAQ,SAAS,GAAG;AAC5B;;;;AAKA,SAAgB,aAAa,SAAiB,YAA6B;CAE1E,OADc,eAAe,OAClB,EAAE,KAAK,UAAU;AAC7B;;;;;;;;;;;;;;AAeA,SAAgB,YAAY,SAAiB,aAA6B;CACzE,IAAI,CAAC,kBAAkB,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG;CACtD,OAAO,QAAQ,WAAW,KAAK,WAAW;AAC3C;;;;;;;;;;AAWA,SAAgB,gBACf,SACmC;CACnC,MAAM,UAAU,QAAQ,KAAK;CAC7B,IAAI,YAAY,IAAI,OAAO,EAAE,OAAO,0BAA0B;CAC9D,IAAI,YAAY,SACf,OAAO,EACN,OAAO,sDAAsD,KAAK,UAAU,OAAO,IACpF;CAED,IAAI,QAAQ,SAAS,KACpB,OAAO,EACN,OAAO,0CAA0C,QAAQ,OAAO,QACjE;CAED,IAAI,CAAC,uBAAuB,KAAK,OAAO,GACvC,OAAO,EACN,OAAO,0GAA0G,KAAK,UAAU,OAAO,EAAE,GAC1I;CAED,OAAO,EAAE,IAAI,KAAK;AACnB;AAEA,SAAS,eAAe,SAAyB;CAChD,IAAI,OAAO;CACX,KAAK,MAAM,MAAM,SAChB,IAAI,OAAO,KACV,QAAQ;MACF,IAAI,WAAW,IAAI,EAAE,GAC3B,QAAQ,KAAK;MAEb,QAAQ;CAGV,OAAO,IAAI,OAAO,IAAI,KAAK,EAAE;AAC9B;AAEA,MAAM,aAAa,IAAI,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC"}
1
+ {"version":3,"file":"patterns.js","names":[],"sources":["../../src/lib/patterns.ts"],"sourcesContent":["/**\n * Branch-name pattern helpers. Patterns are GitHub-branch-protection style globs:\n * `*` matches one or more characters within a name segment. `**` is not supported (branch\n * names cannot contain `/` in Neon).\n */\n\n/** Returns `true` when the pattern contains an unescaped wildcard. */\nexport function isWildcardPattern(pattern: string): boolean {\n\treturn pattern.includes(\"*\");\n}\n\n/**\n * Returns `true` if `branchName` matches `pattern`. Anchors at both ends.\n */\nexport function matchPattern(pattern: string, branchName: string): boolean {\n\tconst regex = patternToRegex(pattern);\n\treturn regex.test(branchName);\n}\n\n/**\n * Substitute every `*` in `pattern` with `replacement`. When the pattern has no `*`, the\n * replacement is appended with a `-` separator so the caller still gets a unique name.\n *\n * Pure function. The returned string is **not** validated — callers compose it from\n * sources that already passed {@link validatePattern} (the pattern) and\n * {@link normalizeGitBranch}-style sanitization (the replacement).\n *\n * @example\n * fillPattern(\"preview-*\", \"andre-feature-a1b2c3\") // → \"preview-andre-feature-a1b2c3\"\n * fillPattern(\"feat-*-staging\", \"x\") // → \"feat-x-staging\"\n * fillPattern(\"specific\", \"x\") // → \"specific-x\"\n */\nexport function fillPattern(pattern: string, replacement: string): string {\n\tif (!isWildcardPattern(pattern)) return `${pattern}-${replacement}`;\n\treturn pattern.replaceAll(\"*\", replacement);\n}\n\n/**\n * Validate a branch pattern. Pure — returns either `{ ok: true }` or `{ error: string }`.\n *\n * Rules:\n * - Non-empty after trim, no leading/trailing whitespace.\n * - Length <= 256 (Neon branch name max).\n * - May contain `*`, ASCII letters/digits, and the punctuation Neon allows in branch names:\n * `-`, `_`, `.`, `/`. Whitespace and regex meta-characters other than `*` are rejected.\n */\nexport function validatePattern(\n\tpattern: string,\n): { ok: true } | { error: string } {\n\tconst trimmed = pattern.trim();\n\tif (trimmed === \"\") return { error: \"branch pattern is empty\" };\n\tif (trimmed !== pattern) {\n\t\treturn {\n\t\t\terror: `branch pattern has leading or trailing whitespace: ${JSON.stringify(pattern)}`,\n\t\t};\n\t}\n\tif (trimmed.length > 256) {\n\t\treturn {\n\t\t\terror: `branch pattern exceeds 256 characters: ${trimmed.length} chars`,\n\t\t};\n\t}\n\tif (!/^[A-Za-z0-9._\\-*/]+$/.test(trimmed)) {\n\t\treturn {\n\t\t\terror: `branch pattern contains unsupported characters; allowed: letters, digits, '-', '_', '.', '/', '*' (got ${JSON.stringify(pattern)})`,\n\t\t};\n\t}\n\treturn { ok: true };\n}\n\nfunction patternToRegex(pattern: string): RegExp {\n\tlet body = \"\";\n\tfor (const ch of pattern) {\n\t\tif (ch === \"*\") {\n\t\t\tbody += \".*\";\n\t\t} else if (REGEX_META.has(ch)) {\n\t\t\tbody += `\\\\${ch}`;\n\t\t} else {\n\t\t\tbody += ch;\n\t\t}\n\t}\n\treturn new RegExp(`^${body}$`);\n}\n\nconst REGEX_META = new Set([\n\t\".\",\n\t\"+\",\n\t\"?\",\n\t\"^\",\n\t\"$\",\n\t\"(\",\n\t\")\",\n\t\"[\",\n\t\"]\",\n\t\"{\",\n\t\"}\",\n\t\"|\",\n\t\"\\\\\",\n]);\n"],"mappings":";;;;;;;AAOA,SAAgB,kBAAkB,SAA0B;CAC3D,OAAO,QAAQ,SAAS,GAAG;AAC5B;;;;AAKA,SAAgB,aAAa,SAAiB,YAA6B;CAE1E,OADc,eAAe,OAClB,CAAC,CAAC,KAAK,UAAU;AAC7B;;;;;;;;;;;;;;AAeA,SAAgB,YAAY,SAAiB,aAA6B;CACzE,IAAI,CAAC,kBAAkB,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG;CACtD,OAAO,QAAQ,WAAW,KAAK,WAAW;AAC3C;;;;;;;;;;AAWA,SAAgB,gBACf,SACmC;CACnC,MAAM,UAAU,QAAQ,KAAK;CAC7B,IAAI,YAAY,IAAI,OAAO,EAAE,OAAO,0BAA0B;CAC9D,IAAI,YAAY,SACf,OAAO,EACN,OAAO,sDAAsD,KAAK,UAAU,OAAO,IACpF;CAED,IAAI,QAAQ,SAAS,KACpB,OAAO,EACN,OAAO,0CAA0C,QAAQ,OAAO,QACjE;CAED,IAAI,CAAC,uBAAuB,KAAK,OAAO,GACvC,OAAO,EACN,OAAO,0GAA0G,KAAK,UAAU,OAAO,EAAE,GAC1I;CAED,OAAO,EAAE,IAAI,KAAK;AACnB;AAEA,SAAS,eAAe,SAAyB;CAChD,IAAI,OAAO;CACX,KAAK,MAAM,MAAM,SAChB,IAAI,OAAO,KACV,QAAQ;MACF,IAAI,WAAW,IAAI,EAAE,GAC3B,QAAQ,KAAK;MAEb,QAAQ;CAGV,OAAO,IAAI,OAAO,IAAI,KAAK,EAAE;AAC9B;AAEA,MAAM,aAAa,IAAI,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC"}
@@ -45,7 +45,6 @@ declare const functionDefSchema: z.ZodObject<{
45
45
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
46
46
  dev: z.ZodOptional<z.ZodObject<{
47
47
  port: z.ZodOptional<z.ZodNumber>;
48
- portless: z.ZodOptional<z.ZodBoolean>;
49
48
  }, z.core.$strict>>;
50
49
  }, z.core.$strict>;
51
50
  /** Static definition of a bucket (existence). Name is the record key. */
@@ -63,7 +62,6 @@ declare const previewInputSchema: z.ZodObject<{
63
62
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
64
63
  dev: z.ZodOptional<z.ZodObject<{
65
64
  port: z.ZodOptional<z.ZodNumber>;
66
- portless: z.ZodOptional<z.ZodBoolean>;
67
65
  }, z.core.$strict>>;
68
66
  }, z.core.$strict>>>;
69
67
  buckets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -117,7 +115,6 @@ declare const configInputSchema: z.ZodObject<{
117
115
  env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
118
116
  dev: z.ZodOptional<z.ZodObject<{
119
117
  port: z.ZodOptional<z.ZodNumber>;
120
- portless: z.ZodOptional<z.ZodBoolean>;
121
118
  }, z.core.$strict>>;
122
119
  }, z.core.$strict>>>;
123
120
  buckets: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","names":[],"sources":["../../src/lib/schema.ts"],"mappings":";;;;;;AAgBA;;;;;;;;;;cAAa,uBAAqB,CAAA,CAAA;;;;;;cAiDrB,qBAAmB,CAAA,CAAA;;;;cAKnB,0BAAwB,CAAA,CAAA,mBAAA,CAAA,CAAA,YAAA,CAAA,CAAA;;;cAKxB,sBAAoB,CAAA,CAAA;iBA3DC,eAAA,YAAA,CAAA;IAAA,qBAAA,eAAA,WAAA,CAAA,SAAA,aAAA,CAAA,IAAA,CAAA,cAAA,CAAA,GAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;IAiDrB,qBAEX,eAAA,WAAA,CAAA,SAAA,aAAA,CAAA,IAAA,CAAA,cAAA,CAAA,GAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;IAAA,cAAA,eAAA,WAAA,CAAA,SAAA,aAAA,CAAA,KAAA,CAAA,aAAA,aAAA,CAAA,CAAA,CAAA;;;;;AAF8B;AAKhC;;AAAqC,cAyDxB,iBAzDwB,EAyDP,CAAA,CAAA,SAzDO,CAAA;;;;KAAA,eAAA,YAAA,CAAA;IAAA,IAAA,eAAA,YAAA,CAAA;IAAA,QAAA,eAAA,aAAA,CAAA;EAKxB,CAAA,gBAAA,CAAA,CAAA;CAEX,gBAAA,CAAA;;cA0DW,iBAAe,CAAA,CAAA;;;;cAOf,oBAAkB,CAAA,CAAA;;;;;;;;;;;;;;;;;;cAOlB,sBAAoB,CAAA,CAAA;;iBA1EA,CAAA;AAAA;AAoDjC;;;cAmCa,oBAAkB,CAAA,CAAA;;;;;;;;;;;;;MAnCD,OAAA,eAAA,aAAA,CAAA,UAAA,CAAA,CAAA;IAAA,CAAA,gBAAA,CAAA,CAAA,CAAA;EAQjB,CAAA,gBAAA,CAIX,CAAA;CAAA,gBAAA,CAAA;;;;;;AAJ0B,cAyDf,iBAzDe,EAyDE,CAAA,CAAA,SAzDF,CAAA;EAAA,IAAA,eAAA,WAAA,CAAA,SAAA,aAAA,aAAA,CAAA;IAOf,OAAA,eAIX,aAAA,CAAA;EAAA,CAAA,gBAAA,CAAA,CAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0Fc,eAAA,QAAuB,CAAA,CAAE"}
1
+ {"version":3,"file":"schema.d.ts","names":[],"sources":["../../src/lib/schema.ts"],"mappings":";;;;;;AAgBA;;;;;;;;;;cAAa,uBAAqB,CAAA,CAAA;;;;;;cAiDrB,qBAAmB,CAAA,CAAA;;;;cAKnB,0BAAwB,CAAA,CAAA,mBAAA,CAAA,CAAA,YAAA,CAAA,CAAA;;;cAKxB,sBAAoB,CAAA,CAAA;iBA3DC,eAAA,YAAA,CAAA;IAAA,qBAAA,eAAA,WAAA,CAAA,SAAA,aAAA,CAAA,IAAA,CAAA,cAAA,CAAA,GAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;IAiDrB,qBAEX,eAAA,WAAA,CAAA,SAAA,aAAA,CAAA,IAAA,CAAA,cAAA,CAAA,GAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,cAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;IAAA,cAAA,eAAA,WAAA,CAAA,SAAA,aAAA,CAAA,KAAA,CAAA,aAAA,aAAA,CAAA,CAAA,CAAA;;;;;AAF8B;AAKhC;;AAAqC,cAsDxB,iBAtDwB,EAsDP,CAAA,CAAA,SAtDO,CAAA;;;;KAAA,eAAA,YAAA,CAAA;IAAA,IAAA,eAAA,YAAA,CAAA;EAAA,CAAA,gBAAA,CAAA,CAAA;AAKrC,CAAA,gBAAa,CAAA;;cAyDA,iBAAe,CAAA,CAAA;;;;cAOf,oBAAkB,CAAA,CAAA;;;;;;;;;;;;;;;;;cAOlB,sBAAoB,CAAA,CAAA;;;;;AAvEA;AAiDjC;AAKE,cA8BW,kBA9BX,EA8B6B,CAAA,CAAA,SA9B7B,CAAA;;;;;;;;;;;;;MAL4B,OAAA,eAAA,aAAA,CAAA,UAAA,CAAA,CAAA;IAAA,CAAA,gBAAA,CAAA,CAAA,CAAA;EAQjB,CAAA,gBAAA,CAIX,CAAA;CAAA,gBAAA,CAAA;;;;;;AAJ0B,cAyDf,iBAzDe,EAyDE,CAAA,CAAA,SAzDF,CAAA;EAAA,IAAA,eAAA,WAAA,CAAA,SAAA,aAAA,aAAA,CAAA;IAOf,OAAA,eAIX,aAAA,CAAA;EAAA,CAAA,gBAAA,CAAA,CAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0Fc,eAAA,QAAuB,CAAA,CAAE"}
@@ -78,15 +78,10 @@ const functionEnvSchema = z.record(z.string(), z.string());
78
78
  */
79
79
  const devPortSchema = z.number().int().min(1).max(65535);
80
80
  /**
81
- * Local-dev settings for a function (`neon dev` only; never affects deploy). `port` and
82
- * `portless` are independent: when `portless` is true, portless assigns the port itself
83
- * (so `port` is ignored); otherwise `port` is bound exactly when set, or a free port is
84
- * found when omitted.
81
+ * Local-dev settings for a function (`neon dev` only; never affects deploy). `port` is bound
82
+ * exactly when set (and `neon dev` fails if it is taken), or a free port is found when omitted.
85
83
  */
86
- const functionDevConfigSchema = z.strictObject({
87
- port: devPortSchema.optional(),
88
- portless: z.boolean().optional()
89
- });
84
+ const functionDevConfigSchema = z.strictObject({ port: devPortSchema.optional() });
90
85
  const runtimeSchema = z.literal("nodejs24");
91
86
  /**
92
87
  * Static definition of a function (existence). The slug is the record key (validated by
@@ -190,6 +185,10 @@ function normaliseIssueMessage(issue) {
190
185
  const formatted = keys.map((k) => JSON.stringify(k)).join(", ");
191
186
  return `unknown key${keys.length === 1 ? "" : "s"}: ${formatted}`;
192
187
  }
188
+ if (issue.code === "invalid_key") {
189
+ const reasons = issue.issues.map((nested) => nested.message).filter((message) => message.length > 0);
190
+ if (reasons.length > 0) return reasons.join("; ");
191
+ }
193
192
  return issue.message;
194
193
  }
195
194
  //#endregion