@neondatabase/config 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -2
- package/dist/lib/define-config.d.ts.map +1 -1
- package/dist/lib/define-config.js +2 -1
- package/dist/lib/define-config.js.map +1 -1
- package/dist/lib/errors.d.ts +1 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +1 -0
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/neon-api-real.d.ts +30 -1
- package/dist/lib/neon-api-real.d.ts.map +1 -1
- package/dist/lib/neon-api-real.js +63 -10
- package/dist/lib/neon-api-real.js.map +1 -1
- package/dist/lib/schema.d.ts +12 -0
- package/dist/lib/schema.d.ts.map +1 -1
- package/dist/lib/schema.js +19 -3
- package/dist/lib/schema.js.map +1 -1
- package/dist/lib/types.d.ts +38 -4
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/v1.d.ts +15 -2
- package/dist/v1.d.ts.map +1 -1
- package/dist/v1.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppliedChange, BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, Config, ConflictReport, FunctionConfig, FunctionMemoryMib, FunctionRuntime, PostgresConfig, PreviewConfig, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle } from "./lib/types.js";
|
|
1
|
+
import { AppliedChange, BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, Config, ConflictReport, FunctionConfig, FunctionDevConfig, FunctionMemoryMib, FunctionRuntime, PostgresConfig, PreviewConfig, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle } from "./lib/types.js";
|
|
2
2
|
import { ConfigLoadError, ConfigValidationError, ErrorCode, MissingContextError, PlatformError, PushAbortedError, PushConflictError } from "./lib/errors.js";
|
|
3
3
|
import { CreateBranchInput, CreateBucketInput, CreateProjectInput, DeployFunctionInput, GetConnectionUriInput, NeonApi, NeonAuthSnapshot, NeonBranchSnapshot, NeonBucketSnapshot, NeonDataApiSnapshot, NeonDatabaseSnapshot, NeonEndpointSnapshot, NeonFunctionDeploymentSnapshot, NeonFunctionSnapshot, NeonProjectSnapshot, NeonRoleSnapshot, UpdateBranchInput } from "./lib/neon-api.js";
|
|
4
4
|
import { createNeonApiFromOptions, resolveApiKey } from "./lib/auth.js";
|
|
@@ -7,4 +7,4 @@ import { DiffOptions, DiffResult, PlanStep, RemotePreviewState, RemoteServiceSta
|
|
|
7
7
|
import { LoadConfigOptions, loadConfigFromFile } from "./lib/loader.js";
|
|
8
8
|
import { createRealNeonApi } from "./lib/neon-api-real.js";
|
|
9
9
|
import { errors, schemas } from "./v1.js";
|
|
10
|
-
export { AppliedChange, BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, Config, ConfigLoadError, ConfigValidationError, ConflictReport, CreateBranchInput, CreateBucketInput, CreateProjectInput, DeployFunctionInput, DiffOptions, DiffResult, ErrorCode, FunctionConfig, FunctionMemoryMib, FunctionRuntime, GetConnectionUriInput, LoadConfigOptions, MissingContextError, NeonApi, NeonAuthSnapshot, NeonBranchSnapshot, NeonBucketSnapshot, NeonDataApiSnapshot, NeonDatabaseSnapshot, NeonEndpointSnapshot, NeonFunctionDeploymentSnapshot, NeonFunctionSnapshot, NeonProjectSnapshot, NeonRoleSnapshot, PlanStep, PlatformError, PostgresConfig, PreviewConfig, PushAbortedError, PushConflictError, PushResult, RemotePreviewState, RemoteServiceState, RemoteState, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle, UpdateBranchInput, createNeonApiFromOptions, createRealNeonApi, defineConfig, diffConfig, errors, loadConfigFromFile, resolveApiKey, resolveConfig, schemas };
|
|
10
|
+
export { AppliedChange, BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, Config, ConfigLoadError, ConfigValidationError, ConflictReport, CreateBranchInput, CreateBucketInput, CreateProjectInput, DeployFunctionInput, DiffOptions, DiffResult, ErrorCode, FunctionConfig, FunctionDevConfig, FunctionMemoryMib, FunctionRuntime, GetConnectionUriInput, LoadConfigOptions, MissingContextError, NeonApi, NeonAuthSnapshot, NeonBranchSnapshot, NeonBucketSnapshot, NeonDataApiSnapshot, NeonDatabaseSnapshot, NeonEndpointSnapshot, NeonFunctionDeploymentSnapshot, NeonFunctionSnapshot, NeonProjectSnapshot, NeonRoleSnapshot, PlanStep, PlatformError, PostgresConfig, PreviewConfig, PushAbortedError, PushConflictError, PushResult, RemotePreviewState, RemoteServiceState, RemoteState, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle, UpdateBranchInput, createNeonApiFromOptions, createRealNeonApi, defineConfig, diffConfig, errors, loadConfigFromFile, resolveApiKey, resolveConfig, schemas };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-config.d.ts","names":[],"sources":["../../src/lib/define-config.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"define-config.d.ts","names":[],"sources":["../../src/lib/define-config.ts"],"mappings":";;;;;;AA4CA;;;;;AAAiE;AAcjE;;;;;AAGuB;AA0FvB;;;;;;;;;;;iBA3GgB,6BAA6B,eAAe,IAAI;;;;iBAchD,aAAA,SACP,gBACA,eACN;;;;;;iBA0Fa,eAAA"}
|
|
@@ -93,7 +93,8 @@ function resolveFunctionConfig(fn) {
|
|
|
93
93
|
source: fn.source,
|
|
94
94
|
env: { ...fn.env ?? {} },
|
|
95
95
|
runtime: fn.runtime ?? DEFAULT_FUNCTION_RUNTIME,
|
|
96
|
-
memoryMib: fn.memoryMib ?? DEFAULT_FUNCTION_MEMORY_MIB
|
|
96
|
+
memoryMib: fn.memoryMib ?? DEFAULT_FUNCTION_MEMORY_MIB,
|
|
97
|
+
...fn.dev ? { dev: fn.dev } : {}
|
|
97
98
|
};
|
|
98
99
|
}
|
|
99
100
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-config.js","names":[],"sources":["../../src/lib/define-config.ts"],"sourcesContent":["import { parseDuration } from \"./duration.js\";\nimport { ConfigValidationError } from \"./errors.js\";\nimport { branchConfigSchema, formatZodIssues } from \"./schema.js\";\nimport type {\n\tBranchTarget,\n\tConfig,\n\tFunctionConfig,\n\tPreviewConfig,\n\tResolvedBranchConfig,\n\tResolvedPreviewConfig,\n} from \"./types.js\";\n\n/** Default deploy parameters applied to functions that omit them in `neon.ts`. */\nconst DEFAULT_FUNCTION_RUNTIME = \"nodejs24\" as const;\nconst DEFAULT_FUNCTION_MEMORY_MIB = 512 as const;\n\nconst REGION_PREFIX = /^(aws|azure|gcp)-/;\n\n/**\n * Validate and freeze a Neon Platform branch policy.\n *\n * Used at the top of `neon.ts`:\n * ```ts\n * import { defineConfig } from \"@neondatabase/config/v1\";\n *\n * export default defineConfig((branch) => {\n * if (branch.name === \"main\") {\n * return { protected: true, auth: {} };\n * }\n * return { parent: \"main\", ttl: \"7d\" };\n * });\n * ```\n *\n * The `branch` parameter is a **read-only {@link BranchTarget} descriptor** of the branch\n * this policy invocation is deciding for — not a live branch handle. You don't mutate it\n * (`branch.protected = true` does nothing); you switch on its facts (`branch.name`,\n * `branch.isDefault`, `branch.exists`, …) and **return** the desired {@link BranchConfig}.\n * The same callback runs in two modes: against an existing branch (fields populated from\n * Neon) and during pre-create evaluation (`exists: false`, `id` undefined).\n *\n * Pure function — no I/O, no side effects. The returned policy validates its output every\n * time it is evaluated so errors point at the concrete branch target that triggered them.\n */\nexport function defineConfig<const C extends Config>(input: C): C {\n\tif (typeof input !== \"function\") {\n\t\tthrow new ConfigValidationError([\n\t\t\t\"defineConfig expects a function: `export default defineConfig((branch) => ({ ... }))`.\",\n\t\t\t\"Project-level config has moved to `neonctl link`; neon.ts now describes branch-level policy only.\",\n\t\t]);\n\t}\n\n\treturn Object.freeze(input) as C;\n}\n\n/**\n * Evaluate a branch policy for a specific branch target and return a normalized config.\n */\nexport function resolveConfig(\n\tconfig: Config,\n\tbranch: BranchTarget,\n): ResolvedBranchConfig {\n\tlet raw: unknown;\n\ttry {\n\t\traw = config(Object.freeze({ ...branch }));\n\t} catch (cause) {\n\t\tthrow new ConfigValidationError([\n\t\t\t`Config function threw while evaluating branch \"${branch.name}\".`,\n\t\t\t(cause as Error)?.message ?? String(cause),\n\t\t]);\n\t}\n\n\tconst parsed = branchConfigSchema.safeParse(raw);\n\tif (!parsed.success) {\n\t\tthrow new ConfigValidationError(formatZodIssues(parsed.error));\n\t}\n\n\tconst cfg = parsed.data;\n\tconst issues: string[] = [];\n\tlet ttlSeconds: number | undefined;\n\tif (cfg.ttl !== undefined) {\n\t\tconst parsedTtl = parseDuration(cfg.ttl);\n\t\tif (\"error\" in parsedTtl) {\n\t\t\tissues.push(`ttl: ${parsedTtl.error}`);\n\t\t} else {\n\t\t\tttlSeconds = parsedTtl.seconds;\n\t\t}\n\t}\n\tif (issues.length > 0) {\n\t\tthrow new ConfigValidationError(issues);\n\t}\n\n\tconst resolved: ResolvedBranchConfig = {\n\t\tauthEnabled: isServiceEnabled(cfg.auth),\n\t\tdataApiEnabled: isServiceEnabled(cfg.dataApi),\n\t};\n\tif (cfg.parent !== undefined) resolved.parent = cfg.parent;\n\tif (ttlSeconds !== undefined) resolved.ttlSeconds = ttlSeconds;\n\tif (cfg.protected !== undefined) resolved.protected = cfg.protected;\n\tif (cfg.postgres) {\n\t\tresolved.postgres = {\n\t\t\t...(cfg.postgres.computeSettings\n\t\t\t\t? { computeSettings: { ...cfg.postgres.computeSettings } }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\tif (cfg.preview) {\n\t\tresolved.preview = resolvePreviewConfig(cfg.preview);\n\t}\n\treturn resolved;\n}\n\nfunction isServiceEnabled(service: { enabled?: boolean } | undefined): boolean {\n\treturn service !== undefined && service.enabled !== false;\n}\n\n/**\n * Normalize a {@link PreviewConfig} into a {@link ResolvedPreviewConfig}: apply per-function\n * deploy defaults, default each bucket's access level to `private`, and collapse the\n * `aiGateway` toggle to a boolean using the same present-and-not-`false` rule as\n * `auth` / `dataApi`.\n */\nfunction resolvePreviewConfig(preview: PreviewConfig): ResolvedPreviewConfig {\n\treturn {\n\t\tfunctions: (preview.functions ?? []).map(resolveFunctionConfig),\n\t\tbuckets: (preview.buckets ?? []).map((bucket) => ({\n\t\t\tname: bucket.name,\n\t\t\taccess: bucket.access ?? \"private\",\n\t\t})),\n\t\taiGatewayEnabled: isServiceEnabled(preview.aiGateway),\n\t};\n}\n\nfunction resolveFunctionConfig(fn: FunctionConfig) {\n\treturn {\n\t\tslug: fn.slug,\n\t\tname: fn.name,\n\t\tsource: fn.source,\n\t\tenv: { ...(fn.env ?? {}) },\n\t\truntime: fn.runtime ?? DEFAULT_FUNCTION_RUNTIME,\n\t\tmemoryMib: fn.memoryMib ?? DEFAULT_FUNCTION_MEMORY_MIB,\n\t};\n}\n\n/**\n * Normalize a region identifier to Neon's `<cloud>-<region>` format. When the user writes\n * `us-east-1` we assume `aws-us-east-1`. Pure helper used by both the validator and the\n * NeonApi adapter.\n */\nexport function normalizeRegion(region: string): string {\n\tif (REGION_PREFIX.test(region)) return region;\n\treturn `aws-${region}`;\n}\n"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"define-config.js","names":[],"sources":["../../src/lib/define-config.ts"],"sourcesContent":["import { parseDuration } from \"./duration.js\";\nimport { ConfigValidationError } from \"./errors.js\";\nimport { branchConfigSchema, formatZodIssues } from \"./schema.js\";\nimport type {\n\tBranchTarget,\n\tConfig,\n\tFunctionConfig,\n\tPreviewConfig,\n\tResolvedBranchConfig,\n\tResolvedFunctionConfig,\n\tResolvedPreviewConfig,\n} from \"./types.js\";\n\n/** Default deploy parameters applied to functions that omit them in `neon.ts`. */\nconst DEFAULT_FUNCTION_RUNTIME = \"nodejs24\" as const;\nconst DEFAULT_FUNCTION_MEMORY_MIB = 512 as const;\n\nconst REGION_PREFIX = /^(aws|azure|gcp)-/;\n\n/**\n * Validate and freeze a Neon Platform branch policy.\n *\n * Used at the top of `neon.ts`:\n * ```ts\n * import { defineConfig } from \"@neondatabase/config/v1\";\n *\n * export default defineConfig((branch) => {\n * if (branch.name === \"main\") {\n * return { protected: true, auth: {} };\n * }\n * return { parent: \"main\", ttl: \"7d\" };\n * });\n * ```\n *\n * The `branch` parameter is a **read-only {@link BranchTarget} descriptor** of the branch\n * this policy invocation is deciding for — not a live branch handle. You don't mutate it\n * (`branch.protected = true` does nothing); you switch on its facts (`branch.name`,\n * `branch.isDefault`, `branch.exists`, …) and **return** the desired {@link BranchConfig}.\n * The same callback runs in two modes: against an existing branch (fields populated from\n * Neon) and during pre-create evaluation (`exists: false`, `id` undefined).\n *\n * Pure function — no I/O, no side effects. The returned policy validates its output every\n * time it is evaluated so errors point at the concrete branch target that triggered them.\n */\nexport function defineConfig<const C extends Config>(input: C): C {\n\tif (typeof input !== \"function\") {\n\t\tthrow new ConfigValidationError([\n\t\t\t\"defineConfig expects a function: `export default defineConfig((branch) => ({ ... }))`.\",\n\t\t\t\"Project-level config has moved to `neonctl link`; neon.ts now describes branch-level policy only.\",\n\t\t]);\n\t}\n\n\treturn Object.freeze(input) as C;\n}\n\n/**\n * Evaluate a branch policy for a specific branch target and return a normalized config.\n */\nexport function resolveConfig(\n\tconfig: Config,\n\tbranch: BranchTarget,\n): ResolvedBranchConfig {\n\tlet raw: unknown;\n\ttry {\n\t\traw = config(Object.freeze({ ...branch }));\n\t} catch (cause) {\n\t\tthrow new ConfigValidationError([\n\t\t\t`Config function threw while evaluating branch \"${branch.name}\".`,\n\t\t\t(cause as Error)?.message ?? String(cause),\n\t\t]);\n\t}\n\n\tconst parsed = branchConfigSchema.safeParse(raw);\n\tif (!parsed.success) {\n\t\tthrow new ConfigValidationError(formatZodIssues(parsed.error));\n\t}\n\n\tconst cfg = parsed.data;\n\tconst issues: string[] = [];\n\tlet ttlSeconds: number | undefined;\n\tif (cfg.ttl !== undefined) {\n\t\tconst parsedTtl = parseDuration(cfg.ttl);\n\t\tif (\"error\" in parsedTtl) {\n\t\t\tissues.push(`ttl: ${parsedTtl.error}`);\n\t\t} else {\n\t\t\tttlSeconds = parsedTtl.seconds;\n\t\t}\n\t}\n\tif (issues.length > 0) {\n\t\tthrow new ConfigValidationError(issues);\n\t}\n\n\tconst resolved: ResolvedBranchConfig = {\n\t\tauthEnabled: isServiceEnabled(cfg.auth),\n\t\tdataApiEnabled: isServiceEnabled(cfg.dataApi),\n\t};\n\tif (cfg.parent !== undefined) resolved.parent = cfg.parent;\n\tif (ttlSeconds !== undefined) resolved.ttlSeconds = ttlSeconds;\n\tif (cfg.protected !== undefined) resolved.protected = cfg.protected;\n\tif (cfg.postgres) {\n\t\tresolved.postgres = {\n\t\t\t...(cfg.postgres.computeSettings\n\t\t\t\t? { computeSettings: { ...cfg.postgres.computeSettings } }\n\t\t\t\t: {}),\n\t\t};\n\t}\n\tif (cfg.preview) {\n\t\tresolved.preview = resolvePreviewConfig(cfg.preview);\n\t}\n\treturn resolved;\n}\n\nfunction isServiceEnabled(service: { enabled?: boolean } | undefined): boolean {\n\treturn service !== undefined && service.enabled !== false;\n}\n\n/**\n * Normalize a {@link PreviewConfig} into a {@link ResolvedPreviewConfig}: apply per-function\n * deploy defaults, default each bucket's access level to `private`, and collapse the\n * `aiGateway` toggle to a boolean using the same present-and-not-`false` rule as\n * `auth` / `dataApi`.\n */\nfunction resolvePreviewConfig(preview: PreviewConfig): ResolvedPreviewConfig {\n\treturn {\n\t\tfunctions: (preview.functions ?? []).map(resolveFunctionConfig),\n\t\tbuckets: (preview.buckets ?? []).map((bucket) => ({\n\t\t\tname: bucket.name,\n\t\t\taccess: bucket.access ?? \"private\",\n\t\t})),\n\t\taiGatewayEnabled: isServiceEnabled(preview.aiGateway),\n\t};\n}\n\nfunction resolveFunctionConfig(fn: FunctionConfig): ResolvedFunctionConfig {\n\treturn {\n\t\tslug: fn.slug,\n\t\tname: fn.name,\n\t\tsource: fn.source,\n\t\tenv: { ...(fn.env ?? {}) },\n\t\truntime: fn.runtime ?? DEFAULT_FUNCTION_RUNTIME,\n\t\tmemoryMib: fn.memoryMib ?? DEFAULT_FUNCTION_MEMORY_MIB,\n\t\t// Passed through untouched (no defaults); only `neon dev` reads it.\n\t\t...(fn.dev ? { dev: fn.dev } : {}),\n\t};\n}\n\n/**\n * Normalize a region identifier to Neon's `<cloud>-<region>` format. When the user writes\n * `us-east-1` we assume `aws-us-east-1`. Pure helper used by both the validator and the\n * NeonApi adapter.\n */\nexport function normalizeRegion(region: string): string {\n\tif (REGION_PREFIX.test(region)) return region;\n\treturn `aws-${region}`;\n}\n"],"mappings":";;;;;AAcA,MAAM,2BAA2B;AACjC,MAAM,8BAA8B;AAEpC,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BtB,SAAgB,aAAqC,OAAa;CACjE,IAAI,OAAO,UAAU,YACpB,MAAM,IAAI,sBAAsB,CAC/B,0FACA,mGACD,CAAC;CAGF,OAAO,OAAO,OAAO,KAAK;AAC3B;;;;AAKA,SAAgB,cACf,QACA,QACuB;CACvB,IAAI;CACJ,IAAI;EACH,MAAM,OAAO,OAAO,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC;CAC1C,SAAS,OAAO;EACf,MAAM,IAAI,sBAAsB,CAC/B,kDAAkD,OAAO,KAAK,KAC7D,OAAiB,WAAW,OAAO,KAAK,CAC1C,CAAC;CACF;CAEA,MAAM,SAAS,mBAAmB,UAAU,GAAG;CAC/C,IAAI,CAAC,OAAO,SACX,MAAM,IAAI,sBAAsB,gBAAgB,OAAO,KAAK,CAAC;CAG9D,MAAM,MAAM,OAAO;CACnB,MAAM,SAAmB,CAAC;CAC1B,IAAI;CACJ,IAAI,IAAI,QAAQ,KAAA,GAAW;EAC1B,MAAM,YAAY,cAAc,IAAI,GAAG;EACvC,IAAI,WAAW,WACd,OAAO,KAAK,QAAQ,UAAU,OAAO;OAErC,aAAa,UAAU;CAEzB;CACA,IAAI,OAAO,SAAS,GACnB,MAAM,IAAI,sBAAsB,MAAM;CAGvC,MAAM,WAAiC;EACtC,aAAa,iBAAiB,IAAI,IAAI;EACtC,gBAAgB,iBAAiB,IAAI,OAAO;CAC7C;CACA,IAAI,IAAI,WAAW,KAAA,GAAW,SAAS,SAAS,IAAI;CACpD,IAAI,eAAe,KAAA,GAAW,SAAS,aAAa;CACpD,IAAI,IAAI,cAAc,KAAA,GAAW,SAAS,YAAY,IAAI;CAC1D,IAAI,IAAI,UACP,SAAS,WAAW,EACnB,GAAI,IAAI,SAAS,kBACd,EAAE,iBAAiB,EAAE,GAAG,IAAI,SAAS,gBAAgB,EAAE,IACvD,CAAC,EACL;CAED,IAAI,IAAI,SACP,SAAS,UAAU,qBAAqB,IAAI,OAAO;CAEpD,OAAO;AACR;AAEA,SAAS,iBAAiB,SAAqD;CAC9E,OAAO,YAAY,KAAA,KAAa,QAAQ,YAAY;AACrD;;;;;;;AAQA,SAAS,qBAAqB,SAA+C;CAC5E,OAAO;EACN,YAAY,QAAQ,aAAa,CAAC,GAAG,IAAI,qBAAqB;EAC9D,UAAU,QAAQ,WAAW,CAAC,GAAG,KAAK,YAAY;GACjD,MAAM,OAAO;GACb,QAAQ,OAAO,UAAU;EAC1B,EAAE;EACF,kBAAkB,iBAAiB,QAAQ,SAAS;CACrD;AACD;AAEA,SAAS,sBAAsB,IAA4C;CAC1E,OAAO;EACN,MAAM,GAAG;EACT,MAAM,GAAG;EACT,QAAQ,GAAG;EACX,KAAK,EAAE,GAAI,GAAG,OAAO,CAAC,EAAG;EACzB,SAAS,GAAG,WAAW;EACvB,WAAW,GAAG,aAAa;EAE3B,GAAI,GAAG,MAAM,EAAE,KAAK,GAAG,IAAI,IAAI,CAAC;CACjC;AACD;;;;;;AAOA,SAAgB,gBAAgB,QAAwB;CACvD,IAAI,cAAc,KAAK,MAAM,GAAG,OAAO;CACvC,OAAO,OAAO;AACf"}
|
package/dist/lib/errors.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ declare const ErrorCode: {
|
|
|
33
33
|
readonly MissingApiKey: "PLATFORM_MISSING_API_KEY";
|
|
34
34
|
readonly AmbiguousBranchAuth: "PLATFORM_AMBIGUOUS_BRANCH_AUTH";
|
|
35
35
|
readonly BranchNotFound: "PLATFORM_BRANCH_NOT_FOUND";
|
|
36
|
+
readonly FeatureUnavailable: "PLATFORM_FEATURE_UNAVAILABLE";
|
|
36
37
|
readonly MissingParentBranch: "PLATFORM_MISSING_PARENT_BRANCH";
|
|
37
38
|
readonly Unauthorized: "PLATFORM_UNAUTHORIZED";
|
|
38
39
|
readonly Forbidden: "PLATFORM_FORBIDDEN";
|
package/dist/lib/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/lib/errors.ts"],"mappings":";;;;;;AAuBA;
|
|
1
|
+
{"version":3,"file":"errors.d.ts","names":[],"sources":["../../src/lib/errors.ts"],"mappings":";;;;;;AAuBA;AAsBA;;;;AAAiE;AAYjE;;;;;;AAAwC;AAqBxC;AAUA;AAoBA;AAeA;;;AAIiC,cAxGpB,SAwGoB,EAAA;WAJM,aAAA,EAAA,yBAAA;EAAa,SAAA,cAAA,EAAA,2BAAA;EAqDvC,SAAA,cAAiB,EAAA,0BAAqB;EA8BtC,SAAA,YAAgB,EAAA,wBAAqB;;;;;;;;;;;;;;;;;;KAjKtC,SAAA,WAAoB,wBAAwB;;;;;;;;;cAY3C,aAAA,SAAsB,KAAA;;;oBAGhB,SAAS;;;cAKa;;;;;;;;iBAazB,eAAA,CAAA;;;;;;;cAUH,qBAAA,SAA8B,aAAa;;;;;;;;;;;;cAoB3C,mBAAA,SAA4B,aAAa;;;;;;;;;;;cAezC,iBAAA,SAA0B,aAAA;;+BAET;kCAEG;;;;;;;;;cAiDpB,gBAAA,SAAyB,aAAa;;;;;;;;;cA8BtC,eAAA,SAAwB,aAAa"}
|
package/dist/lib/errors.js
CHANGED
|
@@ -30,6 +30,7 @@ const ErrorCode = {
|
|
|
30
30
|
MissingApiKey: "PLATFORM_MISSING_API_KEY",
|
|
31
31
|
AmbiguousBranchAuth: "PLATFORM_AMBIGUOUS_BRANCH_AUTH",
|
|
32
32
|
BranchNotFound: "PLATFORM_BRANCH_NOT_FOUND",
|
|
33
|
+
FeatureUnavailable: "PLATFORM_FEATURE_UNAVAILABLE",
|
|
33
34
|
MissingParentBranch: "PLATFORM_MISSING_PARENT_BRANCH",
|
|
34
35
|
Unauthorized: "PLATFORM_UNAUTHORIZED",
|
|
35
36
|
Forbidden: "PLATFORM_FORBIDDEN",
|
package/dist/lib/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","names":[],"sources":["../../src/lib/errors.ts"],"sourcesContent":["import type { ConflictReport } from \"./types.js\";\n\n/**\n * Every code a {@link PlatformError} can carry. Stable identifiers — consumers can rely on\n * these for `instanceof PlatformError && err.code === ErrorCode.…` style checks instead of\n * matching on free-text messages.\n *\n * Grouped by source:\n * - `PLATFORM_INVALID_CONFIG` — `defineConfig` / `configSchema` rejected the input.\n * - `PLATFORM_MISSING_CONTEXT` — no project / branch context could be resolved.\n * - `PLATFORM_PUSH_CONFLICT` — local config conflicts with remote and the caller did not\n * opt in to apply.\n * - `PLATFORM_CONFIG_LOAD_FAILED` — `neon.ts` could not be found or evaluated.\n * - `PLATFORM_MISSING_API_KEY` — no `NEON_API_KEY` and no explicit `apiKey` was provided.\n * - `PLATFORM_MISSING_PARENT_BRANCH` — push tried to create a child of a non-existent\n * branch.\n * - `PLATFORM_UNAUTHORIZED` / `PLATFORM_FORBIDDEN` / `PLATFORM_NOT_FOUND` /\n * `PLATFORM_CONFLICT` / `PLATFORM_RATE_LIMITED` / `PLATFORM_LOCKED` /\n * `PLATFORM_SERVER_ERROR` — wrappings of Neon HTTP failures.\n * - `PLATFORM_NETWORK_ERROR` — transport-level failure (no HTTP response at all).\n * - `PLATFORM_INTERNAL_ERROR` — invariant violations. Should never happen in production;\n * if you see one, please open an issue.\n */\nexport const ErrorCode = {\n\tInvalidConfig: \"PLATFORM_INVALID_CONFIG\",\n\tEnvNotInjected: \"PLATFORM_ENV_NOT_INJECTED\",\n\tMissingContext: \"PLATFORM_MISSING_CONTEXT\",\n\tPushConflict: \"PLATFORM_PUSH_CONFLICT\",\n\tPushAborted: \"PLATFORM_PUSH_ABORTED\",\n\tConfigLoadFailed: \"PLATFORM_CONFIG_LOAD_FAILED\",\n\tMissingApiKey: \"PLATFORM_MISSING_API_KEY\",\n\tAmbiguousBranchAuth: \"PLATFORM_AMBIGUOUS_BRANCH_AUTH\",\n\tBranchNotFound: \"PLATFORM_BRANCH_NOT_FOUND\",\n\tMissingParentBranch: \"PLATFORM_MISSING_PARENT_BRANCH\",\n\tUnauthorized: \"PLATFORM_UNAUTHORIZED\",\n\tForbidden: \"PLATFORM_FORBIDDEN\",\n\tNotFound: \"PLATFORM_NOT_FOUND\",\n\tConflict: \"PLATFORM_CONFLICT\",\n\tRateLimited: \"PLATFORM_RATE_LIMITED\",\n\tLocked: \"PLATFORM_LOCKED\",\n\tServerError: \"PLATFORM_SERVER_ERROR\",\n\tNetworkError: \"PLATFORM_NETWORK_ERROR\",\n\tInternalError: \"PLATFORM_INTERNAL_ERROR\",\n} as const;\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nconst ISSUE_URL = \"https://github.com/neondatabase/neon-pkgs/issues/new\";\n\n/**\n * Base class for all errors thrown by `@neondatabase/config`. Always extend this so callers\n * can catch every package-thrown error with a single `instanceof` check.\n *\n * Optional `details` carries structured context that the CLI prints under `--debug` and\n * that programmatic consumers can read (e.g. `details.status` for HTTP wrappings,\n * `details.requestId` for Neon API failures).\n */\nexport class PlatformError extends Error {\n\toverride readonly name: string = \"PlatformError\";\n\treadonly code: string;\n\treadonly details: Readonly<Record<string, unknown>>;\n\n\tconstructor(\n\t\tcode: string,\n\t\tmessage: string,\n\t\toptions?: { cause?: unknown; details?: Record<string, unknown> },\n\t) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t\tthis.details = Object.freeze({ ...(options?.details ?? {}) });\n\t}\n}\n\n/**\n * Append a \"report-a-bug\" footer to an error message. Used only on truly unreachable\n * internal errors — never on user-facing validation / configuration errors where the user\n * is supposed to fix something on their end.\n */\nexport function bugReportFooter(): string {\n\treturn `\\nThis indicates a bug in @neondatabase/config. Please file an issue: ${ISSUE_URL}`;\n}\n\n/**\n * Thrown by {@link defineConfig} when the user-provided configuration object is invalid.\n *\n * The class collects every validation failure rather than throwing on the first one so that\n * users get a complete picture of what is wrong with their `neon.ts`.\n */\nexport class ConfigValidationError extends PlatformError {\n\toverride readonly name = \"ConfigValidationError\";\n\treadonly issues: readonly string[];\n\n\tconstructor(issues: readonly string[]) {\n\t\tsuper(\n\t\t\t\"PLATFORM_INVALID_CONFIG\",\n\t\t\t`Invalid Neon platform config:\\n - ${issues.join(\"\\n - \")}`,\n\t\t);\n\t\tthis.issues = issues;\n\t}\n}\n\n/**\n * Thrown when the package cannot resolve which Neon project to operate on.\n *\n * Per the package's read-only-filesystem contract, we never create a `.neon` context file;\n * callers must either pass `projectId`/`orgId` explicitly or rely on an existing context file\n * (`.neon/project.json` or neonctl's `.neon`).\n */\nexport class MissingContextError extends PlatformError {\n\toverride readonly name = \"MissingContextError\";\n\n\tconstructor(message: string) {\n\t\tsuper(\"PLATFORM_MISSING_CONTEXT\", message);\n\t}\n}\n\n/**\n * Thrown by {@link pushConfig} when it detects differences between the local config and\n * the remote project that the caller hasn't opted in to apply.\n *\n * The message lists every conflict with both the current and desired value plus a\n * per-conflict hint. Mutable branch drift is applied by passing `updateExisting: true`.\n */\nexport class PushConflictError extends PlatformError {\n\toverride readonly name = \"PushConflictError\";\n\treadonly conflicts: readonly ConflictReport[];\n\n\tconstructor(conflicts: readonly ConflictReport[]) {\n\t\tconst lines: string[] = [\n\t\t\t\"pushConfig refused to apply: local config conflicts with remote state.\",\n\t\t\t\"\",\n\t\t];\n\t\tfor (const c of conflicts) {\n\t\t\tlines.push(\n\t\t\t\t` - [${c.kind}:${c.identifier}] ${c.field}: ${c.reason}`,\n\t\t\t\t` current : ${formatValue(c.current)}`,\n\t\t\t\t` desired : ${formatValue(c.desired)}`,\n\t\t\t\t` fix : ${suggestFix(c)}`,\n\t\t\t);\n\t\t}\n\t\tconst hasMutable = conflicts.some((c) => !isImmutableConflict(c));\n\t\tlines.push(\"\");\n\t\tif (hasMutable) {\n\t\t\tlines.push(\n\t\t\t\t\"For mutable conflicts, pass `updateExisting: true` (SDK) / `--update-existing` (CLI) to apply.\",\n\t\t\t);\n\t\t}\n\n\t\tsuper(\"PLATFORM_PUSH_CONFLICT\", lines.join(\"\\n\"), {\n\t\t\tdetails: { conflicts: conflicts.map((c) => ({ ...c })) },\n\t\t});\n\t\tthis.conflicts = conflicts;\n\t}\n}\n\nfunction isImmutableConflict(_c: ConflictReport): boolean {\n\treturn false;\n}\n\nfunction suggestFix(c: ConflictReport): string {\n\tif (isImmutableConflict(c)) {\n\t\treturn \"immutable on Neon — recreate the project, or change your `neon.ts` to match the remote.\";\n\t}\n\tif (c.kind === \"branch\" && c.field === \"parent\") {\n\t\treturn \"create the parent branch on Neon first, or change the `parent` reference to an existing branch.\";\n\t}\n\treturn \"pass `updateExisting: true` (SDK) / `--update-existing` (CLI) to apply.\";\n}\n\n/**\n * Thrown by {@link pushConfig} when the caller-supplied `confirm` callback declines a\n * push that requires confirmation (protected branch and/or mutable drift overriding\n * existing remote settings).\n *\n * The CLI maps this to a non-zero exit so users see \"aborted\" rather than a stack trace.\n */\nexport class PushAbortedError extends PlatformError {\n\toverride readonly name = \"PushAbortedError\";\n\treadonly branchName: string;\n\treadonly reasons: readonly (\"protected-branch\" | \"override-updates\")[];\n\n\tconstructor(\n\t\tbranchName: string,\n\t\treasons: readonly (\"protected-branch\" | \"override-updates\")[],\n\t) {\n\t\tsuper(\n\t\t\t\"PLATFORM_PUSH_ABORTED\",\n\t\t\t[\n\t\t\t\t`Aborted push to branch ${JSON.stringify(branchName)}.`,\n\t\t\t\treasons.length > 0\n\t\t\t\t\t? `Reason${reasons.length === 1 ? \"\" : \"s\"}: ${reasons.join(\", \")}.`\n\t\t\t\t\t: undefined,\n\t\t\t\t\"Re-run with `--update-existing` (override existing settings) or `--allow-protected-branch` (push to a protected branch) to skip the prompt.\",\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(\" \"),\n\t\t\t{ details: { branchName, reasons: [...reasons] } },\n\t\t);\n\t\tthis.branchName = branchName;\n\t\tthis.reasons = reasons;\n\t}\n}\n\n/**\n * Thrown when the SDK fails to find or load a `neon.ts` config file.\n */\nexport class ConfigLoadError extends PlatformError {\n\toverride readonly name = \"ConfigLoadError\";\n\n\tconstructor(message: string, options?: { cause?: unknown }) {\n\t\tsuper(\"PLATFORM_CONFIG_LOAD_FAILED\", message, options);\n\t}\n}\n\nfunction formatValue(value: unknown): string {\n\tif (value === undefined) return \"<unset>\";\n\tif (typeof value === \"string\") return JSON.stringify(value);\n\tif (typeof value === \"object\" && value !== null)\n\t\treturn JSON.stringify(value);\n\treturn String(value);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"errors.js","names":[],"sources":["../../src/lib/errors.ts"],"sourcesContent":["import type { ConflictReport } from \"./types.js\";\n\n/**\n * Every code a {@link PlatformError} can carry. Stable identifiers — consumers can rely on\n * these for `instanceof PlatformError && err.code === ErrorCode.…` style checks instead of\n * matching on free-text messages.\n *\n * Grouped by source:\n * - `PLATFORM_INVALID_CONFIG` — `defineConfig` / `configSchema` rejected the input.\n * - `PLATFORM_MISSING_CONTEXT` — no project / branch context could be resolved.\n * - `PLATFORM_PUSH_CONFLICT` — local config conflicts with remote and the caller did not\n * opt in to apply.\n * - `PLATFORM_CONFIG_LOAD_FAILED` — `neon.ts` could not be found or evaluated.\n * - `PLATFORM_MISSING_API_KEY` — no `NEON_API_KEY` and no explicit `apiKey` was provided.\n * - `PLATFORM_MISSING_PARENT_BRANCH` — push tried to create a child of a non-existent\n * branch.\n * - `PLATFORM_UNAUTHORIZED` / `PLATFORM_FORBIDDEN` / `PLATFORM_NOT_FOUND` /\n * `PLATFORM_CONFLICT` / `PLATFORM_RATE_LIMITED` / `PLATFORM_LOCKED` /\n * `PLATFORM_SERVER_ERROR` — wrappings of Neon HTTP failures.\n * - `PLATFORM_NETWORK_ERROR` — transport-level failure (no HTTP response at all).\n * - `PLATFORM_INTERNAL_ERROR` — invariant violations. Should never happen in production;\n * if you see one, please open an issue.\n */\nexport const ErrorCode = {\n\tInvalidConfig: \"PLATFORM_INVALID_CONFIG\",\n\tEnvNotInjected: \"PLATFORM_ENV_NOT_INJECTED\",\n\tMissingContext: \"PLATFORM_MISSING_CONTEXT\",\n\tPushConflict: \"PLATFORM_PUSH_CONFLICT\",\n\tPushAborted: \"PLATFORM_PUSH_ABORTED\",\n\tConfigLoadFailed: \"PLATFORM_CONFIG_LOAD_FAILED\",\n\tMissingApiKey: \"PLATFORM_MISSING_API_KEY\",\n\tAmbiguousBranchAuth: \"PLATFORM_AMBIGUOUS_BRANCH_AUTH\",\n\tBranchNotFound: \"PLATFORM_BRANCH_NOT_FOUND\",\n\tFeatureUnavailable: \"PLATFORM_FEATURE_UNAVAILABLE\",\n\tMissingParentBranch: \"PLATFORM_MISSING_PARENT_BRANCH\",\n\tUnauthorized: \"PLATFORM_UNAUTHORIZED\",\n\tForbidden: \"PLATFORM_FORBIDDEN\",\n\tNotFound: \"PLATFORM_NOT_FOUND\",\n\tConflict: \"PLATFORM_CONFLICT\",\n\tRateLimited: \"PLATFORM_RATE_LIMITED\",\n\tLocked: \"PLATFORM_LOCKED\",\n\tServerError: \"PLATFORM_SERVER_ERROR\",\n\tNetworkError: \"PLATFORM_NETWORK_ERROR\",\n\tInternalError: \"PLATFORM_INTERNAL_ERROR\",\n} as const;\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\nconst ISSUE_URL = \"https://github.com/neondatabase/neon-pkgs/issues/new\";\n\n/**\n * Base class for all errors thrown by `@neondatabase/config`. Always extend this so callers\n * can catch every package-thrown error with a single `instanceof` check.\n *\n * Optional `details` carries structured context that the CLI prints under `--debug` and\n * that programmatic consumers can read (e.g. `details.status` for HTTP wrappings,\n * `details.requestId` for Neon API failures).\n */\nexport class PlatformError extends Error {\n\toverride readonly name: string = \"PlatformError\";\n\treadonly code: string;\n\treadonly details: Readonly<Record<string, unknown>>;\n\n\tconstructor(\n\t\tcode: string,\n\t\tmessage: string,\n\t\toptions?: { cause?: unknown; details?: Record<string, unknown> },\n\t) {\n\t\tsuper(message, options);\n\t\tthis.code = code;\n\t\tthis.details = Object.freeze({ ...(options?.details ?? {}) });\n\t}\n}\n\n/**\n * Append a \"report-a-bug\" footer to an error message. Used only on truly unreachable\n * internal errors — never on user-facing validation / configuration errors where the user\n * is supposed to fix something on their end.\n */\nexport function bugReportFooter(): string {\n\treturn `\\nThis indicates a bug in @neondatabase/config. Please file an issue: ${ISSUE_URL}`;\n}\n\n/**\n * Thrown by {@link defineConfig} when the user-provided configuration object is invalid.\n *\n * The class collects every validation failure rather than throwing on the first one so that\n * users get a complete picture of what is wrong with their `neon.ts`.\n */\nexport class ConfigValidationError extends PlatformError {\n\toverride readonly name = \"ConfigValidationError\";\n\treadonly issues: readonly string[];\n\n\tconstructor(issues: readonly string[]) {\n\t\tsuper(\n\t\t\t\"PLATFORM_INVALID_CONFIG\",\n\t\t\t`Invalid Neon platform config:\\n - ${issues.join(\"\\n - \")}`,\n\t\t);\n\t\tthis.issues = issues;\n\t}\n}\n\n/**\n * Thrown when the package cannot resolve which Neon project to operate on.\n *\n * Per the package's read-only-filesystem contract, we never create a `.neon` context file;\n * callers must either pass `projectId`/`orgId` explicitly or rely on an existing context file\n * (`.neon/project.json` or neonctl's `.neon`).\n */\nexport class MissingContextError extends PlatformError {\n\toverride readonly name = \"MissingContextError\";\n\n\tconstructor(message: string) {\n\t\tsuper(\"PLATFORM_MISSING_CONTEXT\", message);\n\t}\n}\n\n/**\n * Thrown by {@link pushConfig} when it detects differences between the local config and\n * the remote project that the caller hasn't opted in to apply.\n *\n * The message lists every conflict with both the current and desired value plus a\n * per-conflict hint. Mutable branch drift is applied by passing `updateExisting: true`.\n */\nexport class PushConflictError extends PlatformError {\n\toverride readonly name = \"PushConflictError\";\n\treadonly conflicts: readonly ConflictReport[];\n\n\tconstructor(conflicts: readonly ConflictReport[]) {\n\t\tconst lines: string[] = [\n\t\t\t\"pushConfig refused to apply: local config conflicts with remote state.\",\n\t\t\t\"\",\n\t\t];\n\t\tfor (const c of conflicts) {\n\t\t\tlines.push(\n\t\t\t\t` - [${c.kind}:${c.identifier}] ${c.field}: ${c.reason}`,\n\t\t\t\t` current : ${formatValue(c.current)}`,\n\t\t\t\t` desired : ${formatValue(c.desired)}`,\n\t\t\t\t` fix : ${suggestFix(c)}`,\n\t\t\t);\n\t\t}\n\t\tconst hasMutable = conflicts.some((c) => !isImmutableConflict(c));\n\t\tlines.push(\"\");\n\t\tif (hasMutable) {\n\t\t\tlines.push(\n\t\t\t\t\"For mutable conflicts, pass `updateExisting: true` (SDK) / `--update-existing` (CLI) to apply.\",\n\t\t\t);\n\t\t}\n\n\t\tsuper(\"PLATFORM_PUSH_CONFLICT\", lines.join(\"\\n\"), {\n\t\t\tdetails: { conflicts: conflicts.map((c) => ({ ...c })) },\n\t\t});\n\t\tthis.conflicts = conflicts;\n\t}\n}\n\nfunction isImmutableConflict(_c: ConflictReport): boolean {\n\treturn false;\n}\n\nfunction suggestFix(c: ConflictReport): string {\n\tif (isImmutableConflict(c)) {\n\t\treturn \"immutable on Neon — recreate the project, or change your `neon.ts` to match the remote.\";\n\t}\n\tif (c.kind === \"branch\" && c.field === \"parent\") {\n\t\treturn \"create the parent branch on Neon first, or change the `parent` reference to an existing branch.\";\n\t}\n\treturn \"pass `updateExisting: true` (SDK) / `--update-existing` (CLI) to apply.\";\n}\n\n/**\n * Thrown by {@link pushConfig} when the caller-supplied `confirm` callback declines a\n * push that requires confirmation (protected branch and/or mutable drift overriding\n * existing remote settings).\n *\n * The CLI maps this to a non-zero exit so users see \"aborted\" rather than a stack trace.\n */\nexport class PushAbortedError extends PlatformError {\n\toverride readonly name = \"PushAbortedError\";\n\treadonly branchName: string;\n\treadonly reasons: readonly (\"protected-branch\" | \"override-updates\")[];\n\n\tconstructor(\n\t\tbranchName: string,\n\t\treasons: readonly (\"protected-branch\" | \"override-updates\")[],\n\t) {\n\t\tsuper(\n\t\t\t\"PLATFORM_PUSH_ABORTED\",\n\t\t\t[\n\t\t\t\t`Aborted push to branch ${JSON.stringify(branchName)}.`,\n\t\t\t\treasons.length > 0\n\t\t\t\t\t? `Reason${reasons.length === 1 ? \"\" : \"s\"}: ${reasons.join(\", \")}.`\n\t\t\t\t\t: undefined,\n\t\t\t\t\"Re-run with `--update-existing` (override existing settings) or `--allow-protected-branch` (push to a protected branch) to skip the prompt.\",\n\t\t\t]\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.join(\" \"),\n\t\t\t{ details: { branchName, reasons: [...reasons] } },\n\t\t);\n\t\tthis.branchName = branchName;\n\t\tthis.reasons = reasons;\n\t}\n}\n\n/**\n * Thrown when the SDK fails to find or load a `neon.ts` config file.\n */\nexport class ConfigLoadError extends PlatformError {\n\toverride readonly name = \"ConfigLoadError\";\n\n\tconstructor(message: string, options?: { cause?: unknown }) {\n\t\tsuper(\"PLATFORM_CONFIG_LOAD_FAILED\", message, options);\n\t}\n}\n\nfunction formatValue(value: unknown): string {\n\tif (value === undefined) return \"<unset>\";\n\tif (typeof value === \"string\") return JSON.stringify(value);\n\tif (typeof value === \"object\" && value !== null)\n\t\treturn JSON.stringify(value);\n\treturn String(value);\n}\n"],"mappings":"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"}
|
|
@@ -37,9 +37,38 @@ interface RetryConfig {
|
|
|
37
37
|
* Exported only for tests; production callers go through the wrapped {@link NeonApi}.
|
|
38
38
|
*/
|
|
39
39
|
declare function retryOnLocked<T>(fn: () => Promise<T>, config: RetryConfig): Promise<T>;
|
|
40
|
+
/**
|
|
41
|
+
* Whether an error from a Preview-feature read means the feature simply isn't available
|
|
42
|
+
* for this project/branch/region (as opposed to a real, transient failure). Neon signals
|
|
43
|
+
* this a few ways: a 404 "this route does not exist" (the route isn't deployed at all), or
|
|
44
|
+
* a 503/4xx whose message says the platform feature is "not available" / "not enabled".
|
|
45
|
+
*
|
|
46
|
+
* Callers do **not** swallow this into an empty result — touching a Preview feature that
|
|
47
|
+
* isn't available is surfaced as a {@link previewUnavailableError} so `plan` / `status` /
|
|
48
|
+
* `pull` (and `neon dev`) fail clearly instead of, say, planning to create resources the
|
|
49
|
+
* API will refuse to create.
|
|
50
|
+
*/
|
|
51
|
+
declare function isPreviewFeatureUnavailable(err: unknown): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Convert a Preview-feature error into a clear {@link PlatformError} when the feature is
|
|
54
|
+
* unavailable for the project; otherwise pass the original error through unchanged so a
|
|
55
|
+
* genuine failure (auth, transient 5xx, …) keeps its specific code and message.
|
|
56
|
+
*/
|
|
57
|
+
declare function previewUnavailableError(err: unknown, featureLabel: string): unknown;
|
|
40
58
|
declare function createNeonAuthRestInput(input: {
|
|
41
59
|
databaseName?: string;
|
|
42
60
|
}): CreateNeonAuthRestInput;
|
|
61
|
+
/**
|
|
62
|
+
* Read a response body as JSON, tolerating non-JSON. Some Neon routes return a plain-text
|
|
63
|
+
* body (e.g. a 404 `"this route does not exist"` for a Preview feature not enabled in the
|
|
64
|
+
* project/region). Parsing that with `JSON.parse` used to throw a cryptic
|
|
65
|
+
* `SyntaxError: Unexpected token …`, which — because parsing happens before the `res.ok`
|
|
66
|
+
* check in {@link request} — masked the real HTTP status. We instead return the raw text
|
|
67
|
+
* wrapped as `{ message }` so the status-based error path in `request` / `wrapNeonError`
|
|
68
|
+
* runs and produces a proper {@link PlatformError} (e.g. `NotFound`), and a non-error body
|
|
69
|
+
* that simply isn't JSON degrades to text rather than crashing.
|
|
70
|
+
*/
|
|
71
|
+
declare function readJsonBody(res: Response): Promise<unknown>;
|
|
43
72
|
//#endregion
|
|
44
|
-
export { createNeonAuthRestInput, createRealNeonApi, retryOnLocked };
|
|
73
|
+
export { createNeonAuthRestInput, createRealNeonApi, isPreviewFeatureUnavailable, previewUnavailableError, readJsonBody, retryOnLocked };
|
|
45
74
|
//# sourceMappingURL=neon-api-real.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"neon-api-real.d.ts","names":[],"sources":["../../src/lib/neon-api-real.ts"],"mappings":";;;UAoFU,uBAAA;;EAAA,aAAA,CAAA,EAAA,MAAA;AAeV;AAyCC;AAeD;;;;AAES,iBA1DO,iBAAA,CA0DP,OAAA,EAAA;QACE,EAAA,MAAA;SAAR,CAAA,EAAA,MAAA;EAAO;
|
|
1
|
+
{"version":3,"file":"neon-api-real.d.ts","names":[],"sources":["../../src/lib/neon-api-real.ts"],"mappings":";;;UAoFU,uBAAA;;EAAA,aAAA,CAAA,EAAA,MAAA;AAeV;AAyCC;AAeD;;;;AAES,iBA1DO,iBAAA,CA0DP,OAAA,EAAA;QACE,EAAA,MAAA;SAAR,CAAA,EAAA,MAAA;EAAO;AAq0BV;AAsBA;AAmCA;AAmBA;EAAkC,aAAA,CAAA,EAAA;IAAM,WAAA,CAAA,EAAA,MAAA;IAAW,cAAA,CAAA,EAAA,MAAA;IAAO,UAAA,CAAA,EAAA,MAAA;;IA/7BtD;UA8BM,WAAA;;;;;;;;;;;;iBAaY,2BACX,QAAQ,YACV,cACN,QAAQ;;;;;;;;;;;;iBAq0BK,2BAAA;;;;;;iBAsBA,uBAAA;iBAmCA,uBAAA;;IAEZ;;;;;;;;;;;iBAiBkB,YAAA,MAAkB,WAAW"}
|
|
@@ -340,10 +340,14 @@ var RealNeonApi = class {
|
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
async listBranchBuckets(projectId, branchId) {
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
343
|
+
try {
|
|
344
|
+
return await this.call(`listBranchBuckets(${projectId}/${branchId})`, async () => {
|
|
345
|
+
const data = await this.getJson(branchPreviewPath(projectId, branchId, "buckets"));
|
|
346
|
+
return bucketsListResponseSchema.parse(data).buckets.map(bucketToSnapshot);
|
|
347
|
+
}, { projectId });
|
|
348
|
+
} catch (err) {
|
|
349
|
+
throw previewUnavailableError(err, "Object storage (buckets)");
|
|
350
|
+
}
|
|
347
351
|
}
|
|
348
352
|
async createBranchBucket(projectId, branchId, input) {
|
|
349
353
|
return this.call(`createBranchBucket(${projectId}/${branchId}/${input.name})`, async () => {
|
|
@@ -366,10 +370,14 @@ var RealNeonApi = class {
|
|
|
366
370
|
});
|
|
367
371
|
}
|
|
368
372
|
async listBranchFunctions(projectId, branchId) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
+
try {
|
|
374
|
+
return await this.call(`listBranchFunctions(${projectId}/${branchId})`, async () => {
|
|
375
|
+
const data = await this.getJson(branchPreviewPath(projectId, branchId, "functions"));
|
|
376
|
+
return functionsListResponseSchema.parse(data).functions.map(functionToSnapshot);
|
|
377
|
+
}, { projectId });
|
|
378
|
+
} catch (err) {
|
|
379
|
+
throw previewUnavailableError(err, "Functions");
|
|
380
|
+
}
|
|
373
381
|
}
|
|
374
382
|
async createBranchFunction(projectId, branchId, input) {
|
|
375
383
|
return this.call(`createBranchFunction(${projectId}/${branchId}/${input.slug})`, async () => {
|
|
@@ -406,6 +414,7 @@ var RealNeonApi = class {
|
|
|
406
414
|
return aiGatewayEnabledFromResponse(await this.getJson(aiGatewayPath(projectId, branchId)));
|
|
407
415
|
}, { projectId });
|
|
408
416
|
} catch (err) {
|
|
417
|
+
if (isPreviewFeatureUnavailable(err)) throw previewUnavailableError(err, "AI Gateway");
|
|
409
418
|
if (err instanceof PlatformError && err.code === ErrorCode.NotFound) return false;
|
|
410
419
|
throw err;
|
|
411
420
|
}
|
|
@@ -476,6 +485,36 @@ function aiGatewayEnabledFromResponse(data) {
|
|
|
476
485
|
if (data !== null && typeof data === "object" && "enabled" in data) return data.enabled === true;
|
|
477
486
|
return false;
|
|
478
487
|
}
|
|
488
|
+
/**
|
|
489
|
+
* Whether an error from a Preview-feature read means the feature simply isn't available
|
|
490
|
+
* for this project/branch/region (as opposed to a real, transient failure). Neon signals
|
|
491
|
+
* this a few ways: a 404 "this route does not exist" (the route isn't deployed at all), or
|
|
492
|
+
* a 503/4xx whose message says the platform feature is "not available" / "not enabled".
|
|
493
|
+
*
|
|
494
|
+
* Callers do **not** swallow this into an empty result — touching a Preview feature that
|
|
495
|
+
* isn't available is surfaced as a {@link previewUnavailableError} so `plan` / `status` /
|
|
496
|
+
* `pull` (and `neon dev`) fail clearly instead of, say, planning to create resources the
|
|
497
|
+
* API will refuse to create.
|
|
498
|
+
*/
|
|
499
|
+
function isPreviewFeatureUnavailable(err) {
|
|
500
|
+
if (!(err instanceof PlatformError)) return false;
|
|
501
|
+
const status = err.details.status;
|
|
502
|
+
const message = typeof err.details.neonMessage === "string" ? err.details.neonMessage.toLowerCase() : "";
|
|
503
|
+
return (message.includes("not available") || message.includes("does not exist") || message.includes("not enabled")) && (status === 503 || status === 404 || status === 501);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Convert a Preview-feature error into a clear {@link PlatformError} when the feature is
|
|
507
|
+
* unavailable for the project; otherwise pass the original error through unchanged so a
|
|
508
|
+
* genuine failure (auth, transient 5xx, …) keeps its specific code and message.
|
|
509
|
+
*/
|
|
510
|
+
function previewUnavailableError(err, featureLabel) {
|
|
511
|
+
if (!isPreviewFeatureUnavailable(err)) return err;
|
|
512
|
+
const neonMessage = err instanceof PlatformError && typeof err.details.neonMessage === "string" ? ` (Neon API said: "${err.details.neonMessage}")` : "";
|
|
513
|
+
return new PlatformError(ErrorCode.FeatureUnavailable, `${featureLabel} is a Preview feature that is not available for this project or region${neonMessage}. Enable it for your Neon account/project first, then re-run.`, {
|
|
514
|
+
cause: err,
|
|
515
|
+
details: { feature: featureLabel }
|
|
516
|
+
});
|
|
517
|
+
}
|
|
479
518
|
function neonAuthResponseToSnapshot(data) {
|
|
480
519
|
const snapshot = {
|
|
481
520
|
projectId: data.auth_provider_project_id,
|
|
@@ -492,10 +531,24 @@ function createNeonAuthRestInput(input) {
|
|
|
492
531
|
...input.databaseName ? { database_name: input.databaseName } : {}
|
|
493
532
|
};
|
|
494
533
|
}
|
|
534
|
+
/**
|
|
535
|
+
* Read a response body as JSON, tolerating non-JSON. Some Neon routes return a plain-text
|
|
536
|
+
* body (e.g. a 404 `"this route does not exist"` for a Preview feature not enabled in the
|
|
537
|
+
* project/region). Parsing that with `JSON.parse` used to throw a cryptic
|
|
538
|
+
* `SyntaxError: Unexpected token …`, which — because parsing happens before the `res.ok`
|
|
539
|
+
* check in {@link request} — masked the real HTTP status. We instead return the raw text
|
|
540
|
+
* wrapped as `{ message }` so the status-based error path in `request` / `wrapNeonError`
|
|
541
|
+
* runs and produces a proper {@link PlatformError} (e.g. `NotFound`), and a non-error body
|
|
542
|
+
* that simply isn't JSON degrades to text rather than crashing.
|
|
543
|
+
*/
|
|
495
544
|
async function readJsonBody(res) {
|
|
496
545
|
const text = await res.text();
|
|
497
546
|
if (text.trim() === "") return {};
|
|
498
|
-
|
|
547
|
+
try {
|
|
548
|
+
return JSON.parse(text);
|
|
549
|
+
} catch {
|
|
550
|
+
return { message: text.trim() };
|
|
551
|
+
}
|
|
499
552
|
}
|
|
500
553
|
function projectToSnapshot(project) {
|
|
501
554
|
const defaults = project.default_endpoint_settings;
|
|
@@ -577,6 +630,6 @@ function defaultsToComputeSettings(defaults) {
|
|
|
577
630
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
578
631
|
}
|
|
579
632
|
//#endregion
|
|
580
|
-
export { createNeonAuthRestInput, createRealNeonApi, retryOnLocked };
|
|
633
|
+
export { createNeonAuthRestInput, createRealNeonApi, isPreviewFeatureUnavailable, previewUnavailableError, readJsonBody, retryOnLocked };
|
|
581
634
|
|
|
582
635
|
//# sourceMappingURL=neon-api-real.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"neon-api-real.js","names":[],"sources":["../../src/lib/neon-api-real.ts"],"sourcesContent":["import {\n\ttype Branch,\n\ttype BranchCreateRequest,\n\ttype BranchCreateRequestEndpointOptions,\n\ttype BranchUpdateRequest,\n\tcreateApiClient,\n\ttype Database,\n\ttype DefaultEndpointSettings,\n\ttype Endpoint,\n\tEndpointType,\n\ttype EndpointUpdateRequest,\n\ttype PgVersion,\n\ttype Project,\n\ttype ProjectCreateRequest,\n\ttype ProjectListItem,\n\ttype ProjectUpdateRequest,\n\ttype Role,\n} from \"@neondatabase/api-client\";\nimport { z } from \"zod\";\nimport { formatSuspendTimeout, parseSuspendTimeout } from \"./duration.js\";\nimport { ErrorCode, PlatformError } from \"./errors.js\";\nimport type {\n\tCreateBranchInput,\n\tCreateBucketInput,\n\tCreateProjectInput,\n\tDeployFunctionInput,\n\tGetConnectionUriInput,\n\tNeonApi,\n\tNeonAuthSnapshot,\n\tNeonBranchSnapshot,\n\tNeonBucketSnapshot,\n\tNeonDataApiSnapshot,\n\tNeonDatabaseSnapshot,\n\tNeonEndpointSnapshot,\n\tNeonFunctionDeploymentSnapshot,\n\tNeonFunctionSnapshot,\n\tNeonProjectSnapshot,\n\tNeonRoleSnapshot,\n\tUpdateBranchInput,\n} from \"./neon-api.js\";\nimport type { BucketAccessLevel, ComputeSettings } from \"./types.js\";\nimport { wrapNeonError } from \"./wrap-neon-error.js\";\n\ntype ApiClient = ReturnType<typeof createApiClient>;\nconst DEFAULT_NEON_API_BASE_URL = \"https://console.neon.tech/api/v2\";\n\nconst neonAuthResponseSchema = z.object({\n\tauth_provider_project_id: z.string(),\n\tpub_client_key: z.string().optional(),\n\tsecret_server_key: z.string().optional(),\n\tjwks_url: z.string(),\n\tbase_url: z.string().optional(),\n});\n\n// ─── Preview: buckets ──────────────────────────────────────────────────────\n\nconst bucketSchema = z.object({\n\tname: z.string(),\n\taccess_level: z.string().optional(),\n});\nconst bucketResponseSchema = z.object({ bucket: bucketSchema });\nconst bucketsListResponseSchema = z.object({ buckets: z.array(bucketSchema) });\n\n// ─── Preview: functions ────────────────────────────────────────────────────\n\nconst functionDeploymentSchema = z.object({\n\tid: z.number(),\n\tstatus: z.string(),\n});\nconst neonFunctionSchema = z.object({\n\tid: z.string(),\n\tslug: z.string(),\n\tname: z.string(),\n\tinvocation_url: z.string(),\n\tactive_deployment: functionDeploymentSchema.optional(),\n});\nconst functionResponseSchema = z.object({ function: neonFunctionSchema });\nconst functionsListResponseSchema = z.object({\n\tfunctions: z.array(neonFunctionSchema),\n});\nconst functionDeploymentResponseSchema = z.object({\n\tdeployment: functionDeploymentSchema,\n});\n\ninterface CreateNeonAuthRestInput {\n\tauth_provider: \"better_auth\";\n\tdatabase_name?: string;\n}\n\ninterface RestConfig {\n\tapiKey: string;\n\tbaseUrl: string;\n}\n\n/**\n * Adapt `@neondatabase/api-client` to the narrow {@link NeonApi} façade used by the rest of\n * this package. Constructs are restricted to whole-object read/write of just the fields we\n * model in {@link Config}; anything else stays untouched on the remote.\n */\nexport function createRealNeonApi(options: {\n\tapiKey: string;\n\tbaseUrl?: string;\n\t/**\n\t * Tuning knob for the built-in 423 retry. Defaults: ~30s of total wait spread across\n\t * 12 attempts with exponential backoff capped at 5s. Lowering this is mostly useful in\n\t * tests; raising it is rarely needed because Neon operations are usually sub-second.\n\t */\n\tretryOnLocked?: {\n\t\tmaxAttempts?: number;\n\t\tinitialDelayMs?: number;\n\t\tmaxDelayMs?: number;\n\t};\n}): NeonApi {\n\tif (!options.apiKey || options.apiKey.trim() === \"\") {\n\t\tthrow new PlatformError(\n\t\t\tErrorCode.MissingApiKey,\n\t\t\t[\n\t\t\t\t\"createRealNeonApi requires a non-empty `apiKey`.\",\n\t\t\t\t\"Generate one at https://console.neon.tech/app/settings/api-keys and pass it as { apiKey: process.env.NEON_API_KEY }.\",\n\t\t\t].join(\" \"),\n\t\t);\n\t}\n\n\tconst client = createApiClient({\n\t\tapiKey: options.apiKey,\n\t\t...(options.baseUrl ? { baseURL: options.baseUrl } : {}),\n\t});\n\n\treturn new RealNeonApi(\n\t\tclient,\n\t\t{\n\t\t\tmaxAttempts: options.retryOnLocked?.maxAttempts ?? 12,\n\t\t\tinitialDelayMs: options.retryOnLocked?.initialDelayMs ?? 250,\n\t\t\tmaxDelayMs: options.retryOnLocked?.maxDelayMs ?? 5_000,\n\t\t},\n\t\t{\n\t\t\tapiKey: options.apiKey,\n\t\t\tbaseUrl: options.baseUrl ?? DEFAULT_NEON_API_BASE_URL,\n\t\t},\n\t);\n}\n\ninterface RetryConfig {\n\tmaxAttempts: number;\n\tinitialDelayMs: number;\n\tmaxDelayMs: number;\n}\n\n/**\n * Retry a function whenever it throws an HTTP 423 (Locked) — Neon's signal that a prior\n * mutation on the same resource is still in flight. Uses exponential backoff capped at\n * `maxDelayMs`. Any other error (and the last attempt) propagates.\n *\n * Exported only for tests; production callers go through the wrapped {@link NeonApi}.\n */\nexport async function retryOnLocked<T>(\n\tfn: () => Promise<T>,\n\tconfig: RetryConfig,\n): Promise<T> {\n\tlet delay = config.initialDelayMs;\n\tlet lastError: unknown;\n\tfor (let attempt = 1; attempt <= config.maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} catch (err) {\n\t\t\tlastError = err;\n\t\t\tconst status = readHttpStatusFromError(err);\n\t\t\tif (status !== 423 || attempt === config.maxAttempts) throw err;\n\t\t\tawait sleep(delay);\n\t\t\tdelay = Math.min(delay * 2, config.maxDelayMs);\n\t\t}\n\t}\n\tthrow lastError;\n}\n\nfunction readHttpStatusFromError(err: unknown): number | undefined {\n\tif (err === null || typeof err !== \"object\") return undefined;\n\tconst response = (err as { response?: unknown }).response;\n\tif (response === null || typeof response !== \"object\") return undefined;\n\tconst status = (response as { status?: unknown }).status;\n\treturn typeof status === \"number\" ? status : undefined;\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nclass RealNeonApi implements NeonApi {\n\tconstructor(\n\t\tprivate readonly client: ApiClient,\n\t\tprivate readonly retryConfig: RetryConfig,\n\t\tprivate readonly restConfig: RestConfig,\n\t) {}\n\n\tprivate retry<T>(fn: () => Promise<T>): Promise<T> {\n\t\treturn retryOnLocked(fn, this.retryConfig);\n\t}\n\n\tprivate async call<T>(\n\t\top: string,\n\t\tfn: () => Promise<T>,\n\t\toptions: { projectId?: string; mutating?: boolean } = {},\n\t): Promise<T> {\n\t\ttry {\n\t\t\treturn options.mutating ? await this.retry(fn) : await fn();\n\t\t} catch (err) {\n\t\t\tconst wrapped = wrapNeonError(\n\t\t\t\terr,\n\t\t\t\toptions.projectId\n\t\t\t\t\t? { op, projectId: options.projectId }\n\t\t\t\t\t: { op },\n\t\t\t);\n\t\t\tthrow wrapped;\n\t\t}\n\t}\n\n\tasync listProjects(filter: {\n\t\torgId?: string;\n\t}): Promise<NeonProjectSnapshot[]> {\n\t\treturn this.call(\n\t\t\tfilter.orgId ? `listProjects(org=${filter.orgId})` : \"listProjects\",\n\t\t\tasync () => {\n\t\t\t\tconst projects: ProjectListItem[] = [];\n\t\t\t\tlet cursor: string | undefined;\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst res = await this.client.listProjects({\n\t\t\t\t\t\t...(filter.orgId ? { org_id: filter.orgId } : {}),\n\t\t\t\t\t\t...(cursor ? { cursor } : {}),\n\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t});\n\t\t\t\t\tprojects.push(...res.data.projects);\n\t\t\t\t\tconst next = (\n\t\t\t\t\t\tres.data as { pagination?: { next?: string } }\n\t\t\t\t\t).pagination?.next;\n\t\t\t\t\tif (!next || next === cursor) break;\n\t\t\t\t\tcursor = next;\n\t\t\t\t}\n\t\t\t\treturn projects.map(projectToSnapshot);\n\t\t\t},\n\t\t);\n\t}\n\n\tasync getProject(projectId: string): Promise<NeonProjectSnapshot> {\n\t\treturn this.call(\n\t\t\t`getProject(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.getProject(projectId);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync createProject(\n\t\tinput: CreateProjectInput,\n\t): Promise<NeonProjectSnapshot> {\n\t\tconst body: ProjectCreateRequest = {\n\t\t\tproject: {\n\t\t\t\tname: input.name,\n\t\t\t\tregion_id: input.regionId,\n\t\t\t\t...(input.pgVersion !== undefined\n\t\t\t\t\t? { pg_version: input.pgVersion as PgVersion }\n\t\t\t\t\t: {}),\n\t\t\t\t...(input.orgId ? { org_id: input.orgId } : {}),\n\t\t\t\t...(input.defaultEndpointSettings\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tdefault_endpoint_settings:\n\t\t\t\t\t\t\t\tcomputeSettingsToDefaults(\n\t\t\t\t\t\t\t\t\tinput.defaultEndpointSettings,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\t...(input.defaultBranchName\n\t\t\t\t\t? { branch: { name: input.defaultBranchName } }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t};\n\t\treturn this.call(\n\t\t\t`createProject(${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.createProject(body);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ mutating: true },\n\t\t);\n\t}\n\n\tasync updateProject(\n\t\tprojectId: string,\n\t\tinput: { name?: string; defaultEndpointSettings?: ComputeSettings },\n\t): Promise<NeonProjectSnapshot> {\n\t\tconst body: ProjectUpdateRequest = {\n\t\t\tproject: {\n\t\t\t\t...(input.name !== undefined ? { name: input.name } : {}),\n\t\t\t\t...(input.defaultEndpointSettings\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tdefault_endpoint_settings:\n\t\t\t\t\t\t\t\tcomputeSettingsToDefaults(\n\t\t\t\t\t\t\t\t\tinput.defaultEndpointSettings,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t};\n\t\treturn this.call(\n\t\t\t`updateProject(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProject(projectId, body);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listBranches(projectId: string): Promise<NeonBranchSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranches(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst branches: Branch[] = [];\n\t\t\t\tlet cursor: string | undefined;\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst res = await this.client.listProjectBranches({\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t\t...(cursor ? { cursor } : {}),\n\t\t\t\t\t});\n\t\t\t\t\tbranches.push(...(res.data.branches as Branch[]));\n\t\t\t\t\tconst next = (\n\t\t\t\t\t\tres.data as { pagination?: { next?: string } }\n\t\t\t\t\t).pagination?.next;\n\t\t\t\t\tif (!next || next === cursor) break;\n\t\t\t\t\tcursor = next;\n\t\t\t\t}\n\t\t\t\treturn branches.map(branchToSnapshot);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync createBranch(\n\t\tprojectId: string,\n\t\tinput: CreateBranchInput,\n\t): Promise<{\n\t\tbranch: NeonBranchSnapshot;\n\t\tendpoints: NeonEndpointSnapshot[];\n\t}> {\n\t\tconst endpointOptions: BranchCreateRequestEndpointOptions | undefined =\n\t\t\tinput.computeSettings\n\t\t\t\t? {\n\t\t\t\t\t\ttype: EndpointType.ReadWrite,\n\t\t\t\t\t\t...computeSettingsToEndpointOptions(\n\t\t\t\t\t\t\tinput.computeSettings,\n\t\t\t\t\t\t),\n\t\t\t\t\t}\n\t\t\t\t: { type: EndpointType.ReadWrite };\n\n\t\tconst body: BranchCreateRequest = {\n\t\t\tbranch: {\n\t\t\t\tname: input.name,\n\t\t\t\t...(input.parentId ? { parent_id: input.parentId } : {}),\n\t\t\t\t...(input.expiresAt ? { expires_at: input.expiresAt } : {}),\n\t\t\t\t...(input.protected !== undefined\n\t\t\t\t\t? { protected: input.protected }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\tendpoints: [endpointOptions],\n\t\t};\n\t\treturn this.call(\n\t\t\t`createBranch(${projectId}/${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.createProjectBranch(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbody,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tbranch: branchToSnapshot(res.data.branch),\n\t\t\t\t\tendpoints: (res.data.endpoints ?? []).map(\n\t\t\t\t\t\tendpointToSnapshot,\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync updateBranch(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: UpdateBranchInput,\n\t): Promise<NeonBranchSnapshot> {\n\t\tconst branch: BranchUpdateRequest[\"branch\"] = {};\n\t\tif (input.name !== undefined) branch.name = input.name;\n\t\tif (input.expiresAt !== undefined) branch.expires_at = input.expiresAt;\n\t\tif (input.protected !== undefined) branch.protected = input.protected;\n\t\treturn this.call(\n\t\t\t`updateBranch(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProjectBranch(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t\t{ branch },\n\t\t\t\t);\n\t\t\t\treturn branchToSnapshot(res.data.branch);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listEndpoints(projectId: string): Promise<NeonEndpointSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listEndpoints(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectEndpoints(projectId);\n\t\t\t\treturn (res.data.endpoints as Endpoint[]).map(\n\t\t\t\t\tendpointToSnapshot,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync updateEndpoint(\n\t\tprojectId: string,\n\t\tendpointId: string,\n\t\tsettings: ComputeSettings,\n\t): Promise<NeonEndpointSnapshot> {\n\t\tconst endpoint: EndpointUpdateRequest[\"endpoint\"] =\n\t\t\tcomputeSettingsToEndpointOptions(settings);\n\t\treturn this.call(\n\t\t\t`updateEndpoint(${projectId}/${endpointId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProjectEndpoint(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tendpointId,\n\t\t\t\t\t{ endpoint },\n\t\t\t\t);\n\t\t\t\treturn endpointToSnapshot(res.data.endpoint);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listBranchRoles(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonRoleSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranchRoles(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectBranchRoles(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t);\n\t\t\t\treturn (res.data.roles as Role[]).map(roleToSnapshot);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync listBranchDatabases(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonDatabaseSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranchDatabases(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectBranchDatabases(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t);\n\t\t\t\treturn (res.data.databases as Database[]).map(\n\t\t\t\t\tdatabaseToSnapshot,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync getConnectionUri(\n\t\tprojectId: string,\n\t\tinput: GetConnectionUriInput,\n\t): Promise<{ uri: string }> {\n\t\tconst op = `getConnectionUri(${projectId}/${input.databaseName}@${input.roleName}${input.pooled ? \" pooled\" : \"\"})`;\n\t\t// Always send `pooled` explicitly. The Neon API has switched its default\n\t\t// to returning the pooled URI when the parameter is omitted, so we have\n\t\t// to be explicit to get the direct URI back.\n\t\tconst pooled = input.pooled === true;\n\t\treturn this.call(\n\t\t\top,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.getConnectionUri({\n\t\t\t\t\tprojectId,\n\t\t\t\t\tdatabase_name: input.databaseName,\n\t\t\t\t\trole_name: input.roleName,\n\t\t\t\t\t...(input.branchId ? { branch_id: input.branchId } : {}),\n\t\t\t\t\t...(input.endpointId\n\t\t\t\t\t\t? { endpoint_id: input.endpointId }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\tpooled,\n\t\t\t\t});\n\t\t\t\treturn { uri: res.data.uri };\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync getNeonAuth(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonAuthSnapshot | null> {\n\t\t// `GET /projects/:pid/branches/:bid/auth` returns 404 when no integration exists.\n\t\t// Surface that as `null` so callers can branch cleanly instead of try/catch.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getNeonAuth(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.getNeonAuth(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t);\n\t\t\t\t\treturn neonAuthResponseToSnapshot(res.data);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (err instanceof PlatformError && err.code === ErrorCode.NotFound)\n\t\t\t\treturn null;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableNeonAuth(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: { databaseName?: string } = {},\n\t): Promise<NeonAuthSnapshot> {\n\t\t// Idempotent: if an integration already exists on the branch, the POST returns 409\n\t\t// (`Conflict`). We swallow that and re-fetch the existing snapshot so callers can\n\t\t// rely on `enableNeonAuth` to be safe to invoke from any push, including no-ops.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`enableNeonAuth(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\t// TODO: switch back to `this.client.createNeonAuth` once\n\t\t\t\t\t// @neondatabase/api-client narrows this branch endpoint to `better_auth`.\n\t\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\t\t`/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/auth`,\n\t\t\t\t\t\tcreateNeonAuthRestInput(input),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = neonAuthResponseSchema.parse(data);\n\t\t\t\t\treturn neonAuthResponseToSnapshot(parsed);\n\t\t\t\t},\n\t\t\t\t{ projectId, mutating: true },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\terr instanceof PlatformError &&\n\t\t\t\terr.code === ErrorCode.Conflict\n\t\t\t) {\n\t\t\t\tconst existing = await this.getNeonAuth(projectId, branchId);\n\t\t\t\tif (existing) return existing;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tprivate async postJson(path: string, body: unknown): Promise<unknown> {\n\t\treturn this.request(\"POST\", path, {\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(body),\n\t\t});\n\t}\n\n\tprivate async getJson(path: string): Promise<unknown> {\n\t\treturn this.request(\"GET\", path);\n\t}\n\n\tprivate async deleteJson(path: string): Promise<unknown> {\n\t\treturn this.request(\"DELETE\", path);\n\t}\n\n\t/**\n\t * Upload a built function bundle via `multipart/form-data` to the deploy endpoint.\n\t * Sends the bundle as the `file` field plus the deploy params Neon requires.\n\t */\n\tprivate async postMultipart(\n\t\tpath: string,\n\t\tinput: DeployFunctionInput,\n\t): Promise<unknown> {\n\t\tconst form = new FormData();\n\t\tform.set(\n\t\t\t\"file\",\n\t\t\tnew Blob([input.bundle as BlobPart], {\n\t\t\t\ttype: \"application/zip\",\n\t\t\t}),\n\t\t\t\"bundle.zip\",\n\t\t);\n\t\tform.set(\"memory_mib\", String(input.memoryMib));\n\t\t// Keep concurrency internal for now. The API requires it, but the public\n\t\t// neon.ts config surface intentionally does not expose it yet.\n\t\tform.set(\"concurrency\", \"1\");\n\t\tform.set(\"runtime\", input.runtime);\n\t\tfor (const [key, value] of Object.entries(input.environment)) {\n\t\t\tform.set(`environment[${key}]`, value);\n\t\t}\n\t\treturn this.request(\"POST\", path, { body: form });\n\t}\n\n\tprivate async request(\n\t\tmethod: \"GET\" | \"POST\" | \"DELETE\",\n\t\tpath: string,\n\t\tinit: { headers?: Record<string, string>; body?: BodyInit } = {},\n\t): Promise<unknown> {\n\t\tconst url = `${this.restConfig.baseUrl.replace(/\\/+$/, \"\")}${path}`;\n\t\tconst res = await fetch(url, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${this.restConfig.apiKey}`,\n\t\t\t\t...(init.headers ?? {}),\n\t\t\t},\n\t\t\t...(init.body !== undefined ? { body: init.body } : {}),\n\t\t});\n\t\tconst data = await readJsonBody(res);\n\t\tif (!res.ok) {\n\t\t\tthrow {\n\t\t\t\tresponse: {\n\t\t\t\t\tstatus: res.status,\n\t\t\t\t\tdata,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn data;\n\t}\n\n\tasync getNeonDataApi(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tdatabaseName: string,\n\t): Promise<NeonDataApiSnapshot | null> {\n\t\t// Same shape as getNeonAuth — 404 means \"no integration on this branch/db\", which\n\t\t// we translate to `null` for the caller.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getNeonDataApi(${projectId}/${branchId}/${databaseName})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.getProjectBranchDataApi(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t\tdatabaseName,\n\t\t\t\t\t);\n\t\t\t\t\treturn { url: res.data.url };\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (err instanceof PlatformError && err.code === ErrorCode.NotFound)\n\t\t\t\treturn null;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableProjectBranchDataApi(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tdatabaseName: string,\n\t): Promise<NeonDataApiSnapshot> {\n\t\t// Idempotent in the same shape as `enableNeonAuth`: if an integration already\n\t\t// exists, the POST returns 409 and we re-fetch the existing snapshot.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`enableProjectBranchDataApi(${projectId}/${branchId}/${databaseName})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.createProjectBranchDataApi(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t\tdatabaseName,\n\t\t\t\t\t\t// Empty body — pick up Neon defaults (auth_provider inferred from\n\t\t\t\t\t\t// whether Neon Auth is also enabled; default schemas/grants).\n\t\t\t\t\t\t{},\n\t\t\t\t\t);\n\t\t\t\t\treturn { url: res.data.url };\n\t\t\t\t},\n\t\t\t\t{ projectId, mutating: true },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\terr instanceof PlatformError &&\n\t\t\t\terr.code === ErrorCode.Conflict\n\t\t\t) {\n\t\t\t\tconst existing = await this.getNeonDataApi(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t\tdatabaseName,\n\t\t\t\t);\n\t\t\t\tif (existing) return existing;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t// ─── Preview: buckets ──────────────────────────────────────────────────────\n\n\tasync listBranchBuckets(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonBucketSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranchBuckets(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"buckets\"),\n\t\t\t\t);\n\t\t\t\tconst parsed = bucketsListResponseSchema.parse(data);\n\t\t\t\treturn parsed.buckets.map(bucketToSnapshot);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync createBranchBucket(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: CreateBucketInput,\n\t): Promise<NeonBucketSnapshot> {\n\t\treturn this.call(\n\t\t\t`createBranchBucket(${projectId}/${branchId}/${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"buckets\"),\n\t\t\t\t\t{\n\t\t\t\t\t\tname: input.name,\n\t\t\t\t\t\t...(input.accessLevel\n\t\t\t\t\t\t\t? { access_level: input.accessLevel }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst parsed = bucketResponseSchema.parse(data);\n\t\t\t\treturn bucketToSnapshot(parsed.bucket);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deleteBranchBucket(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tbucketName: string,\n\t): Promise<void> {\n\t\tawait this.call(\n\t\t\t`deleteBranchBucket(${projectId}/${branchId}/${bucketName})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"buckets\")}/${encodeURIComponent(bucketName)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\t// ─── Preview: functions ────────────────────────────────────────────────────\n\n\tasync listBranchFunctions(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonFunctionSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranchFunctions(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"functions\"),\n\t\t\t\t);\n\t\t\t\tconst parsed = functionsListResponseSchema.parse(data);\n\t\t\t\treturn parsed.functions.map(functionToSnapshot);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync createBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: { slug: string; name: string },\n\t): Promise<NeonFunctionSnapshot> {\n\t\treturn this.call(\n\t\t\t`createBranchFunction(${projectId}/${branchId}/${input.slug})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"functions\"),\n\t\t\t\t\t{ slug: input.slug, name: input.name },\n\t\t\t\t);\n\t\t\t\tconst parsed = functionResponseSchema.parse(data);\n\t\t\t\treturn functionToSnapshot(parsed.function);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deleteBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tslug: string,\n\t): Promise<void> {\n\t\tawait this.call(\n\t\t\t`deleteBranchFunction(${projectId}/${branchId}/${slug})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"functions\")}/${encodeURIComponent(slug)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deployBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tslug: string,\n\t\tinput: DeployFunctionInput,\n\t): Promise<NeonFunctionDeploymentSnapshot> {\n\t\treturn this.call(\n\t\t\t`deployBranchFunction(${projectId}/${branchId}/${slug})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postMultipart(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"functions\")}/${encodeURIComponent(slug)}/deployments`,\n\t\t\t\t\tinput,\n\t\t\t\t);\n\t\t\t\tconst parsed = functionDeploymentResponseSchema.parse(data);\n\t\t\t\treturn deploymentToSnapshot(parsed.deployment);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\t// ─── Preview: AI Gateway ───────────────────────────────────────────────────\n\t//\n\t// TODO(neon-deploy): the AI Gateway routes are not yet in the public API spec we wired\n\t// the rest of this adapter against. The paths below follow the established branch-scoped\n\t// convention (`/projects/{p}/branches/{b}/ai-gateway`); confirm them against the real\n\t// API (and the exact enable/disable verb + response shape) before relying on this in\n\t// production, and swap to the typed `@neondatabase/api-client` method once it exists.\n\n\tasync getAiGatewayEnabled(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<boolean> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getAiGatewayEnabled(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\taiGatewayPath(projectId, branchId),\n\t\t\t\t\t);\n\t\t\t\t\treturn aiGatewayEnabledFromResponse(data);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (err instanceof PlatformError && err.code === ErrorCode.NotFound)\n\t\t\t\treturn false;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableAiGateway(projectId: string, branchId: string): Promise<void> {\n\t\tawait this.call(\n\t\t\t`enableAiGateway(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.postJson(aiGatewayPath(projectId, branchId), {\n\t\t\t\t\tenabled: true,\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync disableAiGateway(projectId: string, branchId: string): Promise<void> {\n\t\tawait this.call(\n\t\t\t`disableAiGateway(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(aiGatewayPath(projectId, branchId));\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n}\n\nfunction branchPreviewPath(\n\tprojectId: string,\n\tbranchId: string,\n\tresource: \"buckets\" | \"functions\",\n): string {\n\treturn `/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/${resource}`;\n}\n\nfunction aiGatewayPath(projectId: string, branchId: string): string {\n\treturn `/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/ai-gateway`;\n}\n\nfunction bucketToSnapshot(\n\tbucket: z.infer<typeof bucketSchema>,\n): NeonBucketSnapshot {\n\treturn {\n\t\tname: bucket.name,\n\t\taccessLevel: normalizeBucketAccessLevel(bucket.access_level),\n\t};\n}\n\n/**\n * The Neon API returns `access_level` as a free-form string (per the API guidelines:\n * responses use plain strings, not enums). Map the known values onto our union and treat\n * anything else as `private` — the safe default for an unrecognised access level.\n */\nfunction normalizeBucketAccessLevel(\n\tvalue: string | undefined,\n): BucketAccessLevel {\n\treturn value === \"public_read\" ? \"public_read\" : \"private\";\n}\n\nfunction functionToSnapshot(\n\tfn: z.infer<typeof neonFunctionSchema>,\n): NeonFunctionSnapshot {\n\tconst snapshot: NeonFunctionSnapshot = {\n\t\tid: fn.id,\n\t\tslug: fn.slug,\n\t\tname: fn.name,\n\t\tinvocationUrl: fn.invocation_url,\n\t};\n\tif (fn.active_deployment) {\n\t\tsnapshot.activeDeploymentId = fn.active_deployment.id;\n\t}\n\treturn snapshot;\n}\n\nfunction deploymentToSnapshot(\n\tdeployment: z.infer<typeof functionDeploymentSchema>,\n): NeonFunctionDeploymentSnapshot {\n\treturn {\n\t\tid: deployment.id,\n\t\tstatus: normalizeDeploymentStatus(deployment.status),\n\t};\n}\n\nfunction normalizeDeploymentStatus(\n\tvalue: string,\n): NeonFunctionDeploymentSnapshot[\"status\"] {\n\tswitch (value) {\n\t\tcase \"pending\":\n\t\tcase \"building\":\n\t\tcase \"completed\":\n\t\tcase \"failed\":\n\t\t\treturn value;\n\t\tdefault:\n\t\t\t// Unknown status from a newer server — surface as `pending` rather than throwing,\n\t\t\t// matching the API guideline that clients treat undocumented enum values leniently.\n\t\t\treturn \"pending\";\n\t}\n}\n\nfunction aiGatewayEnabledFromResponse(data: unknown): boolean {\n\tif (data !== null && typeof data === \"object\" && \"enabled\" in data) {\n\t\treturn (data as { enabled?: unknown }).enabled === true;\n\t}\n\treturn false;\n}\n\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\nasync function readJsonBody(res: Response): Promise<unknown> {\n\tconst text = await res.text();\n\tif (text.trim() === \"\") return {};\n\treturn JSON.parse(text);\n}\n\nfunction projectToSnapshot(\n\tproject: Project | ProjectListItem,\n): NeonProjectSnapshot {\n\tconst defaults = project.default_endpoint_settings;\n\tconst snapshot: NeonProjectSnapshot = {\n\t\tid: project.id,\n\t\tname: project.name,\n\t\tregionId: project.region_id,\n\t\tpgVersion: project.pg_version,\n\t};\n\tif (project.org_id) snapshot.orgId = project.org_id;\n\tif (defaults) {\n\t\tconst compute = defaultsToComputeSettings(defaults);\n\t\tif (compute) snapshot.defaultEndpointSettings = compute;\n\t}\n\treturn snapshot;\n}\n\nfunction branchToSnapshot(branch: Branch): NeonBranchSnapshot {\n\tconst snapshot: NeonBranchSnapshot = {\n\t\tid: branch.id,\n\t\tname: branch.name,\n\t\tisDefault: branch.default,\n\t\tprotected: branch.protected === true,\n\t};\n\tif (branch.parent_id) snapshot.parentId = branch.parent_id;\n\tif (branch.expires_at) snapshot.expiresAt = branch.expires_at;\n\treturn snapshot;\n}\n\nfunction endpointToSnapshot(endpoint: Endpoint): NeonEndpointSnapshot {\n\treturn {\n\t\tid: endpoint.id,\n\t\tbranchId: endpoint.branch_id,\n\t\ttype:\n\t\t\tendpoint.type === EndpointType.ReadOnly\n\t\t\t\t? \"read_only\"\n\t\t\t\t: \"read_write\",\n\t\tautoscalingLimitMinCu:\n\t\t\tendpoint.autoscaling_limit_min_cu as ComputeSettings[\"autoscalingLimitMinCu\"],\n\t\tautoscalingLimitMaxCu:\n\t\t\tendpoint.autoscaling_limit_max_cu as ComputeSettings[\"autoscalingLimitMaxCu\"],\n\t\tsuspendTimeout: formatSuspendTimeout(endpoint.suspend_timeout_seconds),\n\t};\n}\n\nfunction roleToSnapshot(role: Role): NeonRoleSnapshot {\n\treturn {\n\t\tname: role.name,\n\t\tbranchId: role.branch_id,\n\t\tprotected: role.protected ?? false,\n\t};\n}\n\nfunction databaseToSnapshot(database: Database): NeonDatabaseSnapshot {\n\treturn {\n\t\tname: database.name,\n\t\tbranchId: database.branch_id,\n\t\townerName: database.owner_name,\n\t};\n}\n\nfunction computeSettingsToDefaults(\n\tsettings: ComputeSettings,\n): DefaultEndpointSettings {\n\tconst out: DefaultEndpointSettings = {};\n\tif (settings.autoscalingLimitMinCu !== undefined)\n\t\tout.autoscaling_limit_min_cu = settings.autoscalingLimitMinCu;\n\tif (settings.autoscalingLimitMaxCu !== undefined)\n\t\tout.autoscaling_limit_max_cu = settings.autoscalingLimitMaxCu;\n\tif (settings.suspendTimeout !== undefined) {\n\t\tconst parsed = parseSuspendTimeout(settings.suspendTimeout);\n\t\tif (\"error\" in parsed) {\n\t\t\tthrow new PlatformError(\n\t\t\t\tErrorCode.InvalidConfig,\n\t\t\t\t`Invalid suspendTimeout: ${parsed.error}`,\n\t\t\t);\n\t\t}\n\t\tout.suspend_timeout_seconds = parsed.seconds;\n\t}\n\treturn out;\n}\n\nfunction computeSettingsToEndpointOptions(settings: ComputeSettings): {\n\tautoscaling_limit_min_cu?: number;\n\tautoscaling_limit_max_cu?: number;\n\tsuspend_timeout_seconds?: number;\n} {\n\tconst out: {\n\t\tautoscaling_limit_min_cu?: number;\n\t\tautoscaling_limit_max_cu?: number;\n\t\tsuspend_timeout_seconds?: number;\n\t} = {};\n\tif (settings.autoscalingLimitMinCu !== undefined)\n\t\tout.autoscaling_limit_min_cu = settings.autoscalingLimitMinCu;\n\tif (settings.autoscalingLimitMaxCu !== undefined)\n\t\tout.autoscaling_limit_max_cu = settings.autoscalingLimitMaxCu;\n\tif (settings.suspendTimeout !== undefined) {\n\t\tconst parsed = parseSuspendTimeout(settings.suspendTimeout);\n\t\tif (\"error\" in parsed) {\n\t\t\tthrow new PlatformError(\n\t\t\t\tErrorCode.InvalidConfig,\n\t\t\t\t`Invalid suspendTimeout: ${parsed.error}`,\n\t\t\t);\n\t\t}\n\t\tout.suspend_timeout_seconds = parsed.seconds;\n\t}\n\treturn out;\n}\n\nfunction defaultsToComputeSettings(\n\tdefaults: DefaultEndpointSettings,\n): ComputeSettings | undefined {\n\tconst out: ComputeSettings = {};\n\tif (defaults.autoscaling_limit_min_cu !== undefined)\n\t\tout.autoscalingLimitMinCu =\n\t\t\tdefaults.autoscaling_limit_min_cu as ComputeSettings[\"autoscalingLimitMinCu\"];\n\tif (defaults.autoscaling_limit_max_cu !== undefined)\n\t\tout.autoscalingLimitMaxCu =\n\t\t\tdefaults.autoscaling_limit_max_cu as ComputeSettings[\"autoscalingLimitMaxCu\"];\n\tif (defaults.suspend_timeout_seconds !== undefined)\n\t\tout.suspendTimeout = formatSuspendTimeout(\n\t\t\tdefaults.suspend_timeout_seconds,\n\t\t);\n\treturn Object.keys(out).length > 0 ? out : undefined;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"neon-api-real.js","names":[],"sources":["../../src/lib/neon-api-real.ts"],"sourcesContent":["import {\n\ttype Branch,\n\ttype BranchCreateRequest,\n\ttype BranchCreateRequestEndpointOptions,\n\ttype BranchUpdateRequest,\n\tcreateApiClient,\n\ttype Database,\n\ttype DefaultEndpointSettings,\n\ttype Endpoint,\n\tEndpointType,\n\ttype EndpointUpdateRequest,\n\ttype PgVersion,\n\ttype Project,\n\ttype ProjectCreateRequest,\n\ttype ProjectListItem,\n\ttype ProjectUpdateRequest,\n\ttype Role,\n} from \"@neondatabase/api-client\";\nimport { z } from \"zod\";\nimport { formatSuspendTimeout, parseSuspendTimeout } from \"./duration.js\";\nimport { ErrorCode, PlatformError } from \"./errors.js\";\nimport type {\n\tCreateBranchInput,\n\tCreateBucketInput,\n\tCreateProjectInput,\n\tDeployFunctionInput,\n\tGetConnectionUriInput,\n\tNeonApi,\n\tNeonAuthSnapshot,\n\tNeonBranchSnapshot,\n\tNeonBucketSnapshot,\n\tNeonDataApiSnapshot,\n\tNeonDatabaseSnapshot,\n\tNeonEndpointSnapshot,\n\tNeonFunctionDeploymentSnapshot,\n\tNeonFunctionSnapshot,\n\tNeonProjectSnapshot,\n\tNeonRoleSnapshot,\n\tUpdateBranchInput,\n} from \"./neon-api.js\";\nimport type { BucketAccessLevel, ComputeSettings } from \"./types.js\";\nimport { wrapNeonError } from \"./wrap-neon-error.js\";\n\ntype ApiClient = ReturnType<typeof createApiClient>;\nconst DEFAULT_NEON_API_BASE_URL = \"https://console.neon.tech/api/v2\";\n\nconst neonAuthResponseSchema = z.object({\n\tauth_provider_project_id: z.string(),\n\tpub_client_key: z.string().optional(),\n\tsecret_server_key: z.string().optional(),\n\tjwks_url: z.string(),\n\tbase_url: z.string().optional(),\n});\n\n// ─── Preview: buckets ──────────────────────────────────────────────────────\n\nconst bucketSchema = z.object({\n\tname: z.string(),\n\taccess_level: z.string().optional(),\n});\nconst bucketResponseSchema = z.object({ bucket: bucketSchema });\nconst bucketsListResponseSchema = z.object({ buckets: z.array(bucketSchema) });\n\n// ─── Preview: functions ────────────────────────────────────────────────────\n\nconst functionDeploymentSchema = z.object({\n\tid: z.number(),\n\tstatus: z.string(),\n});\nconst neonFunctionSchema = z.object({\n\tid: z.string(),\n\tslug: z.string(),\n\tname: z.string(),\n\tinvocation_url: z.string(),\n\tactive_deployment: functionDeploymentSchema.optional(),\n});\nconst functionResponseSchema = z.object({ function: neonFunctionSchema });\nconst functionsListResponseSchema = z.object({\n\tfunctions: z.array(neonFunctionSchema),\n});\nconst functionDeploymentResponseSchema = z.object({\n\tdeployment: functionDeploymentSchema,\n});\n\ninterface CreateNeonAuthRestInput {\n\tauth_provider: \"better_auth\";\n\tdatabase_name?: string;\n}\n\ninterface RestConfig {\n\tapiKey: string;\n\tbaseUrl: string;\n}\n\n/**\n * Adapt `@neondatabase/api-client` to the narrow {@link NeonApi} façade used by the rest of\n * this package. Constructs are restricted to whole-object read/write of just the fields we\n * model in {@link Config}; anything else stays untouched on the remote.\n */\nexport function createRealNeonApi(options: {\n\tapiKey: string;\n\tbaseUrl?: string;\n\t/**\n\t * Tuning knob for the built-in 423 retry. Defaults: ~30s of total wait spread across\n\t * 12 attempts with exponential backoff capped at 5s. Lowering this is mostly useful in\n\t * tests; raising it is rarely needed because Neon operations are usually sub-second.\n\t */\n\tretryOnLocked?: {\n\t\tmaxAttempts?: number;\n\t\tinitialDelayMs?: number;\n\t\tmaxDelayMs?: number;\n\t};\n}): NeonApi {\n\tif (!options.apiKey || options.apiKey.trim() === \"\") {\n\t\tthrow new PlatformError(\n\t\t\tErrorCode.MissingApiKey,\n\t\t\t[\n\t\t\t\t\"createRealNeonApi requires a non-empty `apiKey`.\",\n\t\t\t\t\"Generate one at https://console.neon.tech/app/settings/api-keys and pass it as { apiKey: process.env.NEON_API_KEY }.\",\n\t\t\t].join(\" \"),\n\t\t);\n\t}\n\n\tconst client = createApiClient({\n\t\tapiKey: options.apiKey,\n\t\t...(options.baseUrl ? { baseURL: options.baseUrl } : {}),\n\t});\n\n\treturn new RealNeonApi(\n\t\tclient,\n\t\t{\n\t\t\tmaxAttempts: options.retryOnLocked?.maxAttempts ?? 12,\n\t\t\tinitialDelayMs: options.retryOnLocked?.initialDelayMs ?? 250,\n\t\t\tmaxDelayMs: options.retryOnLocked?.maxDelayMs ?? 5_000,\n\t\t},\n\t\t{\n\t\t\tapiKey: options.apiKey,\n\t\t\tbaseUrl: options.baseUrl ?? DEFAULT_NEON_API_BASE_URL,\n\t\t},\n\t);\n}\n\ninterface RetryConfig {\n\tmaxAttempts: number;\n\tinitialDelayMs: number;\n\tmaxDelayMs: number;\n}\n\n/**\n * Retry a function whenever it throws an HTTP 423 (Locked) — Neon's signal that a prior\n * mutation on the same resource is still in flight. Uses exponential backoff capped at\n * `maxDelayMs`. Any other error (and the last attempt) propagates.\n *\n * Exported only for tests; production callers go through the wrapped {@link NeonApi}.\n */\nexport async function retryOnLocked<T>(\n\tfn: () => Promise<T>,\n\tconfig: RetryConfig,\n): Promise<T> {\n\tlet delay = config.initialDelayMs;\n\tlet lastError: unknown;\n\tfor (let attempt = 1; attempt <= config.maxAttempts; attempt++) {\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} catch (err) {\n\t\t\tlastError = err;\n\t\t\tconst status = readHttpStatusFromError(err);\n\t\t\tif (status !== 423 || attempt === config.maxAttempts) throw err;\n\t\t\tawait sleep(delay);\n\t\t\tdelay = Math.min(delay * 2, config.maxDelayMs);\n\t\t}\n\t}\n\tthrow lastError;\n}\n\nfunction readHttpStatusFromError(err: unknown): number | undefined {\n\tif (err === null || typeof err !== \"object\") return undefined;\n\tconst response = (err as { response?: unknown }).response;\n\tif (response === null || typeof response !== \"object\") return undefined;\n\tconst status = (response as { status?: unknown }).status;\n\treturn typeof status === \"number\" ? status : undefined;\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nclass RealNeonApi implements NeonApi {\n\tconstructor(\n\t\tprivate readonly client: ApiClient,\n\t\tprivate readonly retryConfig: RetryConfig,\n\t\tprivate readonly restConfig: RestConfig,\n\t) {}\n\n\tprivate retry<T>(fn: () => Promise<T>): Promise<T> {\n\t\treturn retryOnLocked(fn, this.retryConfig);\n\t}\n\n\tprivate async call<T>(\n\t\top: string,\n\t\tfn: () => Promise<T>,\n\t\toptions: { projectId?: string; mutating?: boolean } = {},\n\t): Promise<T> {\n\t\ttry {\n\t\t\treturn options.mutating ? await this.retry(fn) : await fn();\n\t\t} catch (err) {\n\t\t\tconst wrapped = wrapNeonError(\n\t\t\t\terr,\n\t\t\t\toptions.projectId\n\t\t\t\t\t? { op, projectId: options.projectId }\n\t\t\t\t\t: { op },\n\t\t\t);\n\t\t\tthrow wrapped;\n\t\t}\n\t}\n\n\tasync listProjects(filter: {\n\t\torgId?: string;\n\t}): Promise<NeonProjectSnapshot[]> {\n\t\treturn this.call(\n\t\t\tfilter.orgId ? `listProjects(org=${filter.orgId})` : \"listProjects\",\n\t\t\tasync () => {\n\t\t\t\tconst projects: ProjectListItem[] = [];\n\t\t\t\tlet cursor: string | undefined;\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst res = await this.client.listProjects({\n\t\t\t\t\t\t...(filter.orgId ? { org_id: filter.orgId } : {}),\n\t\t\t\t\t\t...(cursor ? { cursor } : {}),\n\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t});\n\t\t\t\t\tprojects.push(...res.data.projects);\n\t\t\t\t\tconst next = (\n\t\t\t\t\t\tres.data as { pagination?: { next?: string } }\n\t\t\t\t\t).pagination?.next;\n\t\t\t\t\tif (!next || next === cursor) break;\n\t\t\t\t\tcursor = next;\n\t\t\t\t}\n\t\t\t\treturn projects.map(projectToSnapshot);\n\t\t\t},\n\t\t);\n\t}\n\n\tasync getProject(projectId: string): Promise<NeonProjectSnapshot> {\n\t\treturn this.call(\n\t\t\t`getProject(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.getProject(projectId);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync createProject(\n\t\tinput: CreateProjectInput,\n\t): Promise<NeonProjectSnapshot> {\n\t\tconst body: ProjectCreateRequest = {\n\t\t\tproject: {\n\t\t\t\tname: input.name,\n\t\t\t\tregion_id: input.regionId,\n\t\t\t\t...(input.pgVersion !== undefined\n\t\t\t\t\t? { pg_version: input.pgVersion as PgVersion }\n\t\t\t\t\t: {}),\n\t\t\t\t...(input.orgId ? { org_id: input.orgId } : {}),\n\t\t\t\t...(input.defaultEndpointSettings\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tdefault_endpoint_settings:\n\t\t\t\t\t\t\t\tcomputeSettingsToDefaults(\n\t\t\t\t\t\t\t\t\tinput.defaultEndpointSettings,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t\t...(input.defaultBranchName\n\t\t\t\t\t? { branch: { name: input.defaultBranchName } }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t};\n\t\treturn this.call(\n\t\t\t`createProject(${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.createProject(body);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ mutating: true },\n\t\t);\n\t}\n\n\tasync updateProject(\n\t\tprojectId: string,\n\t\tinput: { name?: string; defaultEndpointSettings?: ComputeSettings },\n\t): Promise<NeonProjectSnapshot> {\n\t\tconst body: ProjectUpdateRequest = {\n\t\t\tproject: {\n\t\t\t\t...(input.name !== undefined ? { name: input.name } : {}),\n\t\t\t\t...(input.defaultEndpointSettings\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tdefault_endpoint_settings:\n\t\t\t\t\t\t\t\tcomputeSettingsToDefaults(\n\t\t\t\t\t\t\t\t\tinput.defaultEndpointSettings,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t};\n\t\treturn this.call(\n\t\t\t`updateProject(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProject(projectId, body);\n\t\t\t\treturn projectToSnapshot(res.data.project);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listBranches(projectId: string): Promise<NeonBranchSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranches(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst branches: Branch[] = [];\n\t\t\t\tlet cursor: string | undefined;\n\t\t\t\twhile (true) {\n\t\t\t\t\tconst res = await this.client.listProjectBranches({\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t\t...(cursor ? { cursor } : {}),\n\t\t\t\t\t});\n\t\t\t\t\tbranches.push(...(res.data.branches as Branch[]));\n\t\t\t\t\tconst next = (\n\t\t\t\t\t\tres.data as { pagination?: { next?: string } }\n\t\t\t\t\t).pagination?.next;\n\t\t\t\t\tif (!next || next === cursor) break;\n\t\t\t\t\tcursor = next;\n\t\t\t\t}\n\t\t\t\treturn branches.map(branchToSnapshot);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync createBranch(\n\t\tprojectId: string,\n\t\tinput: CreateBranchInput,\n\t): Promise<{\n\t\tbranch: NeonBranchSnapshot;\n\t\tendpoints: NeonEndpointSnapshot[];\n\t}> {\n\t\tconst endpointOptions: BranchCreateRequestEndpointOptions | undefined =\n\t\t\tinput.computeSettings\n\t\t\t\t? {\n\t\t\t\t\t\ttype: EndpointType.ReadWrite,\n\t\t\t\t\t\t...computeSettingsToEndpointOptions(\n\t\t\t\t\t\t\tinput.computeSettings,\n\t\t\t\t\t\t),\n\t\t\t\t\t}\n\t\t\t\t: { type: EndpointType.ReadWrite };\n\n\t\tconst body: BranchCreateRequest = {\n\t\t\tbranch: {\n\t\t\t\tname: input.name,\n\t\t\t\t...(input.parentId ? { parent_id: input.parentId } : {}),\n\t\t\t\t...(input.expiresAt ? { expires_at: input.expiresAt } : {}),\n\t\t\t\t...(input.protected !== undefined\n\t\t\t\t\t? { protected: input.protected }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\tendpoints: [endpointOptions],\n\t\t};\n\t\treturn this.call(\n\t\t\t`createBranch(${projectId}/${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.createProjectBranch(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbody,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tbranch: branchToSnapshot(res.data.branch),\n\t\t\t\t\tendpoints: (res.data.endpoints ?? []).map(\n\t\t\t\t\t\tendpointToSnapshot,\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync updateBranch(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: UpdateBranchInput,\n\t): Promise<NeonBranchSnapshot> {\n\t\tconst branch: BranchUpdateRequest[\"branch\"] = {};\n\t\tif (input.name !== undefined) branch.name = input.name;\n\t\tif (input.expiresAt !== undefined) branch.expires_at = input.expiresAt;\n\t\tif (input.protected !== undefined) branch.protected = input.protected;\n\t\treturn this.call(\n\t\t\t`updateBranch(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProjectBranch(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t\t{ branch },\n\t\t\t\t);\n\t\t\t\treturn branchToSnapshot(res.data.branch);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listEndpoints(projectId: string): Promise<NeonEndpointSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listEndpoints(${projectId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectEndpoints(projectId);\n\t\t\t\treturn (res.data.endpoints as Endpoint[]).map(\n\t\t\t\t\tendpointToSnapshot,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync updateEndpoint(\n\t\tprojectId: string,\n\t\tendpointId: string,\n\t\tsettings: ComputeSettings,\n\t): Promise<NeonEndpointSnapshot> {\n\t\tconst endpoint: EndpointUpdateRequest[\"endpoint\"] =\n\t\t\tcomputeSettingsToEndpointOptions(settings);\n\t\treturn this.call(\n\t\t\t`updateEndpoint(${projectId}/${endpointId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.updateProjectEndpoint(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tendpointId,\n\t\t\t\t\t{ endpoint },\n\t\t\t\t);\n\t\t\t\treturn endpointToSnapshot(res.data.endpoint);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync listBranchRoles(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonRoleSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranchRoles(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectBranchRoles(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t);\n\t\t\t\treturn (res.data.roles as Role[]).map(roleToSnapshot);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync listBranchDatabases(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonDatabaseSnapshot[]> {\n\t\treturn this.call(\n\t\t\t`listBranchDatabases(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.listProjectBranchDatabases(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t);\n\t\t\t\treturn (res.data.databases as Database[]).map(\n\t\t\t\t\tdatabaseToSnapshot,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync getConnectionUri(\n\t\tprojectId: string,\n\t\tinput: GetConnectionUriInput,\n\t): Promise<{ uri: string }> {\n\t\tconst op = `getConnectionUri(${projectId}/${input.databaseName}@${input.roleName}${input.pooled ? \" pooled\" : \"\"})`;\n\t\t// Always send `pooled` explicitly. The Neon API has switched its default\n\t\t// to returning the pooled URI when the parameter is omitted, so we have\n\t\t// to be explicit to get the direct URI back.\n\t\tconst pooled = input.pooled === true;\n\t\treturn this.call(\n\t\t\top,\n\t\t\tasync () => {\n\t\t\t\tconst res = await this.client.getConnectionUri({\n\t\t\t\t\tprojectId,\n\t\t\t\t\tdatabase_name: input.databaseName,\n\t\t\t\t\trole_name: input.roleName,\n\t\t\t\t\t...(input.branchId ? { branch_id: input.branchId } : {}),\n\t\t\t\t\t...(input.endpointId\n\t\t\t\t\t\t? { endpoint_id: input.endpointId }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\tpooled,\n\t\t\t\t});\n\t\t\t\treturn { uri: res.data.uri };\n\t\t\t},\n\t\t\t{ projectId },\n\t\t);\n\t}\n\n\tasync getNeonAuth(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonAuthSnapshot | null> {\n\t\t// `GET /projects/:pid/branches/:bid/auth` returns 404 when no integration exists.\n\t\t// Surface that as `null` so callers can branch cleanly instead of try/catch.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getNeonAuth(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.getNeonAuth(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t);\n\t\t\t\t\treturn neonAuthResponseToSnapshot(res.data);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (err instanceof PlatformError && err.code === ErrorCode.NotFound)\n\t\t\t\treturn null;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableNeonAuth(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: { databaseName?: string } = {},\n\t): Promise<NeonAuthSnapshot> {\n\t\t// Idempotent: if an integration already exists on the branch, the POST returns 409\n\t\t// (`Conflict`). We swallow that and re-fetch the existing snapshot so callers can\n\t\t// rely on `enableNeonAuth` to be safe to invoke from any push, including no-ops.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`enableNeonAuth(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\t// TODO: switch back to `this.client.createNeonAuth` once\n\t\t\t\t\t// @neondatabase/api-client narrows this branch endpoint to `better_auth`.\n\t\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\t\t`/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/auth`,\n\t\t\t\t\t\tcreateNeonAuthRestInput(input),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = neonAuthResponseSchema.parse(data);\n\t\t\t\t\treturn neonAuthResponseToSnapshot(parsed);\n\t\t\t\t},\n\t\t\t\t{ projectId, mutating: true },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\terr instanceof PlatformError &&\n\t\t\t\terr.code === ErrorCode.Conflict\n\t\t\t) {\n\t\t\t\tconst existing = await this.getNeonAuth(projectId, branchId);\n\t\t\t\tif (existing) return existing;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tprivate async postJson(path: string, body: unknown): Promise<unknown> {\n\t\treturn this.request(\"POST\", path, {\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(body),\n\t\t});\n\t}\n\n\tprivate async getJson(path: string): Promise<unknown> {\n\t\treturn this.request(\"GET\", path);\n\t}\n\n\tprivate async deleteJson(path: string): Promise<unknown> {\n\t\treturn this.request(\"DELETE\", path);\n\t}\n\n\t/**\n\t * Upload a built function bundle via `multipart/form-data` to the deploy endpoint.\n\t * Sends the bundle as the `file` field plus the deploy params Neon requires.\n\t */\n\tprivate async postMultipart(\n\t\tpath: string,\n\t\tinput: DeployFunctionInput,\n\t): Promise<unknown> {\n\t\tconst form = new FormData();\n\t\tform.set(\n\t\t\t\"file\",\n\t\t\tnew Blob([input.bundle as BlobPart], {\n\t\t\t\ttype: \"application/zip\",\n\t\t\t}),\n\t\t\t\"bundle.zip\",\n\t\t);\n\t\tform.set(\"memory_mib\", String(input.memoryMib));\n\t\t// Keep concurrency internal for now. The API requires it, but the public\n\t\t// neon.ts config surface intentionally does not expose it yet.\n\t\tform.set(\"concurrency\", \"1\");\n\t\tform.set(\"runtime\", input.runtime);\n\t\tfor (const [key, value] of Object.entries(input.environment)) {\n\t\t\tform.set(`environment[${key}]`, value);\n\t\t}\n\t\treturn this.request(\"POST\", path, { body: form });\n\t}\n\n\tprivate async request(\n\t\tmethod: \"GET\" | \"POST\" | \"DELETE\",\n\t\tpath: string,\n\t\tinit: { headers?: Record<string, string>; body?: BodyInit } = {},\n\t): Promise<unknown> {\n\t\tconst url = `${this.restConfig.baseUrl.replace(/\\/+$/, \"\")}${path}`;\n\t\tconst res = await fetch(url, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${this.restConfig.apiKey}`,\n\t\t\t\t...(init.headers ?? {}),\n\t\t\t},\n\t\t\t...(init.body !== undefined ? { body: init.body } : {}),\n\t\t});\n\t\tconst data = await readJsonBody(res);\n\t\tif (!res.ok) {\n\t\t\tthrow {\n\t\t\t\tresponse: {\n\t\t\t\t\tstatus: res.status,\n\t\t\t\t\tdata,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\treturn data;\n\t}\n\n\tasync getNeonDataApi(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tdatabaseName: string,\n\t): Promise<NeonDataApiSnapshot | null> {\n\t\t// Same shape as getNeonAuth — 404 means \"no integration on this branch/db\", which\n\t\t// we translate to `null` for the caller.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getNeonDataApi(${projectId}/${branchId}/${databaseName})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.getProjectBranchDataApi(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t\tdatabaseName,\n\t\t\t\t\t);\n\t\t\t\t\treturn { url: res.data.url };\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (err instanceof PlatformError && err.code === ErrorCode.NotFound)\n\t\t\t\treturn null;\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableProjectBranchDataApi(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tdatabaseName: string,\n\t): Promise<NeonDataApiSnapshot> {\n\t\t// Idempotent in the same shape as `enableNeonAuth`: if an integration already\n\t\t// exists, the POST returns 409 and we re-fetch the existing snapshot.\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`enableProjectBranchDataApi(${projectId}/${branchId}/${databaseName})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst res = await this.client.createProjectBranchDataApi(\n\t\t\t\t\t\tprojectId,\n\t\t\t\t\t\tbranchId,\n\t\t\t\t\t\tdatabaseName,\n\t\t\t\t\t\t// Empty body — pick up Neon defaults (auth_provider inferred from\n\t\t\t\t\t\t// whether Neon Auth is also enabled; default schemas/grants).\n\t\t\t\t\t\t{},\n\t\t\t\t\t);\n\t\t\t\t\treturn { url: res.data.url };\n\t\t\t\t},\n\t\t\t\t{ projectId, mutating: true },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\terr instanceof PlatformError &&\n\t\t\t\terr.code === ErrorCode.Conflict\n\t\t\t) {\n\t\t\t\tconst existing = await this.getNeonDataApi(\n\t\t\t\t\tprojectId,\n\t\t\t\t\tbranchId,\n\t\t\t\t\tdatabaseName,\n\t\t\t\t);\n\t\t\t\tif (existing) return existing;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\t// ─── Preview: buckets ──────────────────────────────────────────────────────\n\n\tasync listBranchBuckets(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonBucketSnapshot[]> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`listBranchBuckets(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"buckets\"),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = bucketsListResponseSchema.parse(data);\n\t\t\t\t\treturn parsed.buckets.map(bucketToSnapshot);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow previewUnavailableError(err, \"Object storage (buckets)\");\n\t\t}\n\t}\n\n\tasync createBranchBucket(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: CreateBucketInput,\n\t): Promise<NeonBucketSnapshot> {\n\t\treturn this.call(\n\t\t\t`createBranchBucket(${projectId}/${branchId}/${input.name})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"buckets\"),\n\t\t\t\t\t{\n\t\t\t\t\t\tname: input.name,\n\t\t\t\t\t\t...(input.accessLevel\n\t\t\t\t\t\t\t? { access_level: input.accessLevel }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconst parsed = bucketResponseSchema.parse(data);\n\t\t\t\treturn bucketToSnapshot(parsed.bucket);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deleteBranchBucket(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tbucketName: string,\n\t): Promise<void> {\n\t\tawait this.call(\n\t\t\t`deleteBranchBucket(${projectId}/${branchId}/${bucketName})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"buckets\")}/${encodeURIComponent(bucketName)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\t// ─── Preview: functions ────────────────────────────────────────────────────\n\n\tasync listBranchFunctions(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<NeonFunctionSnapshot[]> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`listBranchFunctions(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"functions\"),\n\t\t\t\t\t);\n\t\t\t\t\tconst parsed = functionsListResponseSchema.parse(data);\n\t\t\t\t\treturn parsed.functions.map(functionToSnapshot);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow previewUnavailableError(err, \"Functions\");\n\t\t}\n\t}\n\n\tasync createBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tinput: { slug: string; name: string },\n\t): Promise<NeonFunctionSnapshot> {\n\t\treturn this.call(\n\t\t\t`createBranchFunction(${projectId}/${branchId}/${input.slug})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postJson(\n\t\t\t\t\tbranchPreviewPath(projectId, branchId, \"functions\"),\n\t\t\t\t\t{ slug: input.slug, name: input.name },\n\t\t\t\t);\n\t\t\t\tconst parsed = functionResponseSchema.parse(data);\n\t\t\t\treturn functionToSnapshot(parsed.function);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deleteBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tslug: string,\n\t): Promise<void> {\n\t\tawait this.call(\n\t\t\t`deleteBranchFunction(${projectId}/${branchId}/${slug})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"functions\")}/${encodeURIComponent(slug)}`,\n\t\t\t\t);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync deployBranchFunction(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t\tslug: string,\n\t\tinput: DeployFunctionInput,\n\t): Promise<NeonFunctionDeploymentSnapshot> {\n\t\treturn this.call(\n\t\t\t`deployBranchFunction(${projectId}/${branchId}/${slug})`,\n\t\t\tasync () => {\n\t\t\t\tconst data = await this.postMultipart(\n\t\t\t\t\t`${branchPreviewPath(projectId, branchId, \"functions\")}/${encodeURIComponent(slug)}/deployments`,\n\t\t\t\t\tinput,\n\t\t\t\t);\n\t\t\t\tconst parsed = functionDeploymentResponseSchema.parse(data);\n\t\t\t\treturn deploymentToSnapshot(parsed.deployment);\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\t// ─── Preview: AI Gateway ───────────────────────────────────────────────────\n\t//\n\t// TODO(neon-deploy): the AI Gateway routes are not yet in the public API spec we wired\n\t// the rest of this adapter against. The paths below follow the established branch-scoped\n\t// convention (`/projects/{p}/branches/{b}/ai-gateway`); confirm them against the real\n\t// API (and the exact enable/disable verb + response shape) before relying on this in\n\t// production, and swap to the typed `@neondatabase/api-client` method once it exists.\n\n\tasync getAiGatewayEnabled(\n\t\tprojectId: string,\n\t\tbranchId: string,\n\t): Promise<boolean> {\n\t\ttry {\n\t\t\treturn await this.call(\n\t\t\t\t`getAiGatewayEnabled(${projectId}/${branchId})`,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst data = await this.getJson(\n\t\t\t\t\t\taiGatewayPath(projectId, branchId),\n\t\t\t\t\t);\n\t\t\t\t\treturn aiGatewayEnabledFromResponse(data);\n\t\t\t\t},\n\t\t\t\t{ projectId },\n\t\t\t);\n\t\t} catch (err) {\n\t\t\t// A \"feature unavailable\" signal (route not deployed / \"not available\")\n\t\t\t// is a hard error — surface it rather than reporting \"disabled\". A plain\n\t\t\t// NotFound *without* that signal means the route exists but AI Gateway is\n\t\t\t// simply not enabled on this branch, which is `false`.\n\t\t\tif (isPreviewFeatureUnavailable(err)) {\n\t\t\t\tthrow previewUnavailableError(err, \"AI Gateway\");\n\t\t\t}\n\t\t\tif (\n\t\t\t\terr instanceof PlatformError &&\n\t\t\t\terr.code === ErrorCode.NotFound\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync enableAiGateway(projectId: string, branchId: string): Promise<void> {\n\t\tawait this.call(\n\t\t\t`enableAiGateway(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.postJson(aiGatewayPath(projectId, branchId), {\n\t\t\t\t\tenabled: true,\n\t\t\t\t});\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n\n\tasync disableAiGateway(projectId: string, branchId: string): Promise<void> {\n\t\tawait this.call(\n\t\t\t`disableAiGateway(${projectId}/${branchId})`,\n\t\t\tasync () => {\n\t\t\t\tawait this.deleteJson(aiGatewayPath(projectId, branchId));\n\t\t\t},\n\t\t\t{ projectId, mutating: true },\n\t\t);\n\t}\n}\n\nfunction branchPreviewPath(\n\tprojectId: string,\n\tbranchId: string,\n\tresource: \"buckets\" | \"functions\",\n): string {\n\treturn `/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/${resource}`;\n}\n\nfunction aiGatewayPath(projectId: string, branchId: string): string {\n\treturn `/projects/${encodeURIComponent(projectId)}/branches/${encodeURIComponent(branchId)}/ai-gateway`;\n}\n\nfunction bucketToSnapshot(\n\tbucket: z.infer<typeof bucketSchema>,\n): NeonBucketSnapshot {\n\treturn {\n\t\tname: bucket.name,\n\t\taccessLevel: normalizeBucketAccessLevel(bucket.access_level),\n\t};\n}\n\n/**\n * The Neon API returns `access_level` as a free-form string (per the API guidelines:\n * responses use plain strings, not enums). Map the known values onto our union and treat\n * anything else as `private` — the safe default for an unrecognised access level.\n */\nfunction normalizeBucketAccessLevel(\n\tvalue: string | undefined,\n): BucketAccessLevel {\n\treturn value === \"public_read\" ? \"public_read\" : \"private\";\n}\n\nfunction functionToSnapshot(\n\tfn: z.infer<typeof neonFunctionSchema>,\n): NeonFunctionSnapshot {\n\tconst snapshot: NeonFunctionSnapshot = {\n\t\tid: fn.id,\n\t\tslug: fn.slug,\n\t\tname: fn.name,\n\t\tinvocationUrl: fn.invocation_url,\n\t};\n\tif (fn.active_deployment) {\n\t\tsnapshot.activeDeploymentId = fn.active_deployment.id;\n\t}\n\treturn snapshot;\n}\n\nfunction deploymentToSnapshot(\n\tdeployment: z.infer<typeof functionDeploymentSchema>,\n): NeonFunctionDeploymentSnapshot {\n\treturn {\n\t\tid: deployment.id,\n\t\tstatus: normalizeDeploymentStatus(deployment.status),\n\t};\n}\n\nfunction normalizeDeploymentStatus(\n\tvalue: string,\n): NeonFunctionDeploymentSnapshot[\"status\"] {\n\tswitch (value) {\n\t\tcase \"pending\":\n\t\tcase \"building\":\n\t\tcase \"completed\":\n\t\tcase \"failed\":\n\t\t\treturn value;\n\t\tdefault:\n\t\t\t// Unknown status from a newer server — surface as `pending` rather than throwing,\n\t\t\t// matching the API guideline that clients treat undocumented enum values leniently.\n\t\t\treturn \"pending\";\n\t}\n}\n\nfunction aiGatewayEnabledFromResponse(data: unknown): boolean {\n\tif (data !== null && typeof data === \"object\" && \"enabled\" in data) {\n\t\treturn (data as { enabled?: unknown }).enabled === true;\n\t}\n\treturn false;\n}\n\n/**\n * Whether an error from a Preview-feature read means the feature simply isn't available\n * for this project/branch/region (as opposed to a real, transient failure). Neon signals\n * this a few ways: a 404 \"this route does not exist\" (the route isn't deployed at all), or\n * a 503/4xx whose message says the platform feature is \"not available\" / \"not enabled\".\n *\n * Callers do **not** swallow this into an empty result — touching a Preview feature that\n * isn't available is surfaced as a {@link previewUnavailableError} so `plan` / `status` /\n * `pull` (and `neon dev`) fail clearly instead of, say, planning to create resources the\n * API will refuse to create.\n */\nexport function isPreviewFeatureUnavailable(err: unknown): boolean {\n\tif (!(err instanceof PlatformError)) return false;\n\tconst status = err.details.status;\n\tconst message =\n\t\ttypeof err.details.neonMessage === \"string\"\n\t\t\t? err.details.neonMessage.toLowerCase()\n\t\t\t: \"\";\n\tconst mentionsUnavailable =\n\t\tmessage.includes(\"not available\") ||\n\t\tmessage.includes(\"does not exist\") ||\n\t\tmessage.includes(\"not enabled\");\n\treturn (\n\t\tmentionsUnavailable &&\n\t\t(status === 503 || status === 404 || status === 501)\n\t);\n}\n\n/**\n * Convert a Preview-feature error into a clear {@link PlatformError} when the feature is\n * unavailable for the project; otherwise pass the original error through unchanged so a\n * genuine failure (auth, transient 5xx, …) keeps its specific code and message.\n */\nexport function previewUnavailableError(\n\terr: unknown,\n\tfeatureLabel: string,\n): unknown {\n\tif (!isPreviewFeatureUnavailable(err)) return err;\n\tconst neonMessage =\n\t\terr instanceof PlatformError &&\n\t\ttypeof err.details.neonMessage === \"string\"\n\t\t\t? ` (Neon API said: \"${err.details.neonMessage}\")`\n\t\t\t: \"\";\n\treturn new PlatformError(\n\t\tErrorCode.FeatureUnavailable,\n\t\t`${featureLabel} is a Preview feature that is not available for this project or region${neonMessage}. ` +\n\t\t\t\"Enable it for your Neon account/project first, then re-run.\",\n\t\t{ cause: err, details: { feature: featureLabel } },\n\t);\n}\n\nfunction neonAuthResponseToSnapshot(\n\tdata: z.infer<typeof neonAuthResponseSchema>,\n): NeonAuthSnapshot {\n\tconst snapshot: NeonAuthSnapshot = {\n\t\tprojectId: data.auth_provider_project_id,\n\t\tjwksUrl: data.jwks_url,\n\t};\n\tif (data.pub_client_key !== undefined) {\n\t\tsnapshot.publishableClientKey = data.pub_client_key;\n\t}\n\tif (data.secret_server_key !== undefined) {\n\t\tsnapshot.secretServerKey = data.secret_server_key;\n\t}\n\tif (data.base_url) snapshot.baseUrl = data.base_url;\n\treturn snapshot;\n}\n\nexport function createNeonAuthRestInput(input: {\n\tdatabaseName?: string;\n}): CreateNeonAuthRestInput {\n\treturn {\n\t\tauth_provider: \"better_auth\",\n\t\t...(input.databaseName ? { database_name: input.databaseName } : {}),\n\t};\n}\n\n/**\n * 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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"}
|
package/dist/lib/schema.d.ts
CHANGED
|
@@ -36,6 +36,10 @@ declare const functionConfigSchema: z.ZodObject<{
|
|
|
36
36
|
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
37
37
|
runtime: z.ZodOptional<z.ZodLiteral<"nodejs24">>;
|
|
38
38
|
memoryMib: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<256>, z.ZodLiteral<512>, z.ZodLiteral<1024>, z.ZodLiteral<2048>, z.ZodLiteral<4096>, z.ZodLiteral<8192>]>>;
|
|
39
|
+
dev: z.ZodOptional<z.ZodObject<{
|
|
40
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
portless: z.ZodOptional<z.ZodBoolean>;
|
|
42
|
+
}, z.core.$strict>>;
|
|
39
43
|
}, z.core.$strict>;
|
|
40
44
|
declare const bucketConfigSchema: z.ZodObject<{
|
|
41
45
|
name: z.ZodString;
|
|
@@ -49,6 +53,10 @@ declare const previewConfigSchema: z.ZodObject<{
|
|
|
49
53
|
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
50
54
|
runtime: z.ZodOptional<z.ZodLiteral<"nodejs24">>;
|
|
51
55
|
memoryMib: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<256>, z.ZodLiteral<512>, z.ZodLiteral<1024>, z.ZodLiteral<2048>, z.ZodLiteral<4096>, z.ZodLiteral<8192>]>>;
|
|
56
|
+
dev: z.ZodOptional<z.ZodObject<{
|
|
57
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
58
|
+
portless: z.ZodOptional<z.ZodBoolean>;
|
|
59
|
+
}, z.core.$strict>>;
|
|
52
60
|
}, z.core.$strict>>>;
|
|
53
61
|
buckets: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
54
62
|
name: z.ZodString;
|
|
@@ -83,6 +91,10 @@ declare const branchConfigSchema: z.ZodObject<{
|
|
|
83
91
|
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
84
92
|
runtime: z.ZodOptional<z.ZodLiteral<"nodejs24">>;
|
|
85
93
|
memoryMib: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<256>, z.ZodLiteral<512>, z.ZodLiteral<1024>, z.ZodLiteral<2048>, z.ZodLiteral<4096>, z.ZodLiteral<8192>]>>;
|
|
94
|
+
dev: z.ZodOptional<z.ZodObject<{
|
|
95
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
96
|
+
portless: z.ZodOptional<z.ZodBoolean>;
|
|
97
|
+
}, z.core.$strict>>;
|
|
86
98
|
}, z.core.$strict>>>;
|
|
87
99
|
buckets: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
88
100
|
name: z.ZodString;
|
package/dist/lib/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","names":[],"sources":["../../src/lib/schema.ts"],"mappings":";;;;;;AAgBA;;;;;;;;;;cAAa,uBAAqB,CAAA,CAAA;;;;;cAgDrB,qBAAmB,CAAA,CAAA;;;cAInB,sBAAoB,CAAA,CAAA;;;;;;iBApDC,CAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","names":[],"sources":["../../src/lib/schema.ts"],"mappings":";;;;;;AAgBA;;;;;;;;;;cAAa,uBAAqB,CAAA,CAAA;;;;;cAgDrB,qBAAmB,CAAA,CAAA;;;cAInB,sBAAoB,CAAA,CAAA;;;;;;iBApDC,CAAA;AAAA,cA2FrB,oBA3FqB,EA2FD,CAAA,CAAA,SA3FC,CAAA;EAgDrB,IAAA,aAAA;EAEX,IAAA,aAAA;;;;WAF8B,eAAA,WAAA,CAAA,SAAA,aAAA,CAAA,GAAA,CAAA,cAAA,CAAA,GAAA,CAAA,cAAA,CAAA,IAAA,CAAA,cAAA,CAAA,IAAA,CAAA,cAAA,CAAA,IAAA,CAAA,cAAA,CAAA,IAAA,CAAA,CAAA,CAAA,CAAA;EAAA,GAAA,eAAA,YAAA,CAAA;IAInB,IAAA,eAEX,YAAA,CAAA;IAAA,QAAA,eAAA,aAAA,CAAA;;;cAwDW,oBAAkB,CAAA,CAAA;;;;cAOlB,qBAAmB,CAAA,CAAA;;;;;;;;;;;;;;;;;;;mBAjEC,CAAA,CAAA;AAAA,CAAA,gBAAA,CAAA;AAuCpB,cA4EA,kBA3DX,EA2D6B,CAAA,CAAA,SA3D7B,CAAA;EAAA,MAAA,eAAA,YAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;QAjB+B,QAAA,eAAA,aAAA,CAAA;MAAA,CAAA,gBAAA,CAAA,CAAA;IAmBpB,CAAA,gBAKX,CAAA,CAAA,CAAA;IAAA,OAAA,eAAA,WAAA,YAAA,CAAA;;;;;;;mBAL6B,CAAA,CAAA;AAAA,CAAA,gBAAA,CAAA;AAOlB,cAiGA,YA5EV,EA4EsB,CAAA,CAAA,WA5EtB,CA4EsB,CAAA,CAAA,QA5EtB,CAAA,SAAA,CA4EsB,CAAA,CAAA,UA5EtB,CAAA,EAAA,IAAA,CAAA,EA4EsB,CAAA,CAAA,UA5EtB,CAAA;;;;;;;;;;iBA0Fa,eAAA,QAAuB,CAAA,CAAE"}
|
package/dist/lib/schema.js
CHANGED
|
@@ -55,15 +55,30 @@ const serviceToggleSchema = z.strictObject({ enabled: z.boolean().optional() });
|
|
|
55
55
|
const postgresConfigSchema = z.strictObject({ computeSettings: computeSettingsSchema.optional() });
|
|
56
56
|
/**
|
|
57
57
|
* Branch-unique function slug. Mirrors the Neon Functions API path-segment rule
|
|
58
|
-
* (`platform/internal/platform/functions/name.go`): lowercase
|
|
58
|
+
* (`platform/internal/platform/functions/name.go`): 1–20 lowercase letters and digits.
|
|
59
59
|
*/
|
|
60
|
-
const functionSlugSchema = z.string().regex(/^[a-z0-9]
|
|
60
|
+
const functionSlugSchema = z.string().regex(/^[a-z0-9]{1,20}$/, "function slug must be 1-20 lowercase letters and digits (no hyphens or other characters)");
|
|
61
61
|
/**
|
|
62
62
|
* Per-function environment map. Every value must be a defined string: a `process.env.X`
|
|
63
63
|
* that is unset surfaces as `undefined` and is rejected here (rather than silently
|
|
64
64
|
* shipping `undefined` into the deployment).
|
|
65
65
|
*/
|
|
66
66
|
const functionEnvSchema = z.record(z.string(), z.string());
|
|
67
|
+
/**
|
|
68
|
+
* TCP port for a function's local dev server. Excludes 0 (which means "any port" to the OS
|
|
69
|
+
* — `neon dev` expresses "pick one for me" by omitting `port`, not by passing 0).
|
|
70
|
+
*/
|
|
71
|
+
const devPortSchema = z.number().int().min(1).max(65535);
|
|
72
|
+
/**
|
|
73
|
+
* Local-dev settings for a function (`neon dev` only; never affects deploy). `port` and
|
|
74
|
+
* `portless` are independent: when `portless` is true, portless assigns the port itself
|
|
75
|
+
* (so `port` is ignored); otherwise `port` is bound exactly when set, or a free port is
|
|
76
|
+
* found when omitted.
|
|
77
|
+
*/
|
|
78
|
+
const functionDevConfigSchema = z.strictObject({
|
|
79
|
+
port: devPortSchema.optional(),
|
|
80
|
+
portless: z.boolean().optional()
|
|
81
|
+
});
|
|
67
82
|
const functionConfigSchema = z.strictObject({
|
|
68
83
|
slug: functionSlugSchema,
|
|
69
84
|
name: z.string().min(1).max(255),
|
|
@@ -77,7 +92,8 @@ const functionConfigSchema = z.strictObject({
|
|
|
77
92
|
z.literal(2048),
|
|
78
93
|
z.literal(4096),
|
|
79
94
|
z.literal(8192)
|
|
80
|
-
]).optional()
|
|
95
|
+
]).optional(),
|
|
96
|
+
dev: functionDevConfigSchema.optional()
|
|
81
97
|
});
|
|
82
98
|
const bucketConfigSchema = z.strictObject({
|
|
83
99
|
name: z.string().min(1).max(255),
|
package/dist/lib/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","names":[],"sources":["../../src/lib/schema.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { parseDuration, parseSuspendTimeout } from \"./duration.js\";\nimport { isWildcardPattern, validatePattern } from \"./patterns.js\";\n\n/**\n * Zod schema for {@link import(\"./types.js\").ComputeSettings}.\n *\n * - CU values must be one of: 0.25, 0.5, 1, 2, 4, 8\n * - `suspendTimeout` can be:\n * - `false` (never suspend)\n * - duration string like \"5m\", \"1h\" (must be 60s-604800s when parsed)\n * - number in seconds (60-604800, or -1/0 for special values)\n * - `undefined` (use platform default)\n *\n * Cross-field invariants (min <= max) are enforced via `superRefine`.\n */\nexport const computeSettingsSchema = z\n\t.strictObject({\n\t\tautoscalingLimitMinCu: z\n\t\t\t.union([\n\t\t\t\tz.literal(0.25),\n\t\t\t\tz.literal(0.5),\n\t\t\t\tz.literal(1),\n\t\t\t\tz.literal(2),\n\t\t\t\tz.literal(4),\n\t\t\t\tz.literal(8),\n\t\t\t])\n\t\t\t.optional(),\n\t\tautoscalingLimitMaxCu: z\n\t\t\t.union([\n\t\t\t\tz.literal(0.25),\n\t\t\t\tz.literal(0.5),\n\t\t\t\tz.literal(1),\n\t\t\t\tz.literal(2),\n\t\t\t\tz.literal(4),\n\t\t\t\tz.literal(8),\n\t\t\t])\n\t\t\t.optional(),\n\t\tsuspendTimeout: z\n\t\t\t.union([z.literal(false), z.string(), z.number()])\n\t\t\t.optional()\n\t\t\t.superRefine((value, ctx) => {\n\t\t\t\tif (value === undefined) return; // undefined is valid (use platform default)\n\t\t\t\tconst result = parseSuspendTimeout(value);\n\t\t\t\tif (\"error\" in result) {\n\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\tcode: \"custom\",\n\t\t\t\t\t\tmessage: result.error,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}),\n\t})\n\t.superRefine((settings, ctx) => {\n\t\tconst { autoscalingLimitMinCu: min, autoscalingLimitMaxCu: max } =\n\t\t\tsettings;\n\t\tif (min !== undefined && max !== undefined && min > max) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tpath: [\"autoscalingLimitMinCu\"],\n\t\t\t\tmessage: `autoscalingLimitMinCu (${min}) must be <= autoscalingLimitMaxCu (${max})`,\n\t\t\t});\n\t\t}\n\t});\n\nexport const serviceToggleSchema = z.strictObject({\n\tenabled: z.boolean().optional(),\n});\n\nexport const postgresConfigSchema = z.strictObject({\n\tcomputeSettings: computeSettingsSchema.optional(),\n});\n\n/**\n * Branch-unique function slug. Mirrors the Neon Functions API path-segment rule\n * (`platform/internal/platform/functions/name.go`): lowercase DNS label, 1–40 chars.\n */\nconst functionSlugSchema = z\n\t.string()\n\t.regex(\n\t\t/^[a-z0-9]([a-z0-9-]{0,38}[a-z0-9])?$/,\n\t\t\"function slug must be a lowercase DNS label (1-40 chars, letters/digits/hyphens, no leading/trailing hyphen)\",\n\t);\n\n/**\n * Per-function environment map. Every value must be a defined string: a `process.env.X`\n * that is unset surfaces as `undefined` and is rejected here (rather than silently\n * shipping `undefined` into the deployment).\n */\nconst functionEnvSchema = z.record(z.string(), z.string());\n\nexport const functionConfigSchema = z.strictObject({\n\tslug: functionSlugSchema,\n\tname: z.string().min(1).max(255),\n\tsource: z.string().min(1),\n\tenv: functionEnvSchema.optional(),\n\truntime: z.literal(\"nodejs24\").optional(),\n\tmemoryMib: z\n\t\t.union([\n\t\t\tz.literal(256),\n\t\t\tz.literal(512),\n\t\t\tz.literal(1024),\n\t\t\tz.literal(2048),\n\t\t\tz.literal(4096),\n\t\t\tz.literal(8192),\n\t\t])\n\t\t.optional(),\n});\n\nexport const bucketConfigSchema = z.strictObject({\n\tname: z.string().min(1).max(255),\n\taccess: z\n\t\t.union([z.literal(\"private\"), z.literal(\"public_read\")])\n\t\t.optional(),\n});\n\nexport const previewConfigSchema = z\n\t.strictObject({\n\t\tfunctions: z.array(functionConfigSchema).optional(),\n\t\tbuckets: z.array(bucketConfigSchema).optional(),\n\t\taiGateway: serviceToggleSchema.optional(),\n\t})\n\t.superRefine((preview, ctx) => {\n\t\tassertUnique({\n\t\t\tctx,\n\t\t\tpath: [\"functions\"],\n\t\t\titems: preview.functions ?? [],\n\t\t\tkey: (fn) => fn.slug,\n\t\t\tlabel: \"function slug\",\n\t\t});\n\t\tassertUnique({\n\t\t\tctx,\n\t\t\tpath: [\"buckets\"],\n\t\t\titems: preview.buckets ?? [],\n\t\t\tkey: (bucket) => bucket.name,\n\t\t\tlabel: \"bucket name\",\n\t\t});\n\t});\n\n/**\n * Flag duplicate keys within a Preview collection so a typo in two function slugs (or two\n * buckets) surfaces as a config error rather than the second silently clobbering the first\n * at apply time.\n */\nfunction assertUnique<T>(args: {\n\tctx: z.RefinementCtx;\n\tpath: (string | number)[];\n\titems: T[];\n\tkey: (item: T) => string;\n\tlabel: string;\n}): void {\n\tconst { ctx, path, items, key, label } = args;\n\tconst seen = new Set<string>();\n\titems.forEach((item, index) => {\n\t\tconst value = key(item);\n\t\tif (seen.has(value)) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tpath: [...path, index],\n\t\t\t\tmessage: `duplicate ${label}: ${JSON.stringify(value)}`,\n\t\t\t});\n\t\t}\n\t\tseen.add(value);\n\t});\n}\n\nexport const branchConfigSchema = z\n\t.strictObject({\n\t\tparent: z.string().optional(),\n\t\tprotected: z.boolean().optional(),\n\t\tttl: z\n\t\t\t.union([z.string(), z.number()])\n\t\t\t.optional()\n\t\t\t.superRefine((value, ctx) => {\n\t\t\t\tif (value === undefined) return;\n\t\t\t\tconst result = parseDuration(value);\n\t\t\t\tif (\"error\" in result) {\n\t\t\t\t\tctx.addIssue({ code: \"custom\", message: result.error });\n\t\t\t\t}\n\t\t\t}),\n\t\tpostgres: postgresConfigSchema.optional(),\n\t\tauth: serviceToggleSchema.optional(),\n\t\tdataApi: serviceToggleSchema.optional(),\n\t\tpreview: previewConfigSchema.optional(),\n\t})\n\t.superRefine((cfg, ctx) => {\n\t\tvalidateParentReference({\n\t\t\tctx,\n\t\t\tpath: [\"parent\"],\n\t\t\tparent: cfg.parent,\n\t\t});\n\t});\n\nfunction validateParentReference(args: {\n\tctx: z.RefinementCtx;\n\tpath: (string | number)[];\n\tparent: string | undefined;\n}): void {\n\tconst { ctx, path, parent } = args;\n\tif (parent === undefined) return;\n\n\tconst patternCheck = validatePattern(parent);\n\tif (\"error\" in patternCheck) {\n\t\tctx.addIssue({ code: \"custom\", path, message: patternCheck.error });\n\t} else if (isWildcardPattern(parent)) {\n\t\tctx.addIssue({\n\t\t\tcode: \"custom\",\n\t\t\tpath,\n\t\t\tmessage: `parent must be a concrete branch name (no wildcards), got \"${parent}\"`,\n\t\t});\n\t}\n}\n\nexport const configSchema = z.function({\n\tinput: [z.unknown()],\n\toutput: z.unknown(),\n});\n\n/**\n * Convert the structured {@link z.ZodError} produced by `configSchema.safeParse` into the\n * `string[]` shape used by {@link import(\"./errors.js\").ConfigValidationError}.\n *\n * Issue paths are rendered as dot-separated property accesses (`postgres.computeSettings`)\n * and unknown-key issues from `strictObject` are normalised so the message contains the\n * substring \"unknown key\" — keeping pre-zod assertions in test suites and downstream tools\n * stable.\n */\nexport function formatZodIssues(error: z.ZodError): string[] {\n\treturn error.issues.map((issue) => {\n\t\tconst path = renderPath(issue.path);\n\t\tconst message = normaliseIssueMessage(issue);\n\t\treturn path ? `${path}: ${message}` : message;\n\t});\n}\n\nfunction renderPath(path: ReadonlyArray<PropertyKey>): string {\n\tlet out = \"\";\n\tfor (const segment of path) {\n\t\tif (typeof segment === \"number\") out += `[${segment}]`;\n\t\telse if (out === \"\") out += String(segment);\n\t\telse out += `.${String(segment)}`;\n\t}\n\treturn out;\n}\n\nfunction normaliseIssueMessage(issue: z.core.$ZodIssue): string {\n\tif (issue.code === \"unrecognized_keys\") {\n\t\tconst keys = (issue as z.core.$ZodIssueUnrecognizedKeys).keys ?? [];\n\t\tconst formatted = keys.map((k) => JSON.stringify(k)).join(\", \");\n\t\treturn `unknown key${keys.length === 1 ? \"\" : \"s\"}: ${formatted}`;\n\t}\n\treturn issue.message;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema.js","names":[],"sources":["../../src/lib/schema.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { parseDuration, parseSuspendTimeout } from \"./duration.js\";\nimport { isWildcardPattern, validatePattern } from \"./patterns.js\";\n\n/**\n * Zod schema for {@link import(\"./types.js\").ComputeSettings}.\n *\n * - CU values must be one of: 0.25, 0.5, 1, 2, 4, 8\n * - `suspendTimeout` can be:\n * - `false` (never suspend)\n * - duration string like \"5m\", \"1h\" (must be 60s-604800s when parsed)\n * - number in seconds (60-604800, or -1/0 for special values)\n * - `undefined` (use platform default)\n *\n * Cross-field invariants (min <= max) are enforced via `superRefine`.\n */\nexport const computeSettingsSchema = z\n\t.strictObject({\n\t\tautoscalingLimitMinCu: z\n\t\t\t.union([\n\t\t\t\tz.literal(0.25),\n\t\t\t\tz.literal(0.5),\n\t\t\t\tz.literal(1),\n\t\t\t\tz.literal(2),\n\t\t\t\tz.literal(4),\n\t\t\t\tz.literal(8),\n\t\t\t])\n\t\t\t.optional(),\n\t\tautoscalingLimitMaxCu: z\n\t\t\t.union([\n\t\t\t\tz.literal(0.25),\n\t\t\t\tz.literal(0.5),\n\t\t\t\tz.literal(1),\n\t\t\t\tz.literal(2),\n\t\t\t\tz.literal(4),\n\t\t\t\tz.literal(8),\n\t\t\t])\n\t\t\t.optional(),\n\t\tsuspendTimeout: z\n\t\t\t.union([z.literal(false), z.string(), z.number()])\n\t\t\t.optional()\n\t\t\t.superRefine((value, ctx) => {\n\t\t\t\tif (value === undefined) return; // undefined is valid (use platform default)\n\t\t\t\tconst result = parseSuspendTimeout(value);\n\t\t\t\tif (\"error\" in result) {\n\t\t\t\t\tctx.addIssue({\n\t\t\t\t\t\tcode: \"custom\",\n\t\t\t\t\t\tmessage: result.error,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}),\n\t})\n\t.superRefine((settings, ctx) => {\n\t\tconst { autoscalingLimitMinCu: min, autoscalingLimitMaxCu: max } =\n\t\t\tsettings;\n\t\tif (min !== undefined && max !== undefined && min > max) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tpath: [\"autoscalingLimitMinCu\"],\n\t\t\t\tmessage: `autoscalingLimitMinCu (${min}) must be <= autoscalingLimitMaxCu (${max})`,\n\t\t\t});\n\t\t}\n\t});\n\nexport const serviceToggleSchema = z.strictObject({\n\tenabled: z.boolean().optional(),\n});\n\nexport const postgresConfigSchema = z.strictObject({\n\tcomputeSettings: computeSettingsSchema.optional(),\n});\n\n/**\n * Branch-unique function slug. Mirrors the Neon Functions API path-segment rule\n * (`platform/internal/platform/functions/name.go`): 1–20 lowercase letters and digits.\n */\nconst functionSlugSchema = z\n\t.string()\n\t.regex(\n\t\t/^[a-z0-9]{1,20}$/,\n\t\t\"function slug must be 1-20 lowercase letters and digits (no hyphens or other characters)\",\n\t);\n\n/**\n * Per-function environment map. Every value must be a defined string: a `process.env.X`\n * that is unset surfaces as `undefined` and is rejected here (rather than silently\n * shipping `undefined` into the deployment).\n */\nconst functionEnvSchema = z.record(z.string(), z.string());\n\n/**\n * TCP port for a function's local dev server. Excludes 0 (which means \"any port\" to the OS\n * — `neon dev` expresses \"pick one for me\" by omitting `port`, not by passing 0).\n */\nconst devPortSchema = z.number().int().min(1).max(65535);\n\n/**\n * Local-dev settings for a function (`neon dev` only; never affects deploy). `port` and\n * `portless` are independent: when `portless` is true, portless assigns the port itself\n * (so `port` is ignored); otherwise `port` is bound exactly when set, or a free port is\n * found when omitted.\n */\nconst functionDevConfigSchema = z.strictObject({\n\tport: devPortSchema.optional(),\n\tportless: z.boolean().optional(),\n});\n\nexport const functionConfigSchema = z.strictObject({\n\tslug: functionSlugSchema,\n\tname: z.string().min(1).max(255),\n\tsource: z.string().min(1),\n\tenv: functionEnvSchema.optional(),\n\truntime: z.literal(\"nodejs24\").optional(),\n\tmemoryMib: z\n\t\t.union([\n\t\t\tz.literal(256),\n\t\t\tz.literal(512),\n\t\t\tz.literal(1024),\n\t\t\tz.literal(2048),\n\t\t\tz.literal(4096),\n\t\t\tz.literal(8192),\n\t\t])\n\t\t.optional(),\n\tdev: functionDevConfigSchema.optional(),\n});\n\nexport const bucketConfigSchema = z.strictObject({\n\tname: z.string().min(1).max(255),\n\taccess: z\n\t\t.union([z.literal(\"private\"), z.literal(\"public_read\")])\n\t\t.optional(),\n});\n\nexport const previewConfigSchema = z\n\t.strictObject({\n\t\tfunctions: z.array(functionConfigSchema).optional(),\n\t\tbuckets: z.array(bucketConfigSchema).optional(),\n\t\taiGateway: serviceToggleSchema.optional(),\n\t})\n\t.superRefine((preview, ctx) => {\n\t\tassertUnique({\n\t\t\tctx,\n\t\t\tpath: [\"functions\"],\n\t\t\titems: preview.functions ?? [],\n\t\t\tkey: (fn) => fn.slug,\n\t\t\tlabel: \"function slug\",\n\t\t});\n\t\tassertUnique({\n\t\t\tctx,\n\t\t\tpath: [\"buckets\"],\n\t\t\titems: preview.buckets ?? [],\n\t\t\tkey: (bucket) => bucket.name,\n\t\t\tlabel: \"bucket name\",\n\t\t});\n\t});\n\n/**\n * Flag duplicate keys within a Preview collection so a typo in two function slugs (or two\n * buckets) surfaces as a config error rather than the second silently clobbering the first\n * at apply time.\n */\nfunction assertUnique<T>(args: {\n\tctx: z.RefinementCtx;\n\tpath: (string | number)[];\n\titems: T[];\n\tkey: (item: T) => string;\n\tlabel: string;\n}): void {\n\tconst { ctx, path, items, key, label } = args;\n\tconst seen = new Set<string>();\n\titems.forEach((item, index) => {\n\t\tconst value = key(item);\n\t\tif (seen.has(value)) {\n\t\t\tctx.addIssue({\n\t\t\t\tcode: \"custom\",\n\t\t\t\tpath: [...path, index],\n\t\t\t\tmessage: `duplicate ${label}: ${JSON.stringify(value)}`,\n\t\t\t});\n\t\t}\n\t\tseen.add(value);\n\t});\n}\n\nexport const branchConfigSchema = z\n\t.strictObject({\n\t\tparent: z.string().optional(),\n\t\tprotected: z.boolean().optional(),\n\t\tttl: z\n\t\t\t.union([z.string(), z.number()])\n\t\t\t.optional()\n\t\t\t.superRefine((value, ctx) => {\n\t\t\t\tif (value === undefined) return;\n\t\t\t\tconst result = parseDuration(value);\n\t\t\t\tif (\"error\" in result) {\n\t\t\t\t\tctx.addIssue({ code: \"custom\", message: result.error });\n\t\t\t\t}\n\t\t\t}),\n\t\tpostgres: postgresConfigSchema.optional(),\n\t\tauth: serviceToggleSchema.optional(),\n\t\tdataApi: serviceToggleSchema.optional(),\n\t\tpreview: previewConfigSchema.optional(),\n\t})\n\t.superRefine((cfg, ctx) => {\n\t\tvalidateParentReference({\n\t\t\tctx,\n\t\t\tpath: [\"parent\"],\n\t\t\tparent: cfg.parent,\n\t\t});\n\t});\n\nfunction validateParentReference(args: {\n\tctx: z.RefinementCtx;\n\tpath: (string | number)[];\n\tparent: string | undefined;\n}): void {\n\tconst { ctx, path, parent } = args;\n\tif (parent === undefined) return;\n\n\tconst patternCheck = validatePattern(parent);\n\tif (\"error\" in patternCheck) {\n\t\tctx.addIssue({ code: \"custom\", path, message: patternCheck.error });\n\t} else if (isWildcardPattern(parent)) {\n\t\tctx.addIssue({\n\t\t\tcode: \"custom\",\n\t\t\tpath,\n\t\t\tmessage: `parent must be a concrete branch name (no wildcards), got \"${parent}\"`,\n\t\t});\n\t}\n}\n\nexport const configSchema = z.function({\n\tinput: [z.unknown()],\n\toutput: z.unknown(),\n});\n\n/**\n * Convert the structured {@link z.ZodError} produced by `configSchema.safeParse` into the\n * `string[]` shape used by {@link import(\"./errors.js\").ConfigValidationError}.\n *\n * Issue paths are rendered as dot-separated property accesses (`postgres.computeSettings`)\n * and unknown-key issues from `strictObject` are normalised so the message contains the\n * substring \"unknown key\" — keeping pre-zod assertions in test suites and downstream tools\n * stable.\n */\nexport function formatZodIssues(error: z.ZodError): string[] {\n\treturn error.issues.map((issue) => {\n\t\tconst path = renderPath(issue.path);\n\t\tconst message = normaliseIssueMessage(issue);\n\t\treturn path ? `${path}: ${message}` : message;\n\t});\n}\n\nfunction renderPath(path: ReadonlyArray<PropertyKey>): string {\n\tlet out = \"\";\n\tfor (const segment of path) {\n\t\tif (typeof segment === \"number\") out += `[${segment}]`;\n\t\telse if (out === \"\") out += String(segment);\n\t\telse out += `.${String(segment)}`;\n\t}\n\treturn out;\n}\n\nfunction normaliseIssueMessage(issue: z.core.$ZodIssue): string {\n\tif (issue.code === \"unrecognized_keys\") {\n\t\tconst keys = (issue as z.core.$ZodIssueUnrecognizedKeys).keys ?? [];\n\t\tconst formatted = keys.map((k) => JSON.stringify(k)).join(\", \");\n\t\treturn `unknown key${keys.length === 1 ? \"\" : \"s\"}: ${formatted}`;\n\t}\n\treturn issue.message;\n}\n"],"mappings":"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"}
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -79,6 +79,30 @@ type FunctionRuntime = "nodejs24";
|
|
|
79
79
|
* `memory_mib` enum in the spec.
|
|
80
80
|
*/
|
|
81
81
|
type FunctionMemoryMib = 256 | 512 | 1024 | 2048 | 4096 | 8192;
|
|
82
|
+
/**
|
|
83
|
+
* Local-development settings for a function, used by `neon dev` when it serves every
|
|
84
|
+
* function declared in `neon.ts` (i.e. invoked with no `--source`). Never affects deploy.
|
|
85
|
+
*
|
|
86
|
+
* `port` and `portless` are independent:
|
|
87
|
+
*
|
|
88
|
+
* - `portless: true` — wrap this function's local server with `portless <slug> …` so it gets
|
|
89
|
+
* a stable `slug.localhost` URL. Portless assigns the port itself (it injects `PORT`), so
|
|
90
|
+
* `port` is ignored in this mode.
|
|
91
|
+
* - otherwise — serve directly. `port`, when set, is bound exactly (and `neon dev` fails
|
|
92
|
+
* loudly if it is taken); when omitted a free port is found automatically.
|
|
93
|
+
*/
|
|
94
|
+
interface FunctionDevConfig {
|
|
95
|
+
/**
|
|
96
|
+
* Port the local server binds. Bound exactly (fails if taken) when set; a free port is
|
|
97
|
+
* found when omitted. Ignored when `portless` is true (portless assigns the port).
|
|
98
|
+
*/
|
|
99
|
+
port?: number;
|
|
100
|
+
/**
|
|
101
|
+
* Expose this function via `portless` (a stable `slug.localhost` URL). Requires the
|
|
102
|
+
* `portless` binary on PATH. Portless assigns the port, so `port` is ignored here.
|
|
103
|
+
*/
|
|
104
|
+
portless?: boolean;
|
|
105
|
+
}
|
|
82
106
|
/**
|
|
83
107
|
* A single Neon Function deployed to a branch (Preview feature).
|
|
84
108
|
*
|
|
@@ -89,9 +113,9 @@ type FunctionMemoryMib = 256 | 512 | 1024 | 2048 | 4096 | 8192;
|
|
|
89
113
|
*/
|
|
90
114
|
interface FunctionConfig {
|
|
91
115
|
/**
|
|
92
|
-
* Branch-unique
|
|
93
|
-
*
|
|
94
|
-
* @example "
|
|
116
|
+
* Branch-unique slug used as the path segment in the function's invocation URL.
|
|
117
|
+
* Immutable once created. 1–20 lowercase letters and digits: `^[a-z0-9]{1,20}$`.
|
|
118
|
+
* @example "hellofn"
|
|
95
119
|
*/
|
|
96
120
|
slug: string;
|
|
97
121
|
/** Free-form display name. @example "Hello World" */
|
|
@@ -118,6 +142,11 @@ interface FunctionConfig {
|
|
|
118
142
|
runtime?: FunctionRuntime;
|
|
119
143
|
/** Memory allotted to each invocation, in MiB. Defaults to `512`. */
|
|
120
144
|
memoryMib?: FunctionMemoryMib;
|
|
145
|
+
/**
|
|
146
|
+
* Local-development settings used by `neon dev` when serving every function from
|
|
147
|
+
* `neon.ts`. Ignored at deploy time. See {@link FunctionDevConfig}.
|
|
148
|
+
*/
|
|
149
|
+
dev?: FunctionDevConfig;
|
|
121
150
|
}
|
|
122
151
|
/** Anonymous-access level for a branchable object-storage bucket. */
|
|
123
152
|
type BucketAccessLevel = "private" | "public_read";
|
|
@@ -185,6 +214,11 @@ interface ResolvedFunctionConfig {
|
|
|
185
214
|
env: Record<string, string>;
|
|
186
215
|
runtime: FunctionRuntime;
|
|
187
216
|
memoryMib: FunctionMemoryMib;
|
|
217
|
+
/**
|
|
218
|
+
* Local-development settings, passed through untouched from {@link FunctionConfig.dev}
|
|
219
|
+
* (no defaults applied). Only consumed by `neon dev`; deploy ignores it.
|
|
220
|
+
*/
|
|
221
|
+
dev?: FunctionDevConfig;
|
|
188
222
|
}
|
|
189
223
|
/** A bucket with its access level defaulted to `private`. */
|
|
190
224
|
interface ResolvedBucketConfig {
|
|
@@ -255,5 +289,5 @@ interface PushResult {
|
|
|
255
289
|
conflicts: ConflictReport[];
|
|
256
290
|
}
|
|
257
291
|
//#endregion
|
|
258
|
-
export { AppliedChange, BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, ComputeUnit, Config, ConflictReport, FunctionConfig, FunctionMemoryMib, FunctionRuntime, PostgresConfig, PreviewConfig, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle };
|
|
292
|
+
export { AppliedChange, BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, ComputeUnit, Config, ConflictReport, FunctionConfig, FunctionDevConfig, FunctionMemoryMib, FunctionRuntime, PostgresConfig, PreviewConfig, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle };
|
|
259
293
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/lib/types.ts"],"mappings":";;AAIA;AASA;;AAMyB,KAfb,WAAA,GAea,IAAA,GAAA,GAAA,GAAA,CAAA,GAAA,CAAA,GAAA,CAAA,GAAA,CAAA;;AAMW;AAuBpC;AAiBA;AAKA;AASA;AAMA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/lib/types.ts"],"mappings":";;AAIA;AASA;;AAMyB,KAfb,WAAA,GAea,IAAA,GAAA,GAAA,GAAA,CAAA,GAAA,CAAA,GAAA,CAAA,GAAA,CAAA;;AAMW;AAuBpC;AAiBA;AAKA;AASA;AAMA;AAciB,UAtFA,eAAA,CAsFiB;EAqBjB;;;;;uBAmCV,CAAA,EAxIkB,WAwIlB;EAAiB;AAIxB;AAKA;AAcA;;uBAEa,CAAA,EA3JY,WA2JZ;;;AAIa;AACzB;;;;AAcuB;AAAA;;;;;gBAOW,CAAA,EAAA,KAAA,GAAA,IAAA,GAAA,IAAA,GAAA,MAAA,GAAA,MAAA;AAAa;AAEhD;;;;AAAiE;AAEjE;AAAkB,UAlKD,YAAA,CAkKC;;MAA6B,EAAA,MAAA;EAAY;EAM1C,EAAA,CAAA,EAAA,MAAA;EAAsB;QAIjC,EAAA,OAAA;;UAEM,CAAA,EAAA,MAAA;;EAKY,SAAA,CAAA,EAAA,OAAA;EAIP;EAUA,WAAA,CAAA,EAAA,OAAA;EAAqB;WAC1B,CAAA,EAAA,MAAA;;AACkB,UAlLb,aAAA,CAkLa;EAIb;EAAoB,OAAA,CAAA,EAAA,OAAA;;AAO1B,UAxLM,cAAA,CAwLN;EAAqB,eAAA,CAAA,EAvLb,eAuLa;AAMhC;AAkBA;AAYA;;;;AAW0B,KA9Nd,eAAA,GA8Nc,UAAA;;;;;KAxNd,iBAAA;;;;;;;;;;;;;UAcK,iBAAA;;;;;;;;;;;;;;;;;;;;UAqBA,cAAA;;;;;;;;;;;;;;;;;;;;;;;;;;QA0BV;;YAEI;;cAEE;;;;;QAKN;;;KAIK,iBAAA;;;;UAKK,YAAA;;;;;;;WAOP;;;;;;UAOO,aAAA;;cAEJ;;YAEF;;cAEE;;UAGH,gBAAA;;;;;;;aAOE;;;;;YAKD;;KAGN,mBAAA;;;;QAEM;;;;WACiB;;QACjB;WAAwB;;KAEvB,YAAA,GAAe,mBAAmB;KAElC,MAAA,YAAkB,iBAAiB;;;;;UAM9B,sBAAA;;;;OAIX;WACI;aACE;;;;;QAKL;;;UAIU,oBAAA;;UAER;;;;;;;UAQQ,qBAAA;aACL;WACF;;;UAIO,oBAAA;;;;aAIL;;;YAGD;;;;;UAMM,aAAA;;;;;;;;YAQN;;;;;;;;;UAUM,cAAA;;;;;;;;;;;UAYA,UAAA;;;;;;;;;;WAUP;aACE"}
|
package/dist/v1.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppliedChange, BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, Config, ConflictReport, FunctionConfig, FunctionMemoryMib, FunctionRuntime, PostgresConfig, PreviewConfig, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle } from "./lib/types.js";
|
|
1
|
+
import { AppliedChange, BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, Config, ConflictReport, FunctionConfig, FunctionDevConfig, FunctionMemoryMib, FunctionRuntime, PostgresConfig, PreviewConfig, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle } from "./lib/types.js";
|
|
2
2
|
import { ConfigLoadError, ConfigValidationError, ErrorCode, MissingContextError, PlatformError, PushAbortedError, PushConflictError } from "./lib/errors.js";
|
|
3
3
|
import { CreateBranchInput, CreateBucketInput, CreateProjectInput, DeployFunctionInput, GetConnectionUriInput, NeonApi, NeonAuthSnapshot, NeonBranchSnapshot, NeonBucketSnapshot, NeonDataApiSnapshot, NeonDatabaseSnapshot, NeonEndpointSnapshot, NeonFunctionDeploymentSnapshot, NeonFunctionSnapshot, NeonProjectSnapshot, NeonRoleSnapshot, UpdateBranchInput } from "./lib/neon-api.js";
|
|
4
4
|
import { createNeonApiFromOptions, resolveApiKey } from "./lib/auth.js";
|
|
@@ -28,6 +28,7 @@ declare const errors: {
|
|
|
28
28
|
readonly MissingApiKey: "PLATFORM_MISSING_API_KEY";
|
|
29
29
|
readonly AmbiguousBranchAuth: "PLATFORM_AMBIGUOUS_BRANCH_AUTH";
|
|
30
30
|
readonly BranchNotFound: "PLATFORM_BRANCH_NOT_FOUND";
|
|
31
|
+
readonly FeatureUnavailable: "PLATFORM_FEATURE_UNAVAILABLE";
|
|
31
32
|
readonly MissingParentBranch: "PLATFORM_MISSING_PARENT_BRANCH";
|
|
32
33
|
readonly Unauthorized: "PLATFORM_UNAUTHORIZED";
|
|
33
34
|
readonly Forbidden: "PLATFORM_FORBIDDEN";
|
|
@@ -71,6 +72,10 @@ declare const schemas: {
|
|
|
71
72
|
env: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodString>>;
|
|
72
73
|
runtime: zod0.ZodOptional<zod0.ZodLiteral<"nodejs24">>;
|
|
73
74
|
memoryMib: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<256>, zod0.ZodLiteral<512>, zod0.ZodLiteral<1024>, zod0.ZodLiteral<2048>, zod0.ZodLiteral<4096>, zod0.ZodLiteral<8192>]>>;
|
|
75
|
+
dev: zod0.ZodOptional<zod0.ZodObject<{
|
|
76
|
+
port: zod0.ZodOptional<zod0.ZodNumber>;
|
|
77
|
+
portless: zod0.ZodOptional<zod0.ZodBoolean>;
|
|
78
|
+
}, zod_v4_core0.$strict>>;
|
|
74
79
|
}, zod_v4_core0.$strict>>>;
|
|
75
80
|
buckets: zod0.ZodOptional<zod0.ZodArray<zod0.ZodObject<{
|
|
76
81
|
name: zod0.ZodString;
|
|
@@ -98,6 +103,10 @@ declare const schemas: {
|
|
|
98
103
|
env: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodString>>;
|
|
99
104
|
runtime: zod0.ZodOptional<zod0.ZodLiteral<"nodejs24">>;
|
|
100
105
|
memoryMib: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<256>, zod0.ZodLiteral<512>, zod0.ZodLiteral<1024>, zod0.ZodLiteral<2048>, zod0.ZodLiteral<4096>, zod0.ZodLiteral<8192>]>>;
|
|
106
|
+
dev: zod0.ZodOptional<zod0.ZodObject<{
|
|
107
|
+
port: zod0.ZodOptional<zod0.ZodNumber>;
|
|
108
|
+
portless: zod0.ZodOptional<zod0.ZodBoolean>;
|
|
109
|
+
}, zod_v4_core0.$strict>>;
|
|
101
110
|
}, zod_v4_core0.$strict>;
|
|
102
111
|
readonly postgres: zod0.ZodObject<{
|
|
103
112
|
computeSettings: zod0.ZodOptional<zod0.ZodObject<{
|
|
@@ -114,6 +123,10 @@ declare const schemas: {
|
|
|
114
123
|
env: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodString>>;
|
|
115
124
|
runtime: zod0.ZodOptional<zod0.ZodLiteral<"nodejs24">>;
|
|
116
125
|
memoryMib: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<256>, zod0.ZodLiteral<512>, zod0.ZodLiteral<1024>, zod0.ZodLiteral<2048>, zod0.ZodLiteral<4096>, zod0.ZodLiteral<8192>]>>;
|
|
126
|
+
dev: zod0.ZodOptional<zod0.ZodObject<{
|
|
127
|
+
port: zod0.ZodOptional<zod0.ZodNumber>;
|
|
128
|
+
portless: zod0.ZodOptional<zod0.ZodBoolean>;
|
|
129
|
+
}, zod_v4_core0.$strict>>;
|
|
117
130
|
}, zod_v4_core0.$strict>>>;
|
|
118
131
|
buckets: zod0.ZodOptional<zod0.ZodArray<zod0.ZodObject<{
|
|
119
132
|
name: zod0.ZodString;
|
|
@@ -128,5 +141,5 @@ declare const schemas: {
|
|
|
128
141
|
}, zod_v4_core0.$strict>;
|
|
129
142
|
};
|
|
130
143
|
//#endregion
|
|
131
|
-
export { type AppliedChange, type BranchConfig, type BranchTarget, type BucketAccessLevel, type BucketConfig, type ComputeSettings, type Config, ConfigLoadError, ConfigValidationError, type ConflictReport, type CreateBranchInput, type CreateBucketInput, type CreateProjectInput, type DeployFunctionInput, type DiffOptions, type DiffResult, ErrorCode, type FunctionConfig, type FunctionMemoryMib, type FunctionRuntime, type GetConnectionUriInput, type LoadConfigOptions, MissingContextError, type NeonApi, type NeonAuthSnapshot, type NeonBranchSnapshot, type NeonBucketSnapshot, type NeonDataApiSnapshot, type NeonDatabaseSnapshot, type NeonEndpointSnapshot, type NeonFunctionDeploymentSnapshot, type NeonFunctionSnapshot, type NeonProjectSnapshot, type NeonRoleSnapshot, type PlanStep, PlatformError, type PostgresConfig, type PreviewConfig, PushAbortedError, PushConflictError, type PushResult, type RemotePreviewState, type RemoteServiceState, type RemoteState, type ResolvedBranchConfig, type ResolvedBucketConfig, type ResolvedFunctionConfig, type ResolvedPreviewConfig, type ServiceToggle, type UpdateBranchInput, createNeonApiFromOptions, createRealNeonApi, defineConfig, diffConfig, errors, loadConfigFromFile, resolveApiKey, resolveConfig, schemas };
|
|
144
|
+
export { type AppliedChange, type BranchConfig, type BranchTarget, type BucketAccessLevel, type BucketConfig, type ComputeSettings, type Config, ConfigLoadError, ConfigValidationError, type ConflictReport, type CreateBranchInput, type CreateBucketInput, type CreateProjectInput, type DeployFunctionInput, type DiffOptions, type DiffResult, ErrorCode, type FunctionConfig, type FunctionDevConfig, type FunctionMemoryMib, type FunctionRuntime, type GetConnectionUriInput, type LoadConfigOptions, MissingContextError, type NeonApi, type NeonAuthSnapshot, type NeonBranchSnapshot, type NeonBucketSnapshot, type NeonDataApiSnapshot, type NeonDatabaseSnapshot, type NeonEndpointSnapshot, type NeonFunctionDeploymentSnapshot, type NeonFunctionSnapshot, type NeonProjectSnapshot, type NeonRoleSnapshot, type PlanStep, PlatformError, type PostgresConfig, type PreviewConfig, PushAbortedError, PushConflictError, type PushResult, type RemotePreviewState, type RemoteServiceState, type RemoteState, type ResolvedBranchConfig, type ResolvedBucketConfig, type ResolvedFunctionConfig, type ResolvedPreviewConfig, type ServiceToggle, type UpdateBranchInput, createNeonApiFromOptions, createRealNeonApi, defineConfig, diffConfig, errors, loadConfigFromFile, resolveApiKey, resolveConfig, schemas };
|
|
132
145
|
//# sourceMappingURL=v1.d.ts.map
|
package/dist/v1.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v1.d.ts","names":[],"sources":["../src/v1.ts"],"mappings":";;;;;;;;;;;;;;;;;cA0Da
|
|
1
|
+
{"version":3,"file":"v1.d.ts","names":[],"sources":["../src/v1.ts"],"mappings":";;;;;;;;;;;;;;;;;cA0Da;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAWA;;6BASH,IAAA,CAAA,SAAA"}
|
package/dist/v1.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v1.js","names":[],"sources":["../src/v1.ts"],"sourcesContent":["/**\n * `@neondatabase/config/v1` — the v1 public API for Config-as-Code on the Neon Platform.\n *\n * Usage in `neon.ts`:\n * ```ts\n * import { defineConfig } from \"@neondatabase/config/v1\";\n *\n * export default defineConfig((branch) => {\n * if (branch.name === \"main\") return { protected: true, auth: {} };\n * return { parent: \"main\", ttl: \"7d\" };\n * });\n * ```\n *\n * This is the **authoring** surface — `defineConfig`, types, schemas, the pure diff engine,\n * and the Neon API adapter. It is intentionally free of heavy/native dependencies so that\n * importing it from `neon.ts` stays cheap and bundler-safe.\n *\n * The imperative operations (`inspect` / `plan` / `apply`, `pushConfig` / `pullConfig`) and\n * function bundling/deploy live in **`@neondatabase/config-runtime`**, which depends on this\n * package and pulls in `esbuild`. Import that from your CLI / CI, not from `neon.ts`:\n * ```ts\n * import config from \"../neon\";\n * import { inspect, plan, apply } from \"@neondatabase/config-runtime/v1\";\n * ```\n *\n * Surface guidelines:\n * - Top-level: `defineConfig` / `resolveConfig`, the pure `diffConfig` engine, the\n * `createRealNeonApi` adapter + `NeonApi` types, the config loader, the `PlatformError`\n * base class + `ErrorCode` enum, and the config types used in `neon.ts`.\n * - `errors` namespace: specific `PlatformError` subclasses (`ConfigLoadError`,\n * `PushConflictError`, …).\n * - `schemas` namespace: the zod schemas underlying `defineConfig`.\n */\n\nimport {\n\tConfigLoadError,\n\tConfigValidationError,\n\tErrorCode,\n\tMissingContextError,\n\tPlatformError,\n\tPushAbortedError,\n\tPushConflictError,\n} from \"./lib/errors.js\";\nimport {\n\tbranchConfigSchema,\n\tbucketConfigSchema,\n\tcomputeSettingsSchema,\n\tconfigSchema,\n\tfunctionConfigSchema,\n\tpostgresConfigSchema,\n\tpreviewConfigSchema,\n\tserviceToggleSchema,\n} from \"./lib/schema.js\";\n\n/**\n * Specific `PlatformError` subclasses, grouped for `instanceof` / structured access.\n * Also available as top-level exports.\n */\nexport const errors = {\n\tConfigLoadError,\n\tConfigValidationError,\n\tErrorCode,\n\tMissingContextError,\n\tPlatformError,\n\tPushAbortedError,\n\tPushConflictError,\n} as const;\n\n/** The zod schemas underlying `defineConfig`, grouped under product-friendly names. */\nexport const schemas = {\n\tbranch: branchConfigSchema,\n\tbucket: bucketConfigSchema,\n\tcomputeSettings: computeSettingsSchema,\n\tconfig: configSchema,\n\tfunction: functionConfigSchema,\n\tpostgres: postgresConfigSchema,\n\tpreview: previewConfigSchema,\n\tservice: serviceToggleSchema,\n} as const;\n\n// ─── Lower-level adapters ──────────────────────────────────────────────────────\nexport { createNeonApiFromOptions, resolveApiKey } from \"./lib/auth.js\";\nexport { defineConfig, resolveConfig } from \"./lib/define-config.js\";\n// ─── Diff engine (pure; consumed by @neondatabase/config-runtime) ─────────────\nexport type {\n\tDiffOptions,\n\tDiffResult,\n\tPlanStep,\n\tRemotePreviewState,\n\tRemoteServiceState,\n\tRemoteState,\n} from \"./lib/diff.js\";\nexport { diffConfig } from \"./lib/diff.js\";\n// ─── Errors ────────────────────────────────────────────────────────────────────\nexport {\n\tConfigLoadError,\n\tConfigValidationError,\n\tErrorCode,\n\tMissingContextError,\n\tPlatformError,\n\tPushAbortedError,\n\tPushConflictError,\n} from \"./lib/errors.js\";\nexport type { LoadConfigOptions } from \"./lib/loader.js\";\nexport { loadConfigFromFile } from \"./lib/loader.js\";\n// ─── NeonApi types (needed by callers implementing their own adapters) ────────\nexport type {\n\tCreateBranchInput,\n\tCreateBucketInput,\n\tCreateProjectInput,\n\tDeployFunctionInput,\n\tGetConnectionUriInput,\n\tNeonApi,\n\tNeonAuthSnapshot,\n\tNeonBranchSnapshot,\n\tNeonBucketSnapshot,\n\tNeonDataApiSnapshot,\n\tNeonDatabaseSnapshot,\n\tNeonEndpointSnapshot,\n\tNeonFunctionDeploymentSnapshot,\n\tNeonFunctionSnapshot,\n\tNeonProjectSnapshot,\n\tNeonRoleSnapshot,\n\tUpdateBranchInput,\n} from \"./lib/neon-api.js\";\nexport { createRealNeonApi } from \"./lib/neon-api-real.js\";\n// ─── Config types (used in neon.ts and in operation return values) ────────────\nexport type {\n\tAppliedChange,\n\tBranchConfig,\n\tBranchTarget,\n\tBucketAccessLevel,\n\tBucketConfig,\n\tComputeSettings,\n\tConfig,\n\tConflictReport,\n\tFunctionConfig,\n\tFunctionMemoryMib,\n\tFunctionRuntime,\n\tPostgresConfig,\n\tPreviewConfig,\n\tPushResult,\n\tResolvedBranchConfig,\n\tResolvedBucketConfig,\n\tResolvedFunctionConfig,\n\tResolvedPreviewConfig,\n\tServiceToggle,\n} from \"./lib/types.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,MAAa,SAAS;CACrB;CACA;CACA;CACA;CACA;CACA;CACA;AACD;;AAGA,MAAa,UAAU;CACtB,QAAQ;CACR,QAAQ;CACR,iBAAiB;CACjB,QAAQ;CACR,UAAU;CACV,UAAU;CACV,SAAS;CACT,SAAS;AACV"}
|
|
1
|
+
{"version":3,"file":"v1.js","names":[],"sources":["../src/v1.ts"],"sourcesContent":["/**\n * `@neondatabase/config/v1` — the v1 public API for Config-as-Code on the Neon Platform.\n *\n * Usage in `neon.ts`:\n * ```ts\n * import { defineConfig } from \"@neondatabase/config/v1\";\n *\n * export default defineConfig((branch) => {\n * if (branch.name === \"main\") return { protected: true, auth: {} };\n * return { parent: \"main\", ttl: \"7d\" };\n * });\n * ```\n *\n * This is the **authoring** surface — `defineConfig`, types, schemas, the pure diff engine,\n * and the Neon API adapter. It is intentionally free of heavy/native dependencies so that\n * importing it from `neon.ts` stays cheap and bundler-safe.\n *\n * The imperative operations (`inspect` / `plan` / `apply`, `pushConfig` / `pullConfig`) and\n * function bundling/deploy live in **`@neondatabase/config-runtime`**, which depends on this\n * package and pulls in `esbuild`. Import that from your CLI / CI, not from `neon.ts`:\n * ```ts\n * import config from \"../neon\";\n * import { inspect, plan, apply } from \"@neondatabase/config-runtime/v1\";\n * ```\n *\n * Surface guidelines:\n * - Top-level: `defineConfig` / `resolveConfig`, the pure `diffConfig` engine, the\n * `createRealNeonApi` adapter + `NeonApi` types, the config loader, the `PlatformError`\n * base class + `ErrorCode` enum, and the config types used in `neon.ts`.\n * - `errors` namespace: specific `PlatformError` subclasses (`ConfigLoadError`,\n * `PushConflictError`, …).\n * - `schemas` namespace: the zod schemas underlying `defineConfig`.\n */\n\nimport {\n\tConfigLoadError,\n\tConfigValidationError,\n\tErrorCode,\n\tMissingContextError,\n\tPlatformError,\n\tPushAbortedError,\n\tPushConflictError,\n} from \"./lib/errors.js\";\nimport {\n\tbranchConfigSchema,\n\tbucketConfigSchema,\n\tcomputeSettingsSchema,\n\tconfigSchema,\n\tfunctionConfigSchema,\n\tpostgresConfigSchema,\n\tpreviewConfigSchema,\n\tserviceToggleSchema,\n} from \"./lib/schema.js\";\n\n/**\n * Specific `PlatformError` subclasses, grouped for `instanceof` / structured access.\n * Also available as top-level exports.\n */\nexport const errors = {\n\tConfigLoadError,\n\tConfigValidationError,\n\tErrorCode,\n\tMissingContextError,\n\tPlatformError,\n\tPushAbortedError,\n\tPushConflictError,\n} as const;\n\n/** The zod schemas underlying `defineConfig`, grouped under product-friendly names. */\nexport const schemas = {\n\tbranch: branchConfigSchema,\n\tbucket: bucketConfigSchema,\n\tcomputeSettings: computeSettingsSchema,\n\tconfig: configSchema,\n\tfunction: functionConfigSchema,\n\tpostgres: postgresConfigSchema,\n\tpreview: previewConfigSchema,\n\tservice: serviceToggleSchema,\n} as const;\n\n// ─── Lower-level adapters ──────────────────────────────────────────────────────\nexport { createNeonApiFromOptions, resolveApiKey } from \"./lib/auth.js\";\nexport { defineConfig, resolveConfig } from \"./lib/define-config.js\";\n// ─── Diff engine (pure; consumed by @neondatabase/config-runtime) ─────────────\nexport type {\n\tDiffOptions,\n\tDiffResult,\n\tPlanStep,\n\tRemotePreviewState,\n\tRemoteServiceState,\n\tRemoteState,\n} from \"./lib/diff.js\";\nexport { diffConfig } from \"./lib/diff.js\";\n// ─── Errors ────────────────────────────────────────────────────────────────────\nexport {\n\tConfigLoadError,\n\tConfigValidationError,\n\tErrorCode,\n\tMissingContextError,\n\tPlatformError,\n\tPushAbortedError,\n\tPushConflictError,\n} from \"./lib/errors.js\";\nexport type { LoadConfigOptions } from \"./lib/loader.js\";\nexport { loadConfigFromFile } from \"./lib/loader.js\";\n// ─── NeonApi types (needed by callers implementing their own adapters) ────────\nexport type {\n\tCreateBranchInput,\n\tCreateBucketInput,\n\tCreateProjectInput,\n\tDeployFunctionInput,\n\tGetConnectionUriInput,\n\tNeonApi,\n\tNeonAuthSnapshot,\n\tNeonBranchSnapshot,\n\tNeonBucketSnapshot,\n\tNeonDataApiSnapshot,\n\tNeonDatabaseSnapshot,\n\tNeonEndpointSnapshot,\n\tNeonFunctionDeploymentSnapshot,\n\tNeonFunctionSnapshot,\n\tNeonProjectSnapshot,\n\tNeonRoleSnapshot,\n\tUpdateBranchInput,\n} from \"./lib/neon-api.js\";\nexport { createRealNeonApi } from \"./lib/neon-api-real.js\";\n// ─── Config types (used in neon.ts and in operation return values) ────────────\nexport type {\n\tAppliedChange,\n\tBranchConfig,\n\tBranchTarget,\n\tBucketAccessLevel,\n\tBucketConfig,\n\tComputeSettings,\n\tConfig,\n\tConflictReport,\n\tFunctionConfig,\n\tFunctionDevConfig,\n\tFunctionMemoryMib,\n\tFunctionRuntime,\n\tPostgresConfig,\n\tPreviewConfig,\n\tPushResult,\n\tResolvedBranchConfig,\n\tResolvedBucketConfig,\n\tResolvedFunctionConfig,\n\tResolvedPreviewConfig,\n\tServiceToggle,\n} from \"./lib/types.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DA,MAAa,SAAS;CACrB;CACA;CACA;CACA;CACA;CACA;CACA;AACD;;AAGA,MAAa,UAAU;CACtB,QAAQ;CACR,QAAQ;CACR,iBAAiB;CACjB,QAAQ;CACR,UAAU;CACV,UAAU;CACV,SAAS;CACT,SAAS;AACV"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neondatabase/config",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.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",
|