@neondatabase/config 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"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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"}
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\n/** Object form of a service toggle (`{ enabled?: boolean }`). */\nexport const serviceToggleSchema = z.strictObject({\n\tenabled: z.boolean().optional(),\n});\n\n/** A service toggle as written in a policy: `boolean` or `{ enabled?: boolean }`. */\nexport const serviceToggleInputSchema = z.union([\n\tz.boolean(),\n\tserviceToggleSchema,\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 * Used as the **key schema** of the `preview.functions` record, so a bad slug fails\n * validation with a path pointing at the offending key and duplicate slugs are impossible\n * by construction (object keys are unique).\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/** Bucket name: 1–255 chars. Used as the key schema of the `preview.buckets` record. */\nconst bucketNameSchema = z.string().min(1).max(255);\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\nconst runtimeSchema = z.literal(\"nodejs24\");\n\n/**\n * Static definition of a function (existence). The slug is the record key (validated by\n * {@link functionSlugSchema}), so it is not a field here. Deploy tuning (`runtime`) lives\n * in the `branch` closure, not here.\n */\nexport const functionDefSchema = z.strictObject({\n\tname: z.string().min(1).max(255),\n\tsource: z.string().min(1),\n\tenv: functionEnvSchema.optional(),\n\tdev: functionDevConfigSchema.optional(),\n});\n\n/** Static definition of a bucket (existence). Name is the record key. */\nexport const bucketDefSchema = z.strictObject({\n\taccess: z\n\t\t.union([z.literal(\"private\"), z.literal(\"public_read\")])\n\t\t.optional(),\n});\n\n/** Static, beta Preview feature set: AI Gateway toggle + functions/buckets records. */\nexport const previewInputSchema = z.strictObject({\n\taiGateway: serviceToggleInputSchema.optional(),\n\tfunctions: z.record(functionSlugSchema, functionDefSchema).optional(),\n\tbuckets: z.record(bucketNameSchema, bucketDefSchema).optional(),\n});\n\n/** Per-function deploy tuning returned by the `branch` closure. */\nexport const functionTuningSchema = z.strictObject({\n\truntime: runtimeSchema.optional(),\n});\n\n/** Per-branch Preview tuning. Keys must be slugs declared in the static `preview`. */\nconst previewTuningSchema = z.strictObject({\n\tfunctions: z.record(functionSlugSchema, functionTuningSchema).optional(),\n});\n\n/**\n * The object returned by the `branch` closure. Validated on every `resolveConfig` call so\n * tuning errors point at the concrete branch target that triggered them.\n */\nexport const branchTuningSchema = 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\tpreview: previewTuningSchema.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\n/**\n * The top-level object accepted by `defineConfig`. The `branch` closure is validated\n * structurally as a function here; its returned tuning is validated per-evaluation by\n * {@link branchTuningSchema} inside `resolveConfig`.\n */\nexport const configInputSchema = z.strictObject({\n\tauth: serviceToggleInputSchema.optional(),\n\tdataApi: serviceToggleInputSchema.optional(),\n\tpreview: previewInputSchema.optional(),\n\tbranch: z\n\t\t.custom<(...args: unknown[]) => unknown>(\n\t\t\t(value) => typeof value === \"function\",\n\t\t\t{\n\t\t\t\tmessage:\n\t\t\t\t\t\"branch must be a function: `branch: (branch) => ({ … })`\",\n\t\t\t},\n\t\t)\n\t\t.optional(),\n});\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\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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"}
@@ -61,10 +61,26 @@ interface BranchTarget {
61
61
  /** Current expiration timestamp from Neon, when set. */
62
62
  expiresAt?: string;
63
63
  }
64
+ /**
65
+ * Object form of a branch-scoped service toggle. `{}` or `{ enabled: true }` enables it;
66
+ * `{ enabled: false }` opts out. Used as the object half of {@link ServiceToggleInput}.
67
+ */
64
68
  interface ServiceToggle {
65
69
  /** Defaults to `true` when the service namespace is present. Set `false` to opt out. */
66
70
  enabled?: boolean;
67
71
  }
72
+ /**
73
+ * How a branch-scoped service (Neon Auth, Data API, AI Gateway) is toggled in a policy.
74
+ *
75
+ * - `true` / `{}` / `{ enabled: true }` — enabled.
76
+ * - `false` / `{ enabled: false }` — disabled.
77
+ * - omitted (`undefined`) — not part of the policy at all.
78
+ *
79
+ * These toggles are **static** (they live in the top-level `defineConfig({ … })` object,
80
+ * not in the per-branch `branch` closure) so the secret set they imply can be derived at
81
+ * the type level — that's what makes `NeonEnv<typeof config>` exact.
82
+ */
83
+ type ServiceToggleInput = boolean | ServiceToggle;
68
84
  interface PostgresConfig {
69
85
  computeSettings?: ComputeSettings;
70
86
  }
@@ -74,11 +90,6 @@ interface PostgresConfig {
74
90
  * non-breaking, type-checked change.
75
91
  */
76
92
  type FunctionRuntime = "nodejs24";
77
- /**
78
- * Memory sizes (MiB) accepted by the Neon Functions deploy API. Mirrors the
79
- * `memory_mib` enum in the spec.
80
- */
81
- type FunctionMemoryMib = 256 | 512 | 1024 | 2048 | 4096 | 8192;
82
93
  /**
83
94
  * Local-development settings for a function, used by `neon dev` when it serves every
84
95
  * function declared in `neon.ts` (i.e. invoked with no `--source`). Never affects deploy.
@@ -104,20 +115,21 @@ interface FunctionDevConfig {
104
115
  portless?: boolean;
105
116
  }
106
117
  /**
107
- * A single Neon Function deployed to a branch (Preview feature).
118
+ * Static definition of a Neon Function (Preview feature). Declares that the function
119
+ * **exists** on every branch; its branch-unique slug is the **record key** in
120
+ * {@link PreviewInput.functions} (not a field here), so slugs are statically enumerable,
121
+ * cannot duplicate, and the `branch` closure can only tune slugs that are declared here.
108
122
  *
109
123
  * A function is invoked like a Cloudflare/Vercel handler — its source module
110
124
  * `export default { fetch }` or `export async function handler(req): Response`. The
111
- * `source` path is bundled (esbuild) and uploaded as a deployment; the newest
112
- * deployment becomes active.
125
+ * `source` path is bundled (esbuild) and uploaded as a deployment; the newest deployment
126
+ * becomes active.
127
+ *
128
+ * Runtime tuning is **not** here — it varies per branch and lives in the `branch` closure
129
+ * (see {@link FunctionTuning}). Memory is fixed by the platform policy for now and is not
130
+ * user-configurable.
113
131
  */
114
- interface FunctionConfig {
115
- /**
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"
119
- */
120
- slug: string;
132
+ interface FunctionDef {
121
133
  /** Free-form display name. @example "Hello World" */
122
134
  name: string;
123
135
  /**
@@ -132,16 +144,16 @@ interface FunctionConfig {
132
144
  */
133
145
  source: string;
134
146
  /**
135
- * Environment variables injected into the deployed function. Every value must be a
136
- * defined string a `process.env.X` that is `undefined` (unset) errors at validation
137
- * time rather than silently shipping `undefined`.
138
- * @example { RESEND_API_KEY: process.env.RESEND_API_KEY }
147
+ * Environment variables injected into the deployed function, keyed by the var name the
148
+ * function reads at runtime. The **keys** are static (preserved at the type level so
149
+ * `parseEnv(config, "<slug>").function.<key>` is typed); the **values** are arbitrary
150
+ * strings evaluated when `neon.ts` is loaded (typically `process.env.X`) and uploaded
151
+ * at `config apply`. Every value must be a defined string — a `process.env.X` that is
152
+ * `undefined` (unset) errors at validation time rather than silently shipping
153
+ * `undefined`.
154
+ * @example { resendApiKey: process.env.RESEND_API_KEY ?? "" }
139
155
  */
140
156
  env?: Record<string, string>;
141
- /** Runtime to execute the function with. Defaults to `"nodejs24"`. */
142
- runtime?: FunctionRuntime;
143
- /** Memory allotted to each invocation, in MiB. Defaults to `512`. */
144
- memoryMib?: FunctionMemoryMib;
145
157
  /**
146
158
  * Local-development settings used by `neon dev` when serving every function from
147
159
  * `neon.ts`. Ignored at deploy time. See {@link FunctionDevConfig}.
@@ -151,11 +163,11 @@ interface FunctionConfig {
151
163
  /** Anonymous-access level for a branchable object-storage bucket. */
152
164
  type BucketAccessLevel = "private" | "public_read";
153
165
  /**
154
- * A branchable object-storage bucket on a branch (Preview feature).
166
+ * Static definition of a branchable object-storage bucket (Preview feature). The bucket's
167
+ * name is the **record key** in {@link PreviewInput.buckets}, so names are statically
168
+ * enumerable and cannot duplicate.
155
169
  */
156
- interface BucketConfig {
157
- /** Bucket name, unique within a branch. 1–255 chars. */
158
- name: string;
170
+ interface BucketDef {
159
171
  /**
160
172
  * Anonymous access level. `private` (default) requires authenticated reads/writes;
161
173
  * `public_read` allows anonymous GetObject/HeadObject.
@@ -163,18 +175,44 @@ interface BucketConfig {
163
175
  access?: BucketAccessLevel;
164
176
  }
165
177
  /**
166
- * Branch-scoped Preview features. Grouped under `preview` to signal they are backed by
167
- * Neon `x-stability-level: beta` endpoints and may change before GA.
178
+ * Static, branch-scoped **Preview** features. Grouped under `preview` to signal they are
179
+ * backed by Neon `x-stability-level: beta` endpoints and may change before GA. Everything
180
+ * here is existential (it determines what exists on the branch); per-branch tuning lives in
181
+ * the `branch` closure.
168
182
  */
169
- interface PreviewConfig {
170
- /** Functions to deploy on the branch. */
171
- functions?: FunctionConfig[];
172
- /** Object-storage buckets to create on the branch. */
173
- buckets?: BucketConfig[];
183
+ interface PreviewInput {
174
184
  /** Enable/disable the AI Gateway on the branch (toggle, like auth / dataApi). */
175
- aiGateway?: ServiceToggle;
185
+ aiGateway?: ServiceToggleInput;
186
+ /** Functions to deploy, keyed by branch-unique slug (`^[a-z0-9]{1,20}$`). */
187
+ functions?: Record<string, FunctionDef>;
188
+ /** Object-storage buckets to create, keyed by bucket name. */
189
+ buckets?: Record<string, BucketDef>;
190
+ }
191
+ /**
192
+ * Per-branch deploy tuning for a single function. Returned (per slug) by the `branch`
193
+ * closure. Deliberately **cannot** change the function's existence, source, name, env
194
+ * **keys**, or memory — only runtime selection is currently configurable — so the static
195
+ * secret/function set stays sound.
196
+ */
197
+ interface FunctionTuning {
198
+ /** Runtime to execute the function with. Defaults to `"nodejs24"`. */
199
+ runtime?: FunctionRuntime;
176
200
  }
177
- interface BranchConfigBase {
201
+ /**
202
+ * Per-branch tuning of Preview features. Only existing function slugs (those declared in
203
+ * the static {@link PreviewInput.functions}) may be tuned — `Slug` is constrained to the
204
+ * declared keys by {@link BranchTuningFn}.
205
+ */
206
+ interface PreviewTuning<Slug extends string = string> {
207
+ functions?: Partial<Record<Slug, FunctionTuning>>;
208
+ }
209
+ /**
210
+ * The per-branch tuning object returned by the `branch` closure. It can adjust branch
211
+ * lifecycle (`parent`, `ttl`, `protected`), Postgres compute settings, and per-function
212
+ * deploy tuning — but **cannot** add/remove services or functions. That guarantee is what
213
+ * keeps the static secret set (and therefore `NeonEnv`) exact.
214
+ */
215
+ interface BranchTuning<Slug extends string = string> {
178
216
  /** Parent branch name used when creating a new branch. Not a Postgres setting. */
179
217
  parent?: string;
180
218
  /** Time-to-live applied when creating a new branch, or reconciled on existing branches. */
@@ -182,30 +220,43 @@ interface BranchConfigBase {
182
220
  /** Whether the selected branch should be protected. Undefined means "leave as-is". */
183
221
  protected?: boolean;
184
222
  postgres?: PostgresConfig;
185
- /**
186
- * Branch-scoped Preview features (functions, object-storage buckets, AI Gateway).
187
- * Backed by Neon `x-stability-level: beta` endpoints see {@link PreviewConfig}.
188
- */
189
- preview?: PreviewConfig;
223
+ preview?: PreviewTuning<Slug>;
224
+ }
225
+ /** Extract the declared function slugs from a {@link PreviewInput} for closure typing. */
226
+ type FunctionSlugsOf<Preview extends PreviewInput | undefined> = Preview extends {
227
+ functions: infer F;
228
+ } ? Extract<keyof F, string> : string;
229
+ /**
230
+ * Signature of the `branch` closure. Generic over the static {@link PreviewInput} so the
231
+ * `preview.functions` keys it may tune are constrained to the slugs actually declared.
232
+ */
233
+ type BranchTuningFn<Preview extends PreviewInput | undefined = PreviewInput | undefined> = (branch: BranchTarget) => BranchTuning<FunctionSlugsOf<Preview>>;
234
+ /**
235
+ * A validated Neon branch policy — the value `defineConfig({ … })` returns and `neon.ts`
236
+ * default-exports.
237
+ *
238
+ * Split into a **static** existential set (top-level `auth` / `dataApi` GA toggles plus the
239
+ * beta `preview` block) and a **dynamic** per-branch `branch` closure for tuning. The
240
+ * static half is what makes the secret set — and therefore `NeonEnv<typeof config>` and
241
+ * `parseEnv` — exact; the closure can tune but never change what exists.
242
+ *
243
+ * Generic over the three static fields so the type system can read the exact toggle/slug
244
+ * literals; the defaults make the bare `Config` a usable "any policy" type for runtime
245
+ * function signatures.
246
+ */
247
+ interface Config<Auth extends ServiceToggleInput | undefined = ServiceToggleInput | undefined, DataApi extends ServiceToggleInput | undefined = ServiceToggleInput | undefined, Preview extends PreviewInput | undefined = PreviewInput | undefined> {
248
+ /** Neon Auth integration toggle (GA). Static — drives `NeonEnv.auth`. */
249
+ auth?: Auth;
250
+ /** Neon Data API integration toggle (GA). Static — drives `NeonEnv.dataApi`. */
251
+ dataApi?: DataApi;
252
+ /** Beta (Preview) feature set: AI Gateway, functions, buckets. Static. */
253
+ preview?: Preview;
254
+ /** Per-branch tuning closure. Cannot change the static existential set. */
255
+ branch?: BranchTuningFn<Preview>;
190
256
  }
191
- type BranchServiceConfig = {
192
- auth?: never;
193
- dataApi?: never;
194
- } | {
195
- auth: ServiceToggle;
196
- dataApi?: never;
197
- } | {
198
- auth?: never;
199
- dataApi: ServiceToggle;
200
- } | {
201
- auth: ServiceToggle;
202
- dataApi: ServiceToggle;
203
- };
204
- type BranchConfig = BranchConfigBase & BranchServiceConfig;
205
- type Config = (branch: BranchTarget) => BranchConfig;
206
257
  /**
207
- * A function with all deploy defaults applied. `resolveConfig` fills in `runtime` and
208
- * `memoryMib` so downstream diff/apply never has to re-derive them.
258
+ * A function with all deploy defaults applied. `resolveConfig` fills in `runtime` so
259
+ * downstream diff/apply never has to re-derive it.
209
260
  */
210
261
  interface ResolvedFunctionConfig {
211
262
  slug: string;
@@ -213,9 +264,8 @@ interface ResolvedFunctionConfig {
213
264
  source: string;
214
265
  env: Record<string, string>;
215
266
  runtime: FunctionRuntime;
216
- memoryMib: FunctionMemoryMib;
217
267
  /**
218
- * Local-development settings, passed through untouched from {@link FunctionConfig.dev}
268
+ * Local-development settings, passed through untouched from {@link FunctionDef.dev}
219
269
  * (no defaults applied). Only consumed by `neon dev`; deploy ignores it.
220
270
  */
221
271
  dev?: FunctionDevConfig;
@@ -226,7 +276,7 @@ interface ResolvedBucketConfig {
226
276
  access: BucketAccessLevel;
227
277
  }
228
278
  /**
229
- * Normalized {@link PreviewConfig}. Only present on {@link ResolvedBranchConfig} when the
279
+ * Normalized {@link PreviewInput}. Only present on {@link ResolvedBranchConfig} when the
230
280
  * policy returned a `preview` block. `aiGatewayEnabled` follows the same
231
281
  * "present-and-not-`false`" semantics as `authEnabled` / `dataApiEnabled`.
232
282
  */
@@ -289,5 +339,5 @@ interface PushResult {
289
339
  conflicts: ConflictReport[];
290
340
  }
291
341
  //#endregion
292
- export { AppliedChange, BranchConfig, BranchTarget, BucketAccessLevel, BucketConfig, ComputeSettings, ComputeUnit, Config, ConflictReport, FunctionConfig, FunctionDevConfig, FunctionMemoryMib, FunctionRuntime, PostgresConfig, PreviewConfig, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle };
342
+ export { AppliedChange, BranchTarget, BranchTuning, BranchTuningFn, BucketAccessLevel, BucketDef, ComputeSettings, ComputeUnit, Config, ConflictReport, FunctionDef, FunctionDevConfig, FunctionRuntime, FunctionTuning, PostgresConfig, PreviewInput, PreviewTuning, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle, ServiceToggleInput };
293
343
  //# sourceMappingURL=types.d.ts.map
@@ -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;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"}
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;AAqBA;AAgBA;AAEA;AASA;AAciB,UAjGA,eAAA,CAiGiB;EA4BjB;;;;AA6BO;EAIZ,qBAAiB,CAAA,EAxJJ,WAwJI;EAOZ;AAcjB;;;;uBAIa,CAAA,EA3KY,WA2KZ;;;AAEI;AASjB;AAUA;;;;;;AACoB;AASpB;;gBAOY,CAAA,EAAA,KAAA,GAAA,IAAA,GAAA,IAAA,GAAA,MAAA,GAAA,MAAA;;;AACY;AACvB;;;;AAOiB,UAnMD,YAAA,CAmMC;;EAAP,IAAA,EAAA,MAAA;EAOC;EAAc,EAAA,CAAA,EAAA,MAAA;;QACkB,EAAA,OAAA;;UACe,CAAA,EAAA,MAAA;;WAA7B,CAAA,EAAA,OAAA;EAAY;EAezB,WAAM,CAAA,EAAA,OAAA;EAAA;WACT,CAAA,EAAA,MAAA;;;;;;AASN,UAhNS,aAAA,CAgNT;;SAIG,CAAA,EAAA,OAAA;;;AAEa;AAOxB;;;;;AAUwB;AAIxB;AAUA;;AACY,KAtOA,kBAAA,GAsOA,OAAA,GAtO+B,aAsO/B;AACF,UArOO,cAAA,CAqOP;EAAoB,eAAA,CAAA,EApOX,eAoOW;AAI9B;;;;AAOgC;AAMhC;AAkBiB,KA/PL,eAAA,GA+PmB,UAAA;AAY/B;;;;AAW0B;;;;;;;;UAxQT,iBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;UA4BA,WAAA;;;;;;;;;;;;;;;;;;;;;;;;QAwBV;;;;;QAKA;;;KAIK,iBAAA;;;;;;UAOK,SAAA;;;;;WAKP;;;;;;;;UASO,YAAA;;cAEJ;;cAEA,eAAe;;YAEjB,eAAe;;;;;;;;UAST,cAAA;;YAEN;;;;;;;UAQM;cACJ,QAAQ,OAAO,MAAM;;;;;;;;UASjB;;;;;;;aAOL;YACD,cAAc;;;KAIpB,gCAAgC,4BACpC;;IAGG,cAAc;;;;;KAON,+BACK,2BAA2B,qCAC/B,iBAAiB,aAAa,gBAAgB;;;;;;;;;;;;;;UAe1C,oBACH,iCACV,gDAEa,iCACb,gDAEa,2BAA2B;;SAGpC;;YAEG;;YAEA;;WAED,eAAe;;;;;;UAOR,sBAAA;;;;OAIX;WACI;;;;;QAKH;;;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, FunctionDevConfig, FunctionMemoryMib, FunctionRuntime, PostgresConfig, PreviewConfig, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle } from "./lib/types.js";
1
+ import { AppliedChange, BranchTarget, BranchTuning, BranchTuningFn, BucketAccessLevel, BucketDef, ComputeSettings, Config, ConflictReport, FunctionDef, FunctionDevConfig, FunctionRuntime, FunctionTuning, PostgresConfig, PreviewInput, PreviewTuning, PushResult, ResolvedBranchConfig, ResolvedBucketConfig, ResolvedFunctionConfig, ResolvedPreviewConfig, ServiceToggle, ServiceToggleInput } 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";
@@ -47,47 +47,50 @@ declare const errors: {
47
47
  };
48
48
  /** The zod schemas underlying `defineConfig`, grouped under product-friendly names. */
49
49
  declare const schemas: {
50
- readonly branch: zod0.ZodObject<{
51
- parent: zod0.ZodOptional<zod0.ZodString>;
52
- protected: zod0.ZodOptional<zod0.ZodBoolean>;
53
- ttl: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodString, zod0.ZodNumber]>>;
54
- postgres: zod0.ZodOptional<zod0.ZodObject<{
55
- computeSettings: zod0.ZodOptional<zod0.ZodObject<{
56
- autoscalingLimitMinCu: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<0.25>, zod0.ZodLiteral<0.5>, zod0.ZodLiteral<1>, zod0.ZodLiteral<2>, zod0.ZodLiteral<4>, zod0.ZodLiteral<8>]>>;
57
- autoscalingLimitMaxCu: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<0.25>, zod0.ZodLiteral<0.5>, zod0.ZodLiteral<1>, zod0.ZodLiteral<2>, zod0.ZodLiteral<4>, zod0.ZodLiteral<8>]>>;
58
- suspendTimeout: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<false>, zod0.ZodString, zod0.ZodNumber]>>;
59
- }, zod_v4_core0.$strict>>;
60
- }, zod_v4_core0.$strict>>;
61
- auth: zod0.ZodOptional<zod0.ZodObject<{
50
+ readonly config: zod0.ZodObject<{
51
+ auth: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodBoolean, zod0.ZodObject<{
62
52
  enabled: zod0.ZodOptional<zod0.ZodBoolean>;
63
- }, zod_v4_core0.$strict>>;
64
- dataApi: zod0.ZodOptional<zod0.ZodObject<{
53
+ }, zod_v4_core0.$strict>]>>;
54
+ dataApi: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodBoolean, zod0.ZodObject<{
65
55
  enabled: zod0.ZodOptional<zod0.ZodBoolean>;
66
- }, zod_v4_core0.$strict>>;
56
+ }, zod_v4_core0.$strict>]>>;
67
57
  preview: zod0.ZodOptional<zod0.ZodObject<{
68
- functions: zod0.ZodOptional<zod0.ZodArray<zod0.ZodObject<{
69
- slug: zod0.ZodString;
58
+ aiGateway: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodBoolean, zod0.ZodObject<{
59
+ enabled: zod0.ZodOptional<zod0.ZodBoolean>;
60
+ }, zod_v4_core0.$strict>]>>;
61
+ functions: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodObject<{
70
62
  name: zod0.ZodString;
71
63
  source: zod0.ZodString;
72
64
  env: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodString>>;
73
- runtime: zod0.ZodOptional<zod0.ZodLiteral<"nodejs24">>;
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
65
  dev: zod0.ZodOptional<zod0.ZodObject<{
76
66
  port: zod0.ZodOptional<zod0.ZodNumber>;
77
67
  portless: zod0.ZodOptional<zod0.ZodBoolean>;
78
68
  }, zod_v4_core0.$strict>>;
79
69
  }, zod_v4_core0.$strict>>>;
80
- buckets: zod0.ZodOptional<zod0.ZodArray<zod0.ZodObject<{
81
- name: zod0.ZodString;
70
+ buckets: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodObject<{
82
71
  access: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<"private">, zod0.ZodLiteral<"public_read">]>>;
83
72
  }, zod_v4_core0.$strict>>>;
84
- aiGateway: zod0.ZodOptional<zod0.ZodObject<{
85
- enabled: zod0.ZodOptional<zod0.ZodBoolean>;
73
+ }, zod_v4_core0.$strict>>;
74
+ branch: zod0.ZodOptional<zod0.ZodCustom<(...args: unknown[]) => unknown, (...args: unknown[]) => unknown>>;
75
+ }, zod_v4_core0.$strict>;
76
+ readonly branchTuning: zod0.ZodObject<{
77
+ parent: zod0.ZodOptional<zod0.ZodString>;
78
+ protected: zod0.ZodOptional<zod0.ZodBoolean>;
79
+ ttl: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodString, zod0.ZodNumber]>>;
80
+ postgres: zod0.ZodOptional<zod0.ZodObject<{
81
+ computeSettings: zod0.ZodOptional<zod0.ZodObject<{
82
+ autoscalingLimitMinCu: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<0.25>, zod0.ZodLiteral<0.5>, zod0.ZodLiteral<1>, zod0.ZodLiteral<2>, zod0.ZodLiteral<4>, zod0.ZodLiteral<8>]>>;
83
+ autoscalingLimitMaxCu: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<0.25>, zod0.ZodLiteral<0.5>, zod0.ZodLiteral<1>, zod0.ZodLiteral<2>, zod0.ZodLiteral<4>, zod0.ZodLiteral<8>]>>;
84
+ suspendTimeout: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<false>, zod0.ZodString, zod0.ZodNumber]>>;
86
85
  }, zod_v4_core0.$strict>>;
87
86
  }, zod_v4_core0.$strict>>;
87
+ preview: zod0.ZodOptional<zod0.ZodObject<{
88
+ functions: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodObject<{
89
+ runtime: zod0.ZodOptional<zod0.ZodLiteral<"nodejs24">>;
90
+ }, zod_v4_core0.$strict>>>;
91
+ }, zod_v4_core0.$strict>>;
88
92
  }, zod_v4_core0.$strict>;
89
93
  readonly bucket: zod0.ZodObject<{
90
- name: zod0.ZodString;
91
94
  access: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<"private">, zod0.ZodLiteral<"public_read">]>>;
92
95
  }, zod_v4_core0.$strict>;
93
96
  readonly computeSettings: zod0.ZodObject<{
@@ -95,19 +98,18 @@ declare const schemas: {
95
98
  autoscalingLimitMaxCu: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<0.25>, zod0.ZodLiteral<0.5>, zod0.ZodLiteral<1>, zod0.ZodLiteral<2>, zod0.ZodLiteral<4>, zod0.ZodLiteral<8>]>>;
96
99
  suspendTimeout: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<false>, zod0.ZodString, zod0.ZodNumber]>>;
97
100
  }, zod_v4_core0.$strict>;
98
- readonly config: zod0.ZodFunction<zod0.ZodTuple<readonly [zod0.ZodUnknown], null>, zod0.ZodUnknown>;
99
101
  readonly function: zod0.ZodObject<{
100
- slug: zod0.ZodString;
101
102
  name: zod0.ZodString;
102
103
  source: zod0.ZodString;
103
104
  env: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodString>>;
104
- runtime: zod0.ZodOptional<zod0.ZodLiteral<"nodejs24">>;
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
105
  dev: zod0.ZodOptional<zod0.ZodObject<{
107
106
  port: zod0.ZodOptional<zod0.ZodNumber>;
108
107
  portless: zod0.ZodOptional<zod0.ZodBoolean>;
109
108
  }, zod_v4_core0.$strict>>;
110
109
  }, zod_v4_core0.$strict>;
110
+ readonly functionTuning: zod0.ZodObject<{
111
+ runtime: zod0.ZodOptional<zod0.ZodLiteral<"nodejs24">>;
112
+ }, zod_v4_core0.$strict>;
111
113
  readonly postgres: zod0.ZodObject<{
112
114
  computeSettings: zod0.ZodOptional<zod0.ZodObject<{
113
115
  autoscalingLimitMinCu: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<0.25>, zod0.ZodLiteral<0.5>, zod0.ZodLiteral<1>, zod0.ZodLiteral<2>, zod0.ZodLiteral<4>, zod0.ZodLiteral<8>]>>;
@@ -116,30 +118,29 @@ declare const schemas: {
116
118
  }, zod_v4_core0.$strict>>;
117
119
  }, zod_v4_core0.$strict>;
118
120
  readonly preview: zod0.ZodObject<{
119
- functions: zod0.ZodOptional<zod0.ZodArray<zod0.ZodObject<{
120
- slug: zod0.ZodString;
121
+ aiGateway: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodBoolean, zod0.ZodObject<{
122
+ enabled: zod0.ZodOptional<zod0.ZodBoolean>;
123
+ }, zod_v4_core0.$strict>]>>;
124
+ functions: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodObject<{
121
125
  name: zod0.ZodString;
122
126
  source: zod0.ZodString;
123
127
  env: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodString>>;
124
- runtime: zod0.ZodOptional<zod0.ZodLiteral<"nodejs24">>;
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
128
  dev: zod0.ZodOptional<zod0.ZodObject<{
127
129
  port: zod0.ZodOptional<zod0.ZodNumber>;
128
130
  portless: zod0.ZodOptional<zod0.ZodBoolean>;
129
131
  }, zod_v4_core0.$strict>>;
130
132
  }, zod_v4_core0.$strict>>>;
131
- buckets: zod0.ZodOptional<zod0.ZodArray<zod0.ZodObject<{
132
- name: zod0.ZodString;
133
+ buckets: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodObject<{
133
134
  access: zod0.ZodOptional<zod0.ZodUnion<readonly [zod0.ZodLiteral<"private">, zod0.ZodLiteral<"public_read">]>>;
134
135
  }, zod_v4_core0.$strict>>>;
135
- aiGateway: zod0.ZodOptional<zod0.ZodObject<{
136
- enabled: zod0.ZodOptional<zod0.ZodBoolean>;
137
- }, zod_v4_core0.$strict>>;
138
136
  }, zod_v4_core0.$strict>;
139
137
  readonly service: zod0.ZodObject<{
140
138
  enabled: zod0.ZodOptional<zod0.ZodBoolean>;
141
139
  }, zod_v4_core0.$strict>;
140
+ readonly serviceInput: zod0.ZodUnion<readonly [zod0.ZodBoolean, zod0.ZodObject<{
141
+ enabled: zod0.ZodOptional<zod0.ZodBoolean>;
142
+ }, zod_v4_core0.$strict>]>;
142
143
  };
143
144
  //#endregion
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 };
145
+ export { type AppliedChange, type BranchTarget, type BranchTuning, type BranchTuningFn, type BucketAccessLevel, type BucketDef, type ComputeSettings, type Config, ConfigLoadError, ConfigValidationError, type ConflictReport, type CreateBranchInput, type CreateBucketInput, type CreateProjectInput, type DeployFunctionInput, type DiffOptions, type DiffResult, ErrorCode, type FunctionDef, type FunctionDevConfig, type FunctionRuntime, type FunctionTuning, 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 PreviewInput, type PreviewTuning, PushAbortedError, PushConflictError, type PushResult, type RemotePreviewState, type RemoteServiceState, type RemoteState, type ResolvedBranchConfig, type ResolvedBucketConfig, type ResolvedFunctionConfig, type ResolvedPreviewConfig, type ServiceToggle, type ServiceToggleInput, type UpdateBranchInput, createNeonApiFromOptions, createRealNeonApi, defineConfig, diffConfig, errors, loadConfigFromFile, resolveApiKey, resolveConfig, schemas };
145
146
  //# 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAWA;;6BASH,IAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"v1.d.ts","names":[],"sources":["../src/v1.ts"],"mappings":";;;;;;;;;;;;;;;;;cA4Da;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAWA;;mDAWH,IAAA,CAAA,UAAA"}
package/dist/v1.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ConfigLoadError, ConfigValidationError, ErrorCode, MissingContextError, PlatformError, PushAbortedError, PushConflictError } from "./lib/errors.js";
2
- import { branchConfigSchema, bucketConfigSchema, computeSettingsSchema, configSchema, functionConfigSchema, postgresConfigSchema, previewConfigSchema, serviceToggleSchema } from "./lib/schema.js";
2
+ import { branchTuningSchema, bucketDefSchema, computeSettingsSchema, configInputSchema, functionDefSchema, functionTuningSchema, postgresConfigSchema, previewInputSchema, serviceToggleInputSchema, serviceToggleSchema } from "./lib/schema.js";
3
3
  import { createRealNeonApi } from "./lib/neon-api-real.js";
4
4
  import { createNeonApiFromOptions, resolveApiKey } from "./lib/auth.js";
5
5
  import { defineConfig, resolveConfig } from "./lib/define-config.js";
@@ -54,14 +54,16 @@ const errors = {
54
54
  };
55
55
  /** The zod schemas underlying `defineConfig`, grouped under product-friendly names. */
56
56
  const schemas = {
57
- branch: branchConfigSchema,
58
- bucket: bucketConfigSchema,
57
+ config: configInputSchema,
58
+ branchTuning: branchTuningSchema,
59
+ bucket: bucketDefSchema,
59
60
  computeSettings: computeSettingsSchema,
60
- config: configSchema,
61
- function: functionConfigSchema,
61
+ function: functionDefSchema,
62
+ functionTuning: functionTuningSchema,
62
63
  postgres: postgresConfigSchema,
63
- preview: previewConfigSchema,
64
- service: serviceToggleSchema
64
+ preview: previewInputSchema,
65
+ service: serviceToggleSchema,
66
+ serviceInput: serviceToggleInputSchema
65
67
  };
66
68
  //#endregion
67
69
  export { ConfigLoadError, ConfigValidationError, ErrorCode, MissingContextError, PlatformError, PushAbortedError, PushConflictError, createNeonApiFromOptions, createRealNeonApi, defineConfig, diffConfig, errors, loadConfigFromFile, resolveApiKey, resolveConfig, schemas };
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\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"}
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\tbranchTuningSchema,\n\tbucketDefSchema,\n\tcomputeSettingsSchema,\n\tconfigInputSchema,\n\tfunctionDefSchema,\n\tfunctionTuningSchema,\n\tpostgresConfigSchema,\n\tpreviewInputSchema,\n\tserviceToggleInputSchema,\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\tconfig: configInputSchema,\n\tbranchTuning: branchTuningSchema,\n\tbucket: bucketDefSchema,\n\tcomputeSettings: computeSettingsSchema,\n\tfunction: functionDefSchema,\n\tfunctionTuning: functionTuningSchema,\n\tpostgres: postgresConfigSchema,\n\tpreview: previewInputSchema,\n\tservice: serviceToggleSchema,\n\tserviceInput: serviceToggleInputSchema,\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\tBranchTarget,\n\tBranchTuning,\n\tBranchTuningFn,\n\tBucketAccessLevel,\n\tBucketDef,\n\tComputeSettings,\n\tConfig,\n\tConflictReport,\n\tFunctionDef,\n\tFunctionDevConfig,\n\tFunctionRuntime,\n\tFunctionTuning,\n\tPostgresConfig,\n\tPreviewInput,\n\tPreviewTuning,\n\tPushResult,\n\tResolvedBranchConfig,\n\tResolvedBucketConfig,\n\tResolvedFunctionConfig,\n\tResolvedPreviewConfig,\n\tServiceToggle,\n\tServiceToggleInput,\n} from \"./lib/types.js\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,MAAa,SAAS;CACrB;CACA;CACA;CACA;CACA;CACA;CACA;AACD;;AAGA,MAAa,UAAU;CACtB,QAAQ;CACR,cAAc;CACd,QAAQ;CACR,iBAAiB;CACjB,UAAU;CACV,gBAAgB;CAChB,UAAU;CACV,SAAS;CACT,SAAS;CACT,cAAc;AACf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neondatabase/config",
3
- "version": "0.2.1",
3
+ "version": "0.4.0",
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",