@neondatabase/config 0.7.2 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -6,7 +6,7 @@ interface CreateNeonAuthRestInput {
|
|
|
6
6
|
database_name?: string;
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
|
-
* Adapt `@
|
|
9
|
+
* Adapt `@neon/sdk` (raw layer) to the narrow {@link NeonApi} façade used by the rest of
|
|
10
10
|
* this package. Constructs are restricted to whole-object read/write of just the fields we
|
|
11
11
|
* model in {@link Config}; anything else stays untouched on the remote.
|
|
12
12
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"neon-api-real.d.ts","names":[],"sources":["../../src/lib/neon-api-real.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"neon-api-real.d.ts","names":[],"sources":["../../src/lib/neon-api-real.ts"],"mappings":";;;UAiRU,uBAAA;;EAAA,aAAA,CAAA,EAAA,MAAA;AAeV;AA4CC;AAeD;;;;AAES,iBA7DO,iBAAA,CA6DP,OAAA,EAAA;QACE,EAAA,MAAA;SAAR,CAAA,EAAA,MAAA;EAAO;AAk9BV;AAiFA;AA6DA;AAoBA;EAAuC,aAAA,CAAA,EAAA;IAAQ,WAAA,CAAA,EAAA,MAAA;IAAsB,cAAA,CAAA,EAAA,MAAA;IAAQ,UAAA,CAAA,EAAA,MAAA;EAwBvD,CAAA;CAAY,CAAA,EA7rC9B,OA6rC8B;UA5pCxB,WAAA,CA4pC8B;aAAW,EAAA,MAAA;EAAO,cAAA,EAAA,MAAA;;;;;;;;;;iBA/oCpC,2BACX,QAAQ,YACV,cACN,QAAQ;;;;;;;;;;;;iBAk9BK,2BAAA;;;;;;;;;;;;iBAiFA,uBAAA;iBA6DA,uBAAA;;IAEZ;;;;;;;;;;;;iBAkBY,uBAAA,QAA+B,sBAAsB;;;;;;;;;;;iBAwB/C,YAAA,MAAkB,WAAW"}
|
|
@@ -2,9 +2,24 @@ import { ErrorCode, PlatformError } from "./errors.js";
|
|
|
2
2
|
import { formatSuspendTimeout, parseSuspendTimeout } from "./duration.js";
|
|
3
3
|
import { wrapNeonError } from "./wrap-neon-error.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
import {
|
|
5
|
+
import { createNeonClient } from "@neon/sdk";
|
|
6
|
+
import { createProject, createProjectBranch, createProjectBranchDataApi, getConnectionUri, getNeonAuth, getProject, getProjectBranchDataApi, listProjectBranchDatabases, listProjectBranchRoles, listProjectBranches, listProjectEndpoints, listProjects, updateProject, updateProjectBranch, updateProjectBranchDataApi, updateProjectEndpoint } from "@neon/sdk/raw";
|
|
6
7
|
//#region src/lib/neon-api-real.ts
|
|
7
8
|
const DEFAULT_NEON_API_BASE_URL = "https://console.neon.tech/api/v2";
|
|
9
|
+
/**
|
|
10
|
+
* Unwrap a `@neon/sdk` raw `{ data, error, response }` result into the bare body, throwing
|
|
11
|
+
* on a non-2xx response. The thrown shape (`{ response: { status, data } }`) deliberately
|
|
12
|
+
* matches what the package's REST fallbacks already throw, so {@link wrapNeonError} and the
|
|
13
|
+
* 423 {@link retryOnLocked} retry keep working unchanged across both transports.
|
|
14
|
+
*/
|
|
15
|
+
function unwrap(result) {
|
|
16
|
+
const response = result.response;
|
|
17
|
+
if (!response || !response.ok) throw { response: {
|
|
18
|
+
status: response?.status,
|
|
19
|
+
data: result.error
|
|
20
|
+
} };
|
|
21
|
+
return result.data;
|
|
22
|
+
}
|
|
8
23
|
const neonAuthResponseSchema = z.object({
|
|
9
24
|
auth_provider_project_id: z.string(),
|
|
10
25
|
pub_client_key: z.string().optional(),
|
|
@@ -129,16 +144,18 @@ const credentialMetaSchema = z.object({
|
|
|
129
144
|
});
|
|
130
145
|
const listCredentialsResponseSchema = z.object({ credentials: z.array(credentialMetaSchema) });
|
|
131
146
|
/**
|
|
132
|
-
* Adapt `@
|
|
147
|
+
* Adapt `@neon/sdk` (raw layer) to the narrow {@link NeonApi} façade used by the rest of
|
|
133
148
|
* this package. Constructs are restricted to whole-object read/write of just the fields we
|
|
134
149
|
* model in {@link Config}; anything else stays untouched on the remote.
|
|
135
150
|
*/
|
|
136
151
|
function createRealNeonApi(options) {
|
|
137
152
|
if (!options.apiKey || options.apiKey.trim() === "") throw new PlatformError(ErrorCode.MissingApiKey, ["createRealNeonApi requires a non-empty `apiKey`.", "Generate one at https://console.neon.tech/app/settings/api-keys and pass it as { apiKey: process.env.NEON_API_KEY }."].join(" "));
|
|
138
|
-
|
|
153
|
+
const client = createNeonClient({
|
|
139
154
|
apiKey: options.apiKey,
|
|
140
|
-
|
|
141
|
-
|
|
155
|
+
retries: 0,
|
|
156
|
+
...options.baseUrl ? { baseUrl: options.baseUrl } : {}
|
|
157
|
+
}).client;
|
|
158
|
+
return new RealNeonApi(client, {
|
|
142
159
|
maxAttempts: options.retryOnLocked?.maxAttempts ?? 12,
|
|
143
160
|
initialDelayMs: options.retryOnLocked?.initialDelayMs ?? 250,
|
|
144
161
|
maxDelayMs: options.retryOnLocked?.maxDelayMs ?? 5e3
|
|
@@ -204,13 +221,16 @@ var RealNeonApi = class {
|
|
|
204
221
|
const projects = [];
|
|
205
222
|
let cursor;
|
|
206
223
|
while (true) {
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
224
|
+
const body = unwrap(await listProjects({
|
|
225
|
+
client: this.client,
|
|
226
|
+
query: {
|
|
227
|
+
...filter.orgId ? { org_id: filter.orgId } : {},
|
|
228
|
+
...cursor ? { cursor } : {},
|
|
229
|
+
limit: 100
|
|
230
|
+
}
|
|
231
|
+
}));
|
|
232
|
+
projects.push(...body.projects);
|
|
233
|
+
const next = body.pagination?.next;
|
|
214
234
|
if (!next || next === cursor) break;
|
|
215
235
|
cursor = next;
|
|
216
236
|
}
|
|
@@ -219,7 +239,10 @@ var RealNeonApi = class {
|
|
|
219
239
|
}
|
|
220
240
|
async getProject(projectId) {
|
|
221
241
|
return this.call(`getProject(${projectId})`, async () => {
|
|
222
|
-
return projectToSnapshot((await
|
|
242
|
+
return projectToSnapshot(unwrap(await getProject({
|
|
243
|
+
client: this.client,
|
|
244
|
+
path: { project_id: projectId }
|
|
245
|
+
})).project);
|
|
223
246
|
}, { projectId });
|
|
224
247
|
}
|
|
225
248
|
async createProject(input) {
|
|
@@ -232,7 +255,10 @@ var RealNeonApi = class {
|
|
|
232
255
|
...input.defaultBranchName ? { branch: { name: input.defaultBranchName } } : {}
|
|
233
256
|
} };
|
|
234
257
|
return this.call(`createProject(${input.name})`, async () => {
|
|
235
|
-
return projectToSnapshot((await
|
|
258
|
+
return projectToSnapshot(unwrap(await createProject({
|
|
259
|
+
client: this.client,
|
|
260
|
+
body
|
|
261
|
+
})).project);
|
|
236
262
|
}, { mutating: true });
|
|
237
263
|
}
|
|
238
264
|
async updateProject(projectId, input) {
|
|
@@ -241,7 +267,11 @@ var RealNeonApi = class {
|
|
|
241
267
|
...input.defaultEndpointSettings ? { default_endpoint_settings: computeSettingsToDefaults(input.defaultEndpointSettings) } : {}
|
|
242
268
|
} };
|
|
243
269
|
return this.call(`updateProject(${projectId})`, async () => {
|
|
244
|
-
return projectToSnapshot((await
|
|
270
|
+
return projectToSnapshot(unwrap(await updateProject({
|
|
271
|
+
client: this.client,
|
|
272
|
+
path: { project_id: projectId },
|
|
273
|
+
body
|
|
274
|
+
})).project);
|
|
245
275
|
}, {
|
|
246
276
|
projectId,
|
|
247
277
|
mutating: true
|
|
@@ -252,13 +282,16 @@ var RealNeonApi = class {
|
|
|
252
282
|
const branches = [];
|
|
253
283
|
let cursor;
|
|
254
284
|
while (true) {
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
285
|
+
const body = unwrap(await listProjectBranches({
|
|
286
|
+
client: this.client,
|
|
287
|
+
path: { project_id: projectId },
|
|
288
|
+
query: {
|
|
289
|
+
limit: 100,
|
|
290
|
+
...cursor ? { cursor } : {}
|
|
291
|
+
}
|
|
292
|
+
}));
|
|
293
|
+
branches.push(...body.branches);
|
|
294
|
+
const next = body.pagination?.next;
|
|
262
295
|
if (!next || next === cursor) break;
|
|
263
296
|
cursor = next;
|
|
264
297
|
}
|
|
@@ -267,9 +300,9 @@ var RealNeonApi = class {
|
|
|
267
300
|
}
|
|
268
301
|
async createBranch(projectId, input) {
|
|
269
302
|
const endpointOptions = input.computeSettings ? {
|
|
270
|
-
type:
|
|
303
|
+
type: "read_write",
|
|
271
304
|
...computeSettingsToEndpointOptions(input.computeSettings)
|
|
272
|
-
} : { type:
|
|
305
|
+
} : { type: "read_write" };
|
|
273
306
|
const body = {
|
|
274
307
|
branch: {
|
|
275
308
|
name: input.name,
|
|
@@ -280,10 +313,14 @@ var RealNeonApi = class {
|
|
|
280
313
|
endpoints: [endpointOptions]
|
|
281
314
|
};
|
|
282
315
|
return this.call(`createBranch(${projectId}/${input.name})`, async () => {
|
|
283
|
-
const
|
|
316
|
+
const data = unwrap(await createProjectBranch({
|
|
317
|
+
client: this.client,
|
|
318
|
+
path: { project_id: projectId },
|
|
319
|
+
body
|
|
320
|
+
}));
|
|
284
321
|
return {
|
|
285
|
-
branch: branchToSnapshot(
|
|
286
|
-
endpoints: (
|
|
322
|
+
branch: branchToSnapshot(data.branch),
|
|
323
|
+
endpoints: (data.endpoints ?? []).map(endpointToSnapshot)
|
|
287
324
|
};
|
|
288
325
|
}, {
|
|
289
326
|
projectId,
|
|
@@ -296,7 +333,14 @@ var RealNeonApi = class {
|
|
|
296
333
|
if (input.expiresAt !== void 0) branch.expires_at = input.expiresAt;
|
|
297
334
|
if (input.protected !== void 0) branch.protected = input.protected;
|
|
298
335
|
return this.call(`updateBranch(${projectId}/${branchId})`, async () => {
|
|
299
|
-
return branchToSnapshot((await
|
|
336
|
+
return branchToSnapshot(unwrap(await updateProjectBranch({
|
|
337
|
+
client: this.client,
|
|
338
|
+
path: {
|
|
339
|
+
project_id: projectId,
|
|
340
|
+
branch_id: branchId
|
|
341
|
+
},
|
|
342
|
+
body: { branch }
|
|
343
|
+
})).branch);
|
|
300
344
|
}, {
|
|
301
345
|
projectId,
|
|
302
346
|
mutating: true
|
|
@@ -304,13 +348,23 @@ var RealNeonApi = class {
|
|
|
304
348
|
}
|
|
305
349
|
async listEndpoints(projectId) {
|
|
306
350
|
return this.call(`listEndpoints(${projectId})`, async () => {
|
|
307
|
-
return (await
|
|
351
|
+
return unwrap(await listProjectEndpoints({
|
|
352
|
+
client: this.client,
|
|
353
|
+
path: { project_id: projectId }
|
|
354
|
+
})).endpoints.map(endpointToSnapshot);
|
|
308
355
|
}, { projectId });
|
|
309
356
|
}
|
|
310
357
|
async updateEndpoint(projectId, endpointId, settings) {
|
|
311
358
|
const endpoint = computeSettingsToEndpointOptions(settings);
|
|
312
359
|
return this.call(`updateEndpoint(${projectId}/${endpointId})`, async () => {
|
|
313
|
-
return endpointToSnapshot((await
|
|
360
|
+
return endpointToSnapshot(unwrap(await updateProjectEndpoint({
|
|
361
|
+
client: this.client,
|
|
362
|
+
path: {
|
|
363
|
+
project_id: projectId,
|
|
364
|
+
endpoint_id: endpointId
|
|
365
|
+
},
|
|
366
|
+
body: { endpoint }
|
|
367
|
+
})).endpoint);
|
|
314
368
|
}, {
|
|
315
369
|
projectId,
|
|
316
370
|
mutating: true
|
|
@@ -318,32 +372,54 @@ var RealNeonApi = class {
|
|
|
318
372
|
}
|
|
319
373
|
async listBranchRoles(projectId, branchId) {
|
|
320
374
|
return this.call(`listBranchRoles(${projectId}/${branchId})`, async () => {
|
|
321
|
-
return (await
|
|
375
|
+
return unwrap(await listProjectBranchRoles({
|
|
376
|
+
client: this.client,
|
|
377
|
+
path: {
|
|
378
|
+
project_id: projectId,
|
|
379
|
+
branch_id: branchId
|
|
380
|
+
}
|
|
381
|
+
})).roles.map(roleToSnapshot);
|
|
322
382
|
}, { projectId });
|
|
323
383
|
}
|
|
324
384
|
async listBranchDatabases(projectId, branchId) {
|
|
325
385
|
return this.call(`listBranchDatabases(${projectId}/${branchId})`, async () => {
|
|
326
|
-
return (await
|
|
386
|
+
return unwrap(await listProjectBranchDatabases({
|
|
387
|
+
client: this.client,
|
|
388
|
+
path: {
|
|
389
|
+
project_id: projectId,
|
|
390
|
+
branch_id: branchId
|
|
391
|
+
}
|
|
392
|
+
})).databases.map(databaseToSnapshot);
|
|
327
393
|
}, { projectId });
|
|
328
394
|
}
|
|
329
395
|
async getConnectionUri(projectId, input) {
|
|
330
396
|
const op = `getConnectionUri(${projectId}/${input.databaseName}@${input.roleName}${input.pooled ? " pooled" : ""})`;
|
|
331
397
|
const pooled = input.pooled === true;
|
|
332
398
|
return this.call(op, async () => {
|
|
333
|
-
return { uri: (await
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
399
|
+
return { uri: unwrap(await getConnectionUri({
|
|
400
|
+
client: this.client,
|
|
401
|
+
path: { project_id: projectId },
|
|
402
|
+
query: {
|
|
403
|
+
database_name: input.databaseName,
|
|
404
|
+
role_name: input.roleName,
|
|
405
|
+
...input.branchId ? { branch_id: input.branchId } : {},
|
|
406
|
+
...input.endpointId ? { endpoint_id: input.endpointId } : {},
|
|
407
|
+
pooled
|
|
408
|
+
}
|
|
409
|
+
})).uri };
|
|
341
410
|
}, { projectId });
|
|
342
411
|
}
|
|
343
412
|
async getNeonAuth(projectId, branchId) {
|
|
344
413
|
try {
|
|
345
414
|
return await this.call(`getNeonAuth(${projectId}/${branchId})`, async () => {
|
|
346
|
-
|
|
415
|
+
const data = unwrap(await getNeonAuth({
|
|
416
|
+
client: this.client,
|
|
417
|
+
path: {
|
|
418
|
+
project_id: projectId,
|
|
419
|
+
branch_id: branchId
|
|
420
|
+
}
|
|
421
|
+
}));
|
|
422
|
+
return neonAuthResponseToSnapshot(neonAuthResponseSchema.parse(data));
|
|
347
423
|
}, { projectId });
|
|
348
424
|
} catch (err) {
|
|
349
425
|
if (err instanceof PlatformError && err.code === ErrorCode.NotFound) return null;
|
|
@@ -406,7 +482,14 @@ var RealNeonApi = class {
|
|
|
406
482
|
}
|
|
407
483
|
async getNeonDataApi(projectId, branchId, databaseName) {
|
|
408
484
|
try {
|
|
409
|
-
return await this.call(`getNeonDataApi(${projectId}/${branchId}/${databaseName})`, async () => dataApiSnapshotFromResponse(await
|
|
485
|
+
return await this.call(`getNeonDataApi(${projectId}/${branchId}/${databaseName})`, async () => dataApiSnapshotFromResponse(unwrap(await getProjectBranchDataApi({
|
|
486
|
+
client: this.client,
|
|
487
|
+
path: {
|
|
488
|
+
project_id: projectId,
|
|
489
|
+
branch_id: branchId,
|
|
490
|
+
database_name: databaseName
|
|
491
|
+
}
|
|
492
|
+
}))), { projectId });
|
|
410
493
|
} catch (err) {
|
|
411
494
|
if (err instanceof PlatformError && err.code === ErrorCode.NotFound) return null;
|
|
412
495
|
throw err;
|
|
@@ -415,7 +498,15 @@ var RealNeonApi = class {
|
|
|
415
498
|
async enableProjectBranchDataApi(projectId, branchId, databaseName, input) {
|
|
416
499
|
try {
|
|
417
500
|
return await this.call(`enableProjectBranchDataApi(${projectId}/${branchId}/${databaseName})`, async () => {
|
|
418
|
-
return { url: (await
|
|
501
|
+
return { url: unwrap(await createProjectBranchDataApi({
|
|
502
|
+
client: this.client,
|
|
503
|
+
path: {
|
|
504
|
+
project_id: projectId,
|
|
505
|
+
branch_id: branchId,
|
|
506
|
+
database_name: databaseName
|
|
507
|
+
},
|
|
508
|
+
body: dataApiCreateRequest(input)
|
|
509
|
+
})).url };
|
|
419
510
|
}, {
|
|
420
511
|
projectId,
|
|
421
512
|
mutating: true
|
|
@@ -430,8 +521,23 @@ var RealNeonApi = class {
|
|
|
430
521
|
}
|
|
431
522
|
async updateProjectBranchDataApi(projectId, branchId, databaseName, settings) {
|
|
432
523
|
return await this.call(`updateProjectBranchDataApi(${projectId}/${branchId}/${databaseName})`, async () => {
|
|
433
|
-
await
|
|
434
|
-
|
|
524
|
+
unwrap(await updateProjectBranchDataApi({
|
|
525
|
+
client: this.client,
|
|
526
|
+
path: {
|
|
527
|
+
project_id: projectId,
|
|
528
|
+
branch_id: branchId,
|
|
529
|
+
database_name: databaseName
|
|
530
|
+
},
|
|
531
|
+
body: { settings: dataApiSettingsToApi(settings) }
|
|
532
|
+
}));
|
|
533
|
+
return dataApiSnapshotFromResponse(unwrap(await getProjectBranchDataApi({
|
|
534
|
+
client: this.client,
|
|
535
|
+
path: {
|
|
536
|
+
project_id: projectId,
|
|
537
|
+
branch_id: branchId,
|
|
538
|
+
database_name: databaseName
|
|
539
|
+
}
|
|
540
|
+
})));
|
|
435
541
|
}, {
|
|
436
542
|
projectId,
|
|
437
543
|
mutating: true
|
|
@@ -796,7 +902,7 @@ function endpointToSnapshot(endpoint) {
|
|
|
796
902
|
return {
|
|
797
903
|
id: endpoint.id,
|
|
798
904
|
branchId: endpoint.branch_id,
|
|
799
|
-
type: endpoint.type ===
|
|
905
|
+
type: endpoint.type === "read_only" ? "read_only" : "read_write",
|
|
800
906
|
autoscalingLimitMinCu: endpoint.autoscaling_limit_min_cu,
|
|
801
907
|
autoscalingLimitMaxCu: endpoint.autoscaling_limit_max_cu,
|
|
802
908
|
suspendTimeout: formatSuspendTimeout(endpoint.suspend_timeout_seconds)
|
|
@@ -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 DataAPICreateRequest,\n\ttype DataAPIReponse,\n\ttype DataAPISettings,\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\tEnableDataApiInput,\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 {\n\tBucketAccessLevel,\n\tComputeSettings,\n\tDataApiSettings,\n} 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// ─── Data API mapping (camelCase neon.ts ↔ snake_case Neon API) ───────────────\n\n/** Map our camelCase {@link DataApiSettings} onto the Neon API's snake_case `DataAPISettings`. */\nfunction dataApiSettingsToApi(settings: DataApiSettings): DataAPISettings {\n\tconst out: DataAPISettings = {};\n\tif (settings.dbAggregatesEnabled !== undefined)\n\t\tout.db_aggregates_enabled = settings.dbAggregatesEnabled;\n\tif (settings.dbAnonRole !== undefined)\n\t\tout.db_anon_role = settings.dbAnonRole;\n\tif (settings.dbExtraSearchPath !== undefined)\n\t\tout.db_extra_search_path = settings.dbExtraSearchPath;\n\tif (settings.dbMaxRows !== undefined) out.db_max_rows = settings.dbMaxRows;\n\tif (settings.dbSchemas !== undefined) out.db_schemas = settings.dbSchemas;\n\tif (settings.jwtRoleClaimKey !== undefined)\n\t\tout.jwt_role_claim_key = settings.jwtRoleClaimKey;\n\tif (settings.jwtCacheMaxLifetime !== undefined)\n\t\tout.jwt_cache_max_lifetime = settings.jwtCacheMaxLifetime;\n\tif (settings.openapiMode !== undefined)\n\t\tout.openapi_mode = settings.openapiMode;\n\tif (settings.serverCorsAllowedOrigins !== undefined)\n\t\tout.server_cors_allowed_origins = settings.serverCorsAllowedOrigins;\n\tif (settings.serverTimingEnabled !== undefined)\n\t\tout.server_timing_enabled = settings.serverTimingEnabled;\n\treturn out;\n}\n\n/** Narrow the API's free-form `openapi_mode` string to our literal union (else drop it). */\nfunction normalizeOpenapiMode(\n\tvalue: string,\n): DataApiSettings[\"openapiMode\"] | undefined {\n\treturn value === \"ignore-privileges\" || value === \"disabled\"\n\t\t? value\n\t\t: undefined;\n}\n\n/** Map the Neon API's snake_case `DataAPISettings` back to our camelCase {@link DataApiSettings}. */\nfunction dataApiSettingsFromApi(\n\tsettings: DataAPISettings | null | undefined,\n): DataApiSettings | undefined {\n\tif (!settings) return undefined;\n\tconst out: DataApiSettings = {};\n\tif (settings.db_aggregates_enabled !== undefined)\n\t\tout.dbAggregatesEnabled = settings.db_aggregates_enabled;\n\tif (settings.db_anon_role !== undefined)\n\t\tout.dbAnonRole = settings.db_anon_role;\n\tif (settings.db_extra_search_path !== undefined)\n\t\tout.dbExtraSearchPath = settings.db_extra_search_path;\n\tif (settings.db_max_rows !== undefined)\n\t\tout.dbMaxRows = settings.db_max_rows;\n\tif (settings.db_schemas !== undefined) out.dbSchemas = settings.db_schemas;\n\tif (settings.jwt_role_claim_key !== undefined)\n\t\tout.jwtRoleClaimKey = settings.jwt_role_claim_key;\n\tif (settings.jwt_cache_max_lifetime !== undefined)\n\t\tout.jwtCacheMaxLifetime = settings.jwt_cache_max_lifetime;\n\tif (settings.openapi_mode !== undefined) {\n\t\tconst mode = normalizeOpenapiMode(settings.openapi_mode);\n\t\tif (mode !== undefined) out.openapiMode = mode;\n\t}\n\tif (settings.server_cors_allowed_origins !== undefined)\n\t\tout.serverCorsAllowedOrigins = settings.server_cors_allowed_origins;\n\tif (settings.server_timing_enabled !== undefined)\n\t\tout.serverTimingEnabled = settings.server_timing_enabled;\n\treturn Object.keys(out).length > 0 ? out : undefined;\n}\n\n/** Build the Neon API `DataAPICreateRequest` from our {@link EnableDataApiInput}. */\nfunction dataApiCreateRequest(\n\tinput: EnableDataApiInput | undefined,\n): DataAPICreateRequest {\n\tconst req: DataAPICreateRequest = {};\n\tif (!input) return req;\n\tif (input.authProvider !== undefined)\n\t\treq.auth_provider =\n\t\t\tinput.authProvider === \"neon\" ? \"neon_auth\" : \"external\";\n\tif (input.jwksUrl !== undefined) req.jwks_url = input.jwksUrl;\n\tif (input.providerName !== undefined)\n\t\treq.provider_name = input.providerName;\n\tif (input.jwtAudience !== undefined) req.jwt_audience = input.jwtAudience;\n\tif (input.settings) {\n\t\tconst settings = dataApiSettingsToApi(input.settings);\n\t\tif (Object.keys(settings).length > 0) req.settings = settings;\n\t}\n\treturn req;\n}\n\n/** Map a `DataAPIReponse` (GET) onto our {@link NeonDataApiSnapshot}. */\nfunction dataApiSnapshotFromResponse(\n\tdata: DataAPIReponse,\n): NeonDataApiSnapshot {\n\tconst snapshot: NeonDataApiSnapshot = { url: data.url };\n\tif (data.status !== undefined) snapshot.status = data.status;\n\tconst settings = dataApiSettingsFromApi(data.settings);\n\tif (settings) snapshot.settings = settings;\n\treturn snapshot;\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\tdataApiSnapshotFromResponse(\n\t\t\t\t\t\tawait this.client\n\t\t\t\t\t\t\t.getProjectBranchDataApi(\n\t\t\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\t\t\tbranchId,\n\t\t\t\t\t\t\t\tdatabaseName,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.then((res) => res.data),\n\t\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\tinput?: EnableDataApiInput,\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\tdataApiCreateRequest(input),\n\t\t\t\t\t);\n\t\t\t\t\t// The create response only carries `url`; settings/status come from a\n\t\t\t\t\t// follow-up GET, which we leave to the caller when it needs them.\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\tasync updateProjectBranchDataApi(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tdatabaseName: string,\n\t\tsettings: DataApiSettings,\n\t): Promise<NeonDataApiSnapshot> {\n\t\treturn await this.call(\n\t\t\t`updateProjectBranchDataApi(${projectId}/${branchId}/${databaseName})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.client.updateProjectBranchDataApi(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t\tdatabaseName,\n\t\t\t\t\t{ settings: dataApiSettingsToApi(settings) },\n\t\t\t\t);\n\t\t\t\t// The PATCH returns an empty body; re-fetch so the caller sees the\n\t\t\t\t// post-update url/status/settings.\n\t\t\t\tconst res = await this.client.getProjectBranchDataApi(\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\treturn dataApiSnapshotFromResponse(res.data);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\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
|
+
{"version":3,"file":"neon-api-real.js","names":["rawListProjects","rawGetProject","rawCreateProject","rawUpdateProject","rawListProjectBranches","rawCreateProjectBranch","rawUpdateProjectBranch","rawListProjectEndpoints","rawUpdateProjectEndpoint","rawListProjectBranchRoles","rawListProjectBranchDatabases","rawGetConnectionUri","rawGetNeonAuth","rawGetProjectBranchDataApi","rawCreateProjectBranchDataApi","rawUpdateProjectBranchDataApi"],"sources":["../../src/lib/neon-api-real.ts"],"sourcesContent":["import type {\n\tDataApiSettings as ApiDataApiSettings,\n\tBranch,\n\tBranchCreateRequest,\n\tBranchCreateRequestEndpointOptions,\n\tBranchUpdateRequest,\n\tDataApiCreateRequest,\n\tDataApiReponse,\n\tDatabase,\n\tDefaultEndpointSettings,\n\tEndpoint,\n\tEndpointUpdateRequest,\n\tPgVersion,\n\tProject,\n\tProjectCreateRequest,\n\tProjectListItem,\n\tProjectUpdateRequest,\n\tRole,\n} from \"@neon/sdk\";\nimport { createNeonClient } from \"@neon/sdk\";\nimport {\n\tcreateProject as rawCreateProject,\n\tcreateProjectBranch as rawCreateProjectBranch,\n\tcreateProjectBranchDataApi as rawCreateProjectBranchDataApi,\n\tgetConnectionUri as rawGetConnectionUri,\n\tgetNeonAuth as rawGetNeonAuth,\n\tgetProject as rawGetProject,\n\tgetProjectBranchDataApi as rawGetProjectBranchDataApi,\n\tlistProjectBranchDatabases as rawListProjectBranchDatabases,\n\tlistProjectBranches as rawListProjectBranches,\n\tlistProjectBranchRoles as rawListProjectBranchRoles,\n\tlistProjectEndpoints as rawListProjectEndpoints,\n\tlistProjects as rawListProjects,\n\tupdateProject as rawUpdateProject,\n\tupdateProjectBranch as rawUpdateProjectBranch,\n\tupdateProjectBranchDataApi as rawUpdateProjectBranchDataApi,\n\tupdateProjectEndpoint as rawUpdateProjectEndpoint,\n} from \"@neon/sdk/raw\";\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\tEnableDataApiInput,\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 {\n\tBucketAccessLevel,\n\tComputeSettings,\n\tDataApiSettings,\n} from \"./types.js\";\nimport { wrapNeonError } from \"./wrap-neon-error.js\";\n\ntype ApiClient = ReturnType<typeof createNeonClient>[\"client\"];\nconst DEFAULT_NEON_API_BASE_URL = \"https://console.neon.tech/api/v2\";\n\n/**\n * Unwrap a `@neon/sdk` raw `{ data, error, response }` result into the bare body, throwing\n * on a non-2xx response. The thrown shape (`{ response: { status, data } }`) deliberately\n * matches what the package's REST fallbacks already throw, so {@link wrapNeonError} and the\n * 423 {@link retryOnLocked} retry keep working unchanged across both transports.\n */\nfunction unwrap<T>(result: {\n\tdata?: T;\n\terror?: unknown;\n\tresponse?: Response;\n}): T {\n\tconst response = result.response;\n\tif (!response || !response.ok) {\n\t\tthrow {\n\t\t\tresponse: {\n\t\t\t\tstatus: response?.status,\n\t\t\t\tdata: result.error,\n\t\t\t},\n\t\t};\n\t}\n\treturn result.data as T;\n}\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// ─── Data API mapping (camelCase neon.ts ↔ snake_case Neon API) ───────────────\n\n/** Map our camelCase {@link DataApiSettings} onto the Neon API's snake_case `DataAPISettings`. */\nfunction dataApiSettingsToApi(settings: DataApiSettings): ApiDataApiSettings {\n\tconst out: ApiDataApiSettings = {};\n\tif (settings.dbAggregatesEnabled !== undefined)\n\t\tout.db_aggregates_enabled = settings.dbAggregatesEnabled;\n\tif (settings.dbAnonRole !== undefined)\n\t\tout.db_anon_role = settings.dbAnonRole;\n\tif (settings.dbExtraSearchPath !== undefined)\n\t\tout.db_extra_search_path = settings.dbExtraSearchPath;\n\tif (settings.dbMaxRows !== undefined) out.db_max_rows = settings.dbMaxRows;\n\tif (settings.dbSchemas !== undefined) out.db_schemas = settings.dbSchemas;\n\tif (settings.jwtRoleClaimKey !== undefined)\n\t\tout.jwt_role_claim_key = settings.jwtRoleClaimKey;\n\tif (settings.jwtCacheMaxLifetime !== undefined)\n\t\tout.jwt_cache_max_lifetime = settings.jwtCacheMaxLifetime;\n\tif (settings.openapiMode !== undefined)\n\t\tout.openapi_mode = settings.openapiMode;\n\tif (settings.serverCorsAllowedOrigins !== undefined)\n\t\tout.server_cors_allowed_origins = settings.serverCorsAllowedOrigins;\n\tif (settings.serverTimingEnabled !== undefined)\n\t\tout.server_timing_enabled = settings.serverTimingEnabled;\n\treturn out;\n}\n\n/** Narrow the API's free-form `openapi_mode` string to our literal union (else drop it). */\nfunction normalizeOpenapiMode(\n\tvalue: string,\n): DataApiSettings[\"openapiMode\"] | undefined {\n\treturn value === \"ignore-privileges\" || value === \"disabled\"\n\t\t? value\n\t\t: undefined;\n}\n\n/** Map the Neon API's snake_case `DataAPISettings` back to our camelCase {@link DataApiSettings}. */\nfunction dataApiSettingsFromApi(\n\tsettings: ApiDataApiSettings | null | undefined,\n): DataApiSettings | undefined {\n\tif (!settings) return undefined;\n\tconst out: DataApiSettings = {};\n\tif (settings.db_aggregates_enabled !== undefined)\n\t\tout.dbAggregatesEnabled = settings.db_aggregates_enabled;\n\tif (settings.db_anon_role !== undefined)\n\t\tout.dbAnonRole = settings.db_anon_role;\n\tif (settings.db_extra_search_path !== undefined)\n\t\tout.dbExtraSearchPath = settings.db_extra_search_path;\n\tif (settings.db_max_rows !== undefined)\n\t\tout.dbMaxRows = settings.db_max_rows;\n\tif (settings.db_schemas !== undefined) out.dbSchemas = settings.db_schemas;\n\tif (settings.jwt_role_claim_key !== undefined)\n\t\tout.jwtRoleClaimKey = settings.jwt_role_claim_key;\n\tif (settings.jwt_cache_max_lifetime !== undefined)\n\t\tout.jwtCacheMaxLifetime = settings.jwt_cache_max_lifetime;\n\tif (settings.openapi_mode !== undefined) {\n\t\tconst mode = normalizeOpenapiMode(settings.openapi_mode);\n\t\tif (mode !== undefined) out.openapiMode = mode;\n\t}\n\tif (settings.server_cors_allowed_origins !== undefined)\n\t\tout.serverCorsAllowedOrigins = settings.server_cors_allowed_origins;\n\tif (settings.server_timing_enabled !== undefined)\n\t\tout.serverTimingEnabled = settings.server_timing_enabled;\n\treturn Object.keys(out).length > 0 ? out : undefined;\n}\n\n/** Build the Neon API `DataAPICreateRequest` from our {@link EnableDataApiInput}. */\nfunction dataApiCreateRequest(\n\tinput: EnableDataApiInput | undefined,\n): DataApiCreateRequest {\n\tconst req: DataApiCreateRequest = {};\n\tif (!input) return req;\n\tif (input.authProvider !== undefined)\n\t\treq.auth_provider =\n\t\t\tinput.authProvider === \"neon\" ? \"neon_auth\" : \"external\";\n\tif (input.jwksUrl !== undefined) req.jwks_url = input.jwksUrl;\n\tif (input.providerName !== undefined)\n\t\treq.provider_name = input.providerName;\n\tif (input.jwtAudience !== undefined) req.jwt_audience = input.jwtAudience;\n\tif (input.settings) {\n\t\tconst settings = dataApiSettingsToApi(input.settings);\n\t\tif (Object.keys(settings).length > 0) req.settings = settings;\n\t}\n\treturn req;\n}\n\n/** Map a `DataAPIReponse` (GET) onto our {@link NeonDataApiSnapshot}. */\nfunction dataApiSnapshotFromResponse(\n\tdata: DataApiReponse,\n): NeonDataApiSnapshot {\n\tconst snapshot: NeonDataApiSnapshot = { url: data.url };\n\tif (data.status !== undefined) snapshot.status = data.status;\n\tconst settings = dataApiSettingsFromApi(data.settings);\n\tif (settings) snapshot.settings = settings;\n\treturn snapshot;\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 `@neon/sdk` (raw layer) 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\t// The SDK runs its own retries by default; this adapter does its own 423-aware\n\t// `retryOnLocked`, so disable the SDK's to avoid compounding backoff.\n\tconst client = createNeonClient({\n\t\tapiKey: options.apiKey,\n\t\tretries: 0,\n\t\t...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),\n\t}).client;\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 body = unwrap(\n\t\t\t\t\t\tawait rawListProjects({\n\t\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\t\tquery: {\n\t\t\t\t\t\t\t\t...(filter.orgId\n\t\t\t\t\t\t\t\t\t? { org_id: filter.orgId }\n\t\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t\t...(cursor ? { cursor } : {}),\n\t\t\t\t\t\t\t\tlimit: 100,\n\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\tprojects.push(...body.projects);\n\t\t\t\t\tconst next = (body as { pagination?: { next?: string } })\n\t\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 body = unwrap(\n\t\t\t\t\tawait rawGetProject({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: { project_id: projectId },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn projectToSnapshot(body.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 data = unwrap(\n\t\t\t\t\tawait rawCreateProject({ client: this.client, body }),\n\t\t\t\t);\n\t\t\t\treturn projectToSnapshot(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 data = unwrap(\n\t\t\t\t\tawait rawUpdateProject({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: { project_id: projectId },\n\t\t\t\t\t\tbody,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn projectToSnapshot(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 body = unwrap(\n\t\t\t\t\t\tawait rawListProjectBranches({\n\t\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\t\tpath: { project_id: projectId },\n\t\t\t\t\t\t\tquery: {\n\t\t\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t\t\t\t...(cursor ? { cursor } : {}),\n\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\tbranches.push(...(body.branches as Branch[]));\n\t\t\t\t\tconst next = (body as { pagination?: { next?: string } })\n\t\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: \"read_write\",\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: \"read_write\" };\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 data = unwrap(\n\t\t\t\t\tawait rawCreateProjectBranch({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: { project_id: projectId },\n\t\t\t\t\t\tbody,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tbranch: branchToSnapshot(data.branch),\n\t\t\t\t\tendpoints: (data.endpoints ?? []).map(endpointToSnapshot),\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 data = unwrap(\n\t\t\t\t\tawait rawUpdateProjectBranch({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: { project_id: projectId, branch_id: branchId },\n\t\t\t\t\t\tbody: { branch },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn branchToSnapshot(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 data = unwrap(\n\t\t\t\t\tawait rawListProjectEndpoints({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: { project_id: projectId },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn (data.endpoints as Endpoint[]).map(endpointToSnapshot);\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 data = unwrap(\n\t\t\t\t\tawait rawUpdateProjectEndpoint({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: {\n\t\t\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\t\t\tendpoint_id: endpointId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbody: { endpoint },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn endpointToSnapshot(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 data = unwrap(\n\t\t\t\t\tawait rawListProjectBranchRoles({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: { project_id: projectId, branch_id: branchId },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn (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 data = unwrap(\n\t\t\t\t\tawait rawListProjectBranchDatabases({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: { project_id: projectId, branch_id: branchId },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn (data.databases as Database[]).map(databaseToSnapshot);\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 data = unwrap(\n\t\t\t\t\tawait rawGetConnectionUri({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: { project_id: projectId },\n\t\t\t\t\t\tquery: {\n\t\t\t\t\t\t\tdatabase_name: input.databaseName,\n\t\t\t\t\t\t\trole_name: input.roleName,\n\t\t\t\t\t\t\t...(input.branchId\n\t\t\t\t\t\t\t\t? { branch_id: input.branchId }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\t...(input.endpointId\n\t\t\t\t\t\t\t\t? { endpoint_id: input.endpointId }\n\t\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t\tpooled,\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn { uri: 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 data = unwrap(\n\t\t\t\t\t\tawait rawGetNeonAuth({\n\t\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\t\tpath: {\n\t\t\t\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\t\t\t\tbranch_id: branchId,\n\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\treturn neonAuthResponseToSnapshot(\n\t\t\t\t\t\tneonAuthResponseSchema.parse(data),\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\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// The generated `createNeonAuth` doesn't narrow this branch\n\t\t\t\t\t// endpoint to `better_auth`, so post the REST body directly.\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\tdataApiSnapshotFromResponse(\n\t\t\t\t\t\tunwrap(\n\t\t\t\t\t\t\tawait rawGetProjectBranchDataApi({\n\t\t\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\t\t\tpath: {\n\t\t\t\t\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\t\t\t\t\tbranch_id: branchId,\n\t\t\t\t\t\t\t\t\tdatabase_name: databaseName,\n\t\t\t\t\t\t\t\t},\n\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{ 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\tinput?: EnableDataApiInput,\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 data = unwrap(\n\t\t\t\t\t\tawait rawCreateProjectBranchDataApi({\n\t\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\t\tpath: {\n\t\t\t\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\t\t\t\tbranch_id: branchId,\n\t\t\t\t\t\t\t\tdatabase_name: databaseName,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbody: dataApiCreateRequest(input),\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\t// The create response only carries `url`; settings/status come from a\n\t\t\t\t\t// follow-up GET, which we leave to the caller when it needs them.\n\t\t\t\t\treturn { url: 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\tasync updateProjectBranchDataApi(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tdatabaseName: string,\n\t\tsettings: DataApiSettings,\n\t): Promise<NeonDataApiSnapshot> {\n\t\treturn await this.call(\n\t\t\t`updateProjectBranchDataApi(${projectId}/${branchId}/${databaseName})`,\n\t\t\tasync () => {\n\t\t\t\tunwrap(\n\t\t\t\t\tawait rawUpdateProjectBranchDataApi({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: {\n\t\t\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\t\t\tbranch_id: branchId,\n\t\t\t\t\t\t\tdatabase_name: databaseName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbody: { settings: dataApiSettingsToApi(settings) },\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\t// The PATCH returns an empty body; re-fetch so the caller sees the\n\t\t\t\t// post-update url/status/settings.\n\t\t\t\tconst data = unwrap(\n\t\t\t\t\tawait rawGetProjectBranchDataApi({\n\t\t\t\t\t\tclient: this.client,\n\t\t\t\t\t\tpath: {\n\t\t\t\t\t\t\tproject_id: projectId,\n\t\t\t\t\t\t\tbranch_id: branchId,\n\t\t\t\t\t\t\tdatabase_name: databaseName,\n\t\t\t\t\t\t},\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\treturn dataApiSnapshotFromResponse(data);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\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: endpoint.type === \"read_only\" ? \"read_only\" : \"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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"}
|
package/dist/lib/patterns.js
CHANGED
package/dist/lib/patterns.js.map
CHANGED
|
@@ -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,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,
|
|
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,6BAAa,IAAI,IAAI;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neondatabase/config",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Config-as-Code for the Neon Platform. Define a `neon.ts` policy and inspect/diff/deploy it against the Neon API as plain TypeScript functions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"neon",
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"vitest": "^3.0.9"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@neondatabase/api-client": "^2.7.1",
|
|
52
51
|
"jiti": "^2.7.0",
|
|
53
|
-
"zod": "^4.4.3"
|
|
52
|
+
"zod": "^4.4.3",
|
|
53
|
+
"@neon/sdk": "0.1.0"
|
|
54
54
|
},
|
|
55
55
|
"engines": {
|
|
56
56
|
"node": ">=22"
|