@neondatabase/config 1.8.6 → 1.9.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 +3 -3
- package/dist/lib/authored-services.d.ts +2 -1
- package/dist/lib/authored-services.d.ts.map +1 -1
- package/dist/lib/authored-services.js +4 -2
- package/dist/lib/authored-services.js.map +1 -1
- package/dist/lib/define-config.d.ts +6 -3
- package/dist/lib/define-config.d.ts.map +1 -1
- package/dist/lib/define-config.js +21 -2
- package/dist/lib/define-config.js.map +1 -1
- package/dist/lib/diff.d.ts +20 -1
- package/dist/lib/diff.d.ts.map +1 -1
- package/dist/lib/diff.js +67 -0
- package/dist/lib/diff.js.map +1 -1
- package/dist/lib/neon-api-real.d.ts.map +1 -1
- package/dist/lib/neon-api-real.js +81 -1
- package/dist/lib/neon-api-real.js.map +1 -1
- package/dist/lib/neon-api.d.ts +27 -1
- package/dist/lib/neon-api.d.ts.map +1 -1
- package/dist/lib/schema.d.ts +22 -8
- package/dist/lib/schema.d.ts.map +1 -1
- package/dist/lib/schema.js +19 -2
- package/dist/lib/schema.js.map +1 -1
- package/dist/lib/types.d.ts +26 -12
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/v1.d.ts +21 -9
- package/dist/v1.d.ts.map +1 -1
- package/dist/v1.js +3 -1
- package/dist/v1.js.map +1 -1
- package/package.json +2 -2
package/dist/lib/diff.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.js","names":[],"sources":["../../src/lib/diff.ts"],"sourcesContent":["import type {\n\tEnableDataApiInput,\n\tNeonBranchSnapshot,\n\tNeonBucketSnapshot,\n\tNeonCustomDomainSnapshot,\n\tNeonEndpointSnapshot,\n\tNeonFunctionSnapshot,\n\tNeonTriggerSnapshot,\n} from \"./neon-api.js\";\nimport type {\n\tBucketAccessLevel,\n\tComputeSettings,\n\tConflictReport,\n\tDataApiSettings,\n\tResolvedBranchConfig,\n\tResolvedDataApiConfig,\n\tResolvedFunctionConfig,\n\tResolvedFunctionTrigger,\n} from \"./types.js\";\n\n/**\n * A planned action to perform a single mutation against the Neon API. The diff engine\n * produces a list of these for `pushConfig` to execute (or report).\n */\nexport type PlanStep =\n\t| {\n\t\t\tkind: \"update-branch-ttl\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\texpiresAt: string | null;\n\t }\n\t| {\n\t\t\tkind: \"update-branch-protected\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tprotected: boolean;\n\t }\n\t| {\n\t\t\tkind: \"update-endpoint\";\n\t\t\tprojectId: string;\n\t\t\tbranchName: string;\n\t\t\tendpointId: string;\n\t\t\tsettings: ComputeSettings;\n\t }\n\t| {\n\t\t\tkind: \"enable-auth\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tdatabaseName?: string;\n\t }\n\t| {\n\t\t\tkind: \"enable-data-api\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tdatabaseName: string;\n\t\t\t/** Create-time auth wiring + initial settings from the policy. */\n\t\t\tinput?: EnableDataApiInput;\n\t }\n\t| {\n\t\t\tkind: \"update-data-api\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tdatabaseName: string;\n\t\t\tsettings: DataApiSettings;\n\t }\n\t| {\n\t\t\tkind: \"disable-data-api\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tdatabaseName: string;\n\t }\n\t| {\n\t\t\tkind: \"create-bucket\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tbucketName: string;\n\t\t\taccessLevel: BucketAccessLevel;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * Deploy code to a function. Planned for every desired function — deployments are\n\t\t\t * versioned and the newest becomes active, so a push ships the current source each\n\t\t\t * time. Neon has no separate \"create function\" endpoint: the first deployment to a\n\t\t\t * slug creates the function. `functionExists` therefore only drives whether this\n\t\t\t * surfaces as a `create` (first deploy) or an `update` (re-deploy).\n\t\t\t */\n\t\t\tkind: \"deploy-function\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tfn: ResolvedFunctionConfig;\n\t\t\t/** Whether the function already existed remotely when the plan was computed. */\n\t\t\tfunctionExists: boolean;\n\t }\n\t| {\n\t\t\tkind: \"create-trigger\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tfunctionSlug: string;\n\t\t\ttrigger: ResolvedFunctionTrigger;\n\t }\n\t| {\n\t\t\tkind: \"update-trigger\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\ttriggerId: string;\n\t\t\tfunctionSlug: string;\n\t\t\ttrigger: ResolvedFunctionTrigger;\n\t }\n\t| {\n\t\t\tkind: \"register-custom-domain\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tfunctionSlug: string;\n\t\t\tdomain: string;\n\t }\n\t| {\n\t\t\tkind: \"retarget-custom-domain\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tfunctionSlug: string;\n\t\t\tpreviousSlug: string;\n\t\t\tdomain: string;\n\t };\n\nexport interface RemoteServiceState {\n\tdatabaseName: string;\n\tauthEnabled: boolean;\n\tdataApiEnabled: boolean;\n\t/**\n\t * Current Data API runtime settings, when the integration is enabled and the API reports\n\t * them (SubZero only). `null`/absent means \"not reported\" — settings drift can't be\n\t * computed, so no update step is planned.\n\t */\n\tdataApiSettings?: DataApiSettings | null;\n}\n\n/**\n * Snapshot of the branch's current Preview-feature state. Absent (`undefined`) when the\n * policy has no `preview` block — `pushConfig` only fetches this when needed.\n */\nexport interface RemotePreviewState {\n\tbuckets: NeonBucketSnapshot[];\n\tfunctions: NeonFunctionSnapshot[];\n\ttriggers: NeonTriggerSnapshot[];\n\t/** Absent on pre-feature snapshots; treated as none. */\n\tcustomDomains?: NeonCustomDomainSnapshot[];\n}\n\nexport interface RemoteState {\n\tprojectId: string;\n\tbranch: NeonBranchSnapshot;\n\tendpoint?: NeonEndpointSnapshot;\n\tservices: RemoteServiceState;\n\tpreview?: RemotePreviewState;\n}\n\nexport interface DiffOptions {\n\t/**\n\t * Apply mutable drift on the selected branch as plan steps instead of conflicts.\n\t * Default: `false`.\n\t */\n\tupdateExisting: boolean;\n}\n\nexport interface DiffResult {\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}\n\n/**\n * Diff desired branch policy against the selected remote branch. Pure function.\n */\nexport function diffConfig(\n\tconfig: ResolvedBranchConfig,\n\tremote: RemoteState,\n\toptions: DiffOptions,\n): DiffResult {\n\tconst conflicts: ConflictReport[] = [];\n\tconst plan: PlanStep[] = [];\n\tdiffBranchConfig({ config, remote, options, plan, conflicts });\n\tdiffServices({ config, remote, options, plan, conflicts });\n\tdiffPreview({ config, remote, options, plan, conflicts });\n\treturn { plan, conflicts };\n}\n\n/**\n * Data API teardown requires explicit `dataApi: false` so omission remains non-destructive.\n *\n * The AI Gateway is intentionally NOT planned here: it is always available on a branch\n * (credential-gated, not per-branch provisioned), so `preview.aiGateway` produces no plan\n * step — it only drives the branch credential's `ai_gateway:invoke` scope and the gateway\n * env vars (`@neon/env`). There is nothing to create, and nothing to probe.\n *\n * Functions are always (re-)deployed: deployments are versioned and the newest becomes\n * active, so each push ships the current source. There is no separate create step — Neon\n * creates the function on its first deployment — so a single `deploy-function` step is\n * emitted per desired function, carrying `functionExists` so the apply can report it as a\n * create (first deploy) or an update (re-deploy).\n */\nfunction diffPreview(args: {\n\tconfig: ResolvedBranchConfig;\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}): void {\n\tconst { config, remote, options, plan, conflicts } = args;\n\tconst preview = config.preview;\n\tif (!preview) return;\n\t// `remote.preview` is only fetched when the policy has a preview block; treat a missing\n\t// snapshot as \"nothing exists yet\" so the diff is still well-defined.\n\tconst state: RemotePreviewState = remote.preview ?? {\n\t\tbuckets: [],\n\t\tfunctions: [],\n\t\ttriggers: [],\n\t};\n\tconst customDomains = state.customDomains ?? [];\n\n\tfor (const bucket of preview.buckets) {\n\t\tif (state.buckets.some((b) => b.name === bucket.name)) continue;\n\t\tplan.push({\n\t\t\tkind: \"create-bucket\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t\tbucketName: bucket.name,\n\t\t\taccessLevel: bucket.access,\n\t\t});\n\t}\n\n\tfor (const fn of preview.functions) {\n\t\tconst exists = state.functions.some((f) => f.slug === fn.slug);\n\t\tplan.push({\n\t\t\tkind: \"deploy-function\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t\tfn,\n\t\t\tfunctionExists: exists,\n\t\t});\n\t\tdiffFunctionCustomDomains({\n\t\t\tfn,\n\t\t\tcustomDomains,\n\t\t\tremote,\n\t\t\toptions,\n\t\t\tplan,\n\t\t\tconflicts,\n\t\t});\n\t}\n\n\tfor (const trigger of config.triggers ?? []) {\n\t\tconst remoteTrigger = state.triggers.find(\n\t\t\t(t) => t.name === trigger.name,\n\t\t);\n\t\tif (!remoteTrigger) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"create-trigger\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t\tfunctionSlug: trigger.functionSlug,\n\t\t\t\ttrigger,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (remoteTrigger.type !== trigger.type) {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: trigger.name,\n\t\t\t\tfield: \"trigger\",\n\t\t\t\tcurrent: remoteTrigger.type,\n\t\t\t\tdesired: trigger.type,\n\t\t\t\treason: `trigger \"${trigger.name}\" exists as type ${remoteTrigger.type}; neon.ts declares ${trigger.type}. Delete the remote trigger with \\`neon triggers delete\\` and apply again.`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (triggerNeedsUpdate(trigger, remoteTrigger)) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"update-trigger\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t\ttriggerId: remoteTrigger.triggerId,\n\t\t\t\tfunctionSlug: trigger.functionSlug,\n\t\t\t\ttrigger,\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction triggerNeedsUpdate(\n\tdesired: ResolvedFunctionTrigger,\n\tremote: NeonTriggerSnapshot,\n): boolean {\n\tif (remote.functionSlug !== desired.functionSlug) return true;\n\tif (remote.functionPath !== desired.functionPath) return true;\n\tif (remote.enabled !== desired.enabled) return true;\n\tif (desired.type === \"schedule\") {\n\t\treturn remote.type !== \"schedule\" || remote.cron !== desired.cron;\n\t}\n\treturn (\n\t\tremote.type !== \"storage_object_created\" ||\n\t\tremote.bucketName !== desired.bucketName ||\n\t\tremote.prefix !== desired.prefix\n\t);\n}\n\nconst FUNCTION_CUSTOM_DOMAIN_ENTITY = \"function\";\n\nfunction diffFunctionCustomDomains(args: {\n\tfn: ResolvedFunctionConfig;\n\tcustomDomains: NeonCustomDomainSnapshot[];\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}): void {\n\tconst { fn, customDomains, remote, options, plan, conflicts } = args;\n\tfor (const domain of fn.customDomains ?? []) {\n\t\tconst existing = customDomains.find((d) => d.domain === domain);\n\t\tif (!existing) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"register-custom-domain\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t\tfunctionSlug: fn.slug,\n\t\t\t\tdomain,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (existing.entityType !== FUNCTION_CUSTOM_DOMAIN_ENTITY) {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: remote.branch.name,\n\t\t\t\tfield: \"customDomain\",\n\t\t\t\tcurrent: {\n\t\t\t\t\tentityType: existing.entityType,\n\t\t\t\t\tentityId: existing.entityId,\n\t\t\t\t},\n\t\t\t\tdesired: {\n\t\t\t\t\tentityType: FUNCTION_CUSTOM_DOMAIN_ENTITY,\n\t\t\t\t\tentityId: fn.slug,\n\t\t\t\t},\n\t\t\t\treason: `custom domain \"${domain}\" is registered to entity type \"${existing.entityType}\", which neon.ts cannot retarget. Delete it with \\`neon function domains delete\\` or stop declaring it.`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (existing.entityId === fn.slug) continue;\n\t\tif (options.updateExisting) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"retarget-custom-domain\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t\tfunctionSlug: fn.slug,\n\t\t\t\tpreviousSlug: existing.entityId,\n\t\t\t\tdomain,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconflicts.push({\n\t\t\tkind: \"branch\",\n\t\t\tidentifier: remote.branch.name,\n\t\t\tfield: \"customDomain\",\n\t\t\tcurrent: existing.entityId,\n\t\t\tdesired: fn.slug,\n\t\t\treason: `custom domain \"${domain}\" is registered to function \"${existing.entityId}\". Pass \\`updateExisting: true\\` (SDK) or \\`--update-existing\\` (CLI) to retarget it to \"${fn.slug}\".`,\n\t\t});\n\t}\n}\n\n/**\n * Plan branch-scoped integrations. Enabling is additive (no existing resource to override).\n * The Data API is the one integration that also has a reconcilable *update*: its runtime\n * `settings` can drift once enabled, and reconciling them is an override (gated on\n * `updateExisting`, like compute/TTL/protected). The auth provider / JWKS wiring is fixed at\n * enable time, so it is never updated here. Disabling stays explicit/manual (destructive).\n */\nfunction diffServices(args: {\n\tconfig: ResolvedBranchConfig;\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}): void {\n\tconst { config, remote, options, plan, conflicts } = args;\n\tconst state = remote.services;\n\tif (config.authEnabled && !state.authEnabled) {\n\t\tconst step: PlanStep = {\n\t\t\tkind: \"enable-auth\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t};\n\t\tif (state.databaseName) step.databaseName = state.databaseName;\n\t\tplan.push(step);\n\t}\n\tconst dataApiPolicy =\n\t\tconfig.dataApiPolicy ?? (config.dataApiEnabled ? \"enabled\" : \"omitted\");\n\tif (dataApiPolicy === \"enabled\") {\n\t\tdiffDataApi({ config, remote, options, plan, conflicts });\n\t} else if (dataApiPolicy === \"disabled\" && state.dataApiEnabled) {\n\t\tif (options.updateExisting) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"disable-data-api\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t\tdatabaseName: state.databaseName,\n\t\t\t});\n\t\t} else {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: remote.branch.name,\n\t\t\t\tfield: \"dataApi\",\n\t\t\t\tcurrent: true,\n\t\t\t\tdesired: false,\n\t\t\t\treason: \"Existing Data API would be deleted. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t\t});\n\t\t}\n\t}\n}\n\n/**\n * Plan the Data API: a first-time **enable** (carrying the create-time auth wiring +\n * settings), or — when it already exists — a **settings update** if the policy's settings\n * drift from the remote. The update is an override: applied as a plan step under\n * `updateExisting`, otherwise reported as a conflict.\n */\nfunction diffDataApi(args: {\n\tconfig: ResolvedBranchConfig;\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}): void {\n\tconst { config, remote, options, plan, conflicts } = args;\n\tconst state = remote.services;\n\tconst desired = config.dataApi;\n\n\tif (!state.dataApiEnabled) {\n\t\tconst step: PlanStep = {\n\t\t\tkind: \"enable-data-api\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t\tdatabaseName: state.databaseName,\n\t\t};\n\t\tconst input = desired ? enableInputFromResolved(desired) : undefined;\n\t\tif (input) step.input = input;\n\t\tplan.push(step);\n\t\treturn;\n\t}\n\n\t// Already enabled: the only reconcilable change is its runtime settings.\n\tconst desiredSettings = desired?.settings;\n\tif (!desiredSettings) return;\n\tif (!dataApiSettingsDiffer(desiredSettings, state.dataApiSettings)) return;\n\n\tif (options.updateExisting) {\n\t\tplan.push({\n\t\t\tkind: \"update-data-api\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t\tdatabaseName: state.databaseName,\n\t\t\tsettings: desiredSettings,\n\t\t});\n\t} else {\n\t\tconflicts.push({\n\t\t\tkind: \"branch\",\n\t\t\tidentifier: remote.branch.name,\n\t\t\tfield: \"dataApi.settings\",\n\t\t\tcurrent: state.dataApiSettings ?? undefined,\n\t\t\tdesired: desiredSettings,\n\t\t\treason: \"Existing Data API has different settings. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t});\n\t}\n}\n\n/** Build the create-time {@link EnableDataApiInput} from a resolved Data API config. */\nfunction enableInputFromResolved(\n\tresolved: ResolvedDataApiConfig,\n): EnableDataApiInput {\n\tconst input: EnableDataApiInput = { authProvider: resolved.authProvider };\n\tif (resolved.jwksUrl !== undefined) input.jwksUrl = resolved.jwksUrl;\n\tif (resolved.providerName !== undefined)\n\t\tinput.providerName = resolved.providerName;\n\tif (resolved.jwtAudience !== undefined)\n\t\tinput.jwtAudience = resolved.jwtAudience;\n\tif (resolved.settings) input.settings = resolved.settings;\n\treturn input;\n}\n\n/** The camelCase keys of {@link DataApiSettings}, used to compare desired vs remote settings. */\nconst DATA_API_SETTING_KEYS = [\n\t\"dbAggregatesEnabled\",\n\t\"dbAnonRole\",\n\t\"dbExtraSearchPath\",\n\t\"dbMaxRows\",\n\t\"dbSchemas\",\n\t\"jwtRoleClaimKey\",\n\t\"jwtCacheMaxLifetime\",\n\t\"openapiMode\",\n\t\"serverCorsAllowedOrigins\",\n\t\"serverTimingEnabled\",\n] as const satisfies ReadonlyArray<keyof DataApiSettings>;\n\n/**\n * Whether the policy's Data API `settings` differ from the remote ones. Only the keys the\n * policy actually set are compared (so unset fields never count as drift). When the remote\n * settings are not reported (`null`/absent — non-SubZero), drift can't be computed and this\n * returns `false` so no spurious update is planned.\n */\nfunction dataApiSettingsDiffer(\n\tdesired: DataApiSettings,\n\tcurrent: DataApiSettings | null | undefined,\n): boolean {\n\tif (!current) return false;\n\tfor (const key of DATA_API_SETTING_KEYS) {\n\t\tif (desired[key] === undefined) continue;\n\t\tif (JSON.stringify(desired[key]) !== JSON.stringify(current[key])) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\ninterface BranchConfigArgs {\n\tconfig: ResolvedBranchConfig;\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}\n\nfunction diffBranchConfig(args: BranchConfigArgs): void {\n\tconst { config, remote, options, plan, conflicts } = args;\n\tconst branchName = remote.branch.name;\n\tconst computeSettings = config.postgres?.computeSettings;\n\n\tif (computeSettings) {\n\t\tconst endpoint = remote.endpoint;\n\t\tif (!endpoint) {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: branchName,\n\t\t\t\tfield: \"endpoint\",\n\t\t\t\tcurrent: undefined,\n\t\t\t\tdesired: computeSettings,\n\t\t\t\treason: \"Branch has no read-write endpoint; cannot apply compute settings.\",\n\t\t\t});\n\t\t} else {\n\t\t\tconst drift = computeDriftBetween(computeSettings, endpoint);\n\t\t\tif (drift) {\n\t\t\t\tif (options.updateExisting) {\n\t\t\t\t\tplan.push({\n\t\t\t\t\t\tkind: \"update-endpoint\",\n\t\t\t\t\t\tprojectId: remote.projectId,\n\t\t\t\t\t\tbranchName,\n\t\t\t\t\t\tendpointId: endpoint.id,\n\t\t\t\t\t\tsettings: computeSettings,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tconflicts.push({\n\t\t\t\t\t\tkind: \"branch\",\n\t\t\t\t\t\tidentifier: branchName,\n\t\t\t\t\t\tfield: \"computeSettings\",\n\t\t\t\t\t\tcurrent: drift.current,\n\t\t\t\t\t\tdesired: drift.desired,\n\t\t\t\t\t\treason: \"Existing branch has different compute settings. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (\n\t\tconfig.protected !== undefined &&\n\t\tconfig.protected !== remote.branch.protected\n\t) {\n\t\tif (options.updateExisting) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"update-branch-protected\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName,\n\t\t\t\tprotected: config.protected,\n\t\t\t});\n\t\t} else {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: branchName,\n\t\t\t\tfield: \"protected\",\n\t\t\t\tcurrent: remote.branch.protected,\n\t\t\t\tdesired: config.protected,\n\t\t\t\treason: \"Existing branch has a different `protected` flag. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (config.ttlSeconds !== undefined) {\n\t\tconst current = remote.branch.expiresAt\n\t\t\t? Math.max(\n\t\t\t\t\t0,\n\t\t\t\t\tMath.round(\n\t\t\t\t\t\t(Date.parse(remote.branch.expiresAt) - Date.now()) /\n\t\t\t\t\t\t\t1000,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t: undefined;\n\t\tif (\n\t\t\tcurrent === undefined ||\n\t\t\tMath.abs(current - config.ttlSeconds) > 30\n\t\t) {\n\t\t\tconst expiresAt = new Date(\n\t\t\t\tDate.now() + config.ttlSeconds * 1000,\n\t\t\t).toISOString();\n\t\t\tif (options.updateExisting) {\n\t\t\t\tplan.push({\n\t\t\t\t\tkind: \"update-branch-ttl\",\n\t\t\t\t\tprojectId: remote.projectId,\n\t\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\t\tbranchName,\n\t\t\t\t\texpiresAt,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconflicts.push({\n\t\t\t\t\tkind: \"branch\",\n\t\t\t\t\tidentifier: branchName,\n\t\t\t\t\tfield: \"ttl\",\n\t\t\t\t\tcurrent: remote.branch.expiresAt,\n\t\t\t\t\tdesired: expiresAt,\n\t\t\t\t\treason: \"Existing branch has a different TTL. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction computeDriftBetween(\n\tdesired: ComputeSettings,\n\tendpoint: NeonEndpointSnapshot,\n): {\n\tcurrent: Partial<ComputeSettings>;\n\tdesired: Partial<ComputeSettings>;\n} | null {\n\tconst currentDrift: Partial<ComputeSettings> = {};\n\tconst desiredDrift: Partial<ComputeSettings> = {};\n\tlet drift = false;\n\n\tif (\n\t\tdesired.autoscalingLimitMinCu !== undefined &&\n\t\tdesired.autoscalingLimitMinCu !== endpoint.autoscalingLimitMinCu\n\t) {\n\t\tcurrentDrift.autoscalingLimitMinCu = endpoint.autoscalingLimitMinCu;\n\t\tdesiredDrift.autoscalingLimitMinCu = desired.autoscalingLimitMinCu;\n\t\tdrift = true;\n\t}\n\tif (\n\t\tdesired.autoscalingLimitMaxCu !== undefined &&\n\t\tdesired.autoscalingLimitMaxCu !== endpoint.autoscalingLimitMaxCu\n\t) {\n\t\tcurrentDrift.autoscalingLimitMaxCu = endpoint.autoscalingLimitMaxCu;\n\t\tdesiredDrift.autoscalingLimitMaxCu = desired.autoscalingLimitMaxCu;\n\t\tdrift = true;\n\t}\n\tif (\n\t\tdesired.suspendTimeout !== undefined &&\n\t\tdesired.suspendTimeout !== endpoint.suspendTimeout\n\t) {\n\t\tcurrentDrift.suspendTimeout = endpoint.suspendTimeout;\n\t\tdesiredDrift.suspendTimeout = desired.suspendTimeout;\n\t\tdrift = true;\n\t}\n\treturn drift ? { current: currentDrift, desired: desiredDrift } : null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"diff.js","names":[],"sources":["../../src/lib/diff.ts"],"sourcesContent":["import type {\n\tConfigureRealtimeInput,\n\tEnableDataApiInput,\n\tNeonBranchSnapshot,\n\tNeonBucketSnapshot,\n\tNeonCustomDomainSnapshot,\n\tNeonEndpointSnapshot,\n\tNeonFunctionSnapshot,\n\tNeonRealtimeSnapshot,\n\tNeonTriggerSnapshot,\n} from \"./neon-api.js\";\nimport type {\n\tBucketAccessLevel,\n\tComputeSettings,\n\tConflictReport,\n\tDataApiSettings,\n\tResolvedBranchConfig,\n\tResolvedDataApiConfig,\n\tResolvedFunctionConfig,\n\tResolvedFunctionTrigger,\n} from \"./types.js\";\n\n/**\n * A planned action to perform a single mutation against the Neon API. The diff engine\n * produces a list of these for `pushConfig` to execute (or report).\n */\nexport type PlanStep =\n\t| {\n\t\t\tkind: \"enable-realtime\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tinput?: ConfigureRealtimeInput;\n\t }\n\t| {\n\t\t\tkind: \"update-realtime\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tinput: Required<ConfigureRealtimeInput>;\n\t }\n\t| {\n\t\t\tkind: \"disable-realtime\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t }\n\t| {\n\t\t\tkind: \"update-branch-ttl\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\texpiresAt: string | null;\n\t }\n\t| {\n\t\t\tkind: \"update-branch-protected\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tprotected: boolean;\n\t }\n\t| {\n\t\t\tkind: \"update-endpoint\";\n\t\t\tprojectId: string;\n\t\t\tbranchName: string;\n\t\t\tendpointId: string;\n\t\t\tsettings: ComputeSettings;\n\t }\n\t| {\n\t\t\tkind: \"enable-auth\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tdatabaseName?: string;\n\t }\n\t| {\n\t\t\tkind: \"enable-data-api\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tdatabaseName: string;\n\t\t\t/** Create-time auth wiring + initial settings from the policy. */\n\t\t\tinput?: EnableDataApiInput;\n\t }\n\t| {\n\t\t\tkind: \"update-data-api\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tdatabaseName: string;\n\t\t\tsettings: DataApiSettings;\n\t }\n\t| {\n\t\t\tkind: \"disable-data-api\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tdatabaseName: string;\n\t }\n\t| {\n\t\t\tkind: \"create-bucket\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tbucketName: string;\n\t\t\taccessLevel: BucketAccessLevel;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * Deploy code to a function. Planned for every desired function — deployments are\n\t\t\t * versioned and the newest becomes active, so a push ships the current source each\n\t\t\t * time. Neon has no separate \"create function\" endpoint: the first deployment to a\n\t\t\t * slug creates the function. `functionExists` therefore only drives whether this\n\t\t\t * surfaces as a `create` (first deploy) or an `update` (re-deploy).\n\t\t\t */\n\t\t\tkind: \"deploy-function\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tfn: ResolvedFunctionConfig;\n\t\t\t/** Whether the function already existed remotely when the plan was computed. */\n\t\t\tfunctionExists: boolean;\n\t }\n\t| {\n\t\t\tkind: \"create-trigger\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tfunctionSlug: string;\n\t\t\ttrigger: ResolvedFunctionTrigger;\n\t }\n\t| {\n\t\t\tkind: \"update-trigger\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\ttriggerId: string;\n\t\t\tfunctionSlug: string;\n\t\t\ttrigger: ResolvedFunctionTrigger;\n\t }\n\t| {\n\t\t\tkind: \"register-custom-domain\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tfunctionSlug: string;\n\t\t\tdomain: string;\n\t }\n\t| {\n\t\t\tkind: \"retarget-custom-domain\";\n\t\t\tprojectId: string;\n\t\t\tbranchId: string;\n\t\t\tbranchName: string;\n\t\t\tfunctionSlug: string;\n\t\t\tpreviousSlug: string;\n\t\t\tdomain: string;\n\t };\n\nexport interface RemoteServiceState {\n\tdatabaseName: string;\n\tauthEnabled: boolean;\n\tdataApiEnabled: boolean;\n\t/**\n\t * Current Data API runtime settings, when the integration is enabled and the API reports\n\t * them (SubZero only). `null`/absent means \"not reported\" — settings drift can't be\n\t * computed, so no update step is planned.\n\t */\n\tdataApiSettings?: DataApiSettings | null;\n}\n\n/**\n * Snapshot of the branch's current Preview-feature state. Absent (`undefined`) when the\n * policy has no `preview` block — `pushConfig` only fetches this when needed.\n */\nexport interface RemotePreviewState {\n\tbuckets: NeonBucketSnapshot[];\n\tfunctions: NeonFunctionSnapshot[];\n\ttriggers: NeonTriggerSnapshot[];\n\t/** Absent on pre-feature snapshots; treated as none. */\n\tcustomDomains?: NeonCustomDomainSnapshot[];\n}\n\nexport interface RemoteState {\n\tprojectId: string;\n\tbranch: NeonBranchSnapshot;\n\tendpoint?: NeonEndpointSnapshot;\n\t/** Present when the policy manages Realtime. */\n\trealtime?: NeonRealtimeSnapshot;\n\tservices: RemoteServiceState;\n\tpreview?: RemotePreviewState;\n}\n\nexport interface DiffOptions {\n\t/**\n\t * Apply mutable drift on the selected branch as plan steps instead of conflicts.\n\t * Default: `false`.\n\t */\n\tupdateExisting: boolean;\n}\n\nexport interface DiffResult {\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}\n\n/**\n * Diff desired branch policy against the selected remote branch. Pure function.\n */\nexport function diffConfig(\n\tconfig: ResolvedBranchConfig,\n\tremote: RemoteState,\n\toptions: DiffOptions,\n): DiffResult {\n\tconst conflicts: ConflictReport[] = [];\n\tconst plan: PlanStep[] = [];\n\tdiffBranchConfig({ config, remote, options, plan, conflicts });\n\tdiffRealtime({ config, remote, options, plan, conflicts });\n\tdiffServices({ config, remote, options, plan, conflicts });\n\tdiffPreview({ config, remote, options, plan, conflicts });\n\treturn { plan, conflicts };\n}\n\nfunction diffRealtime(args: {\n\tconfig: ResolvedBranchConfig;\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}): void {\n\tconst { config, remote, options, plan, conflicts } = args;\n\tconst policy = config.realtimePolicy ?? \"omitted\";\n\tif (policy === \"omitted\") return;\n\tconst state = remote.realtime ?? { enabled: false, pending: false };\n\n\tif (policy === \"disabled\") {\n\t\tif (!state.enabled) return;\n\t\tif (options.updateExisting) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"disable-realtime\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t});\n\t\t} else {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: remote.branch.name,\n\t\t\t\tfield: \"preview.realtime\",\n\t\t\t\tcurrent: true,\n\t\t\t\tdesired: false,\n\t\t\t\treason: \"Existing Realtime would be disabled. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t\t});\n\t\t}\n\t\treturn;\n\t}\n\n\tconst allowedOrigins = config.realtime?.allowedOrigins;\n\tif (!state.enabled) {\n\t\tplan.push({\n\t\t\tkind: \"enable-realtime\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t\t...(allowedOrigins !== undefined\n\t\t\t\t? { input: { allowedOrigins: [...allowedOrigins] } }\n\t\t\t\t: {}),\n\t\t});\n\t\treturn;\n\t}\n\n\tif (\n\t\tallowedOrigins === undefined ||\n\t\toriginsEqual(allowedOrigins, state.allowedOrigins)\n\t) {\n\t\treturn;\n\t}\n\tif (options.updateExisting) {\n\t\tplan.push({\n\t\t\tkind: \"update-realtime\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t\tinput: { allowedOrigins: [...allowedOrigins] },\n\t\t});\n\t} else {\n\t\tconflicts.push({\n\t\t\tkind: \"branch\",\n\t\t\tidentifier: remote.branch.name,\n\t\t\tfield: \"preview.realtime.allowedOrigins\",\n\t\t\tcurrent: state.allowedOrigins,\n\t\t\tdesired: allowedOrigins,\n\t\t\treason: \"Existing Realtime has different allowed origins. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t});\n\t}\n}\n\nfunction originsEqual(\n\tdesired: readonly string[],\n\tcurrent: readonly string[] | undefined,\n): boolean {\n\tif (current === undefined || desired.length !== current.length)\n\t\treturn false;\n\tconst left = [...desired].sort();\n\tconst right = [...current].sort();\n\treturn left.every((origin, index) => origin === right[index]);\n}\n\n/**\n * Data API teardown requires explicit `dataApi: false` so omission remains non-destructive.\n *\n * The AI Gateway is intentionally NOT planned here: it is always available on a branch\n * (credential-gated, not per-branch provisioned), so `preview.aiGateway` produces no plan\n * step — it only drives the branch credential's `ai_gateway:invoke` scope and the gateway\n * env vars (`@neon/env`). There is nothing to create, and nothing to probe.\n *\n * Functions are always (re-)deployed: deployments are versioned and the newest becomes\n * active, so each push ships the current source. There is no separate create step — Neon\n * creates the function on its first deployment — so a single `deploy-function` step is\n * emitted per desired function, carrying `functionExists` so the apply can report it as a\n * create (first deploy) or an update (re-deploy).\n */\nfunction diffPreview(args: {\n\tconfig: ResolvedBranchConfig;\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}): void {\n\tconst { config, remote, options, plan, conflicts } = args;\n\tconst preview = config.preview;\n\tif (!preview) return;\n\t// `remote.preview` is only fetched when the policy has a preview block; treat a missing\n\t// snapshot as \"nothing exists yet\" so the diff is still well-defined.\n\tconst state: RemotePreviewState = remote.preview ?? {\n\t\tbuckets: [],\n\t\tfunctions: [],\n\t\ttriggers: [],\n\t};\n\tconst customDomains = state.customDomains ?? [];\n\n\tfor (const bucket of preview.buckets) {\n\t\tif (state.buckets.some((b) => b.name === bucket.name)) continue;\n\t\tplan.push({\n\t\t\tkind: \"create-bucket\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t\tbucketName: bucket.name,\n\t\t\taccessLevel: bucket.access,\n\t\t});\n\t}\n\n\tfor (const fn of preview.functions) {\n\t\tconst exists = state.functions.some((f) => f.slug === fn.slug);\n\t\tplan.push({\n\t\t\tkind: \"deploy-function\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t\tfn,\n\t\t\tfunctionExists: exists,\n\t\t});\n\t\tdiffFunctionCustomDomains({\n\t\t\tfn,\n\t\t\tcustomDomains,\n\t\t\tremote,\n\t\t\toptions,\n\t\t\tplan,\n\t\t\tconflicts,\n\t\t});\n\t}\n\n\tfor (const trigger of config.triggers ?? []) {\n\t\tconst remoteTrigger = state.triggers.find(\n\t\t\t(t) => t.name === trigger.name,\n\t\t);\n\t\tif (!remoteTrigger) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"create-trigger\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t\tfunctionSlug: trigger.functionSlug,\n\t\t\t\ttrigger,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (remoteTrigger.type !== trigger.type) {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: trigger.name,\n\t\t\t\tfield: \"trigger\",\n\t\t\t\tcurrent: remoteTrigger.type,\n\t\t\t\tdesired: trigger.type,\n\t\t\t\treason: `trigger \"${trigger.name}\" exists as type ${remoteTrigger.type}; neon.ts declares ${trigger.type}. Delete the remote trigger with \\`neon triggers delete\\` and apply again.`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (triggerNeedsUpdate(trigger, remoteTrigger)) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"update-trigger\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t\ttriggerId: remoteTrigger.triggerId,\n\t\t\t\tfunctionSlug: trigger.functionSlug,\n\t\t\t\ttrigger,\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction triggerNeedsUpdate(\n\tdesired: ResolvedFunctionTrigger,\n\tremote: NeonTriggerSnapshot,\n): boolean {\n\tif (remote.functionSlug !== desired.functionSlug) return true;\n\tif (remote.functionPath !== desired.functionPath) return true;\n\tif (remote.enabled !== desired.enabled) return true;\n\tif (desired.type === \"schedule\") {\n\t\treturn remote.type !== \"schedule\" || remote.cron !== desired.cron;\n\t}\n\treturn (\n\t\tremote.type !== \"storage_object_created\" ||\n\t\tremote.bucketName !== desired.bucketName ||\n\t\tremote.prefix !== desired.prefix\n\t);\n}\n\nconst FUNCTION_CUSTOM_DOMAIN_ENTITY = \"function\";\n\nfunction diffFunctionCustomDomains(args: {\n\tfn: ResolvedFunctionConfig;\n\tcustomDomains: NeonCustomDomainSnapshot[];\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}): void {\n\tconst { fn, customDomains, remote, options, plan, conflicts } = args;\n\tfor (const domain of fn.customDomains ?? []) {\n\t\tconst existing = customDomains.find((d) => d.domain === domain);\n\t\tif (!existing) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"register-custom-domain\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t\tfunctionSlug: fn.slug,\n\t\t\t\tdomain,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (existing.entityType !== FUNCTION_CUSTOM_DOMAIN_ENTITY) {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: remote.branch.name,\n\t\t\t\tfield: \"customDomain\",\n\t\t\t\tcurrent: {\n\t\t\t\t\tentityType: existing.entityType,\n\t\t\t\t\tentityId: existing.entityId,\n\t\t\t\t},\n\t\t\t\tdesired: {\n\t\t\t\t\tentityType: FUNCTION_CUSTOM_DOMAIN_ENTITY,\n\t\t\t\t\tentityId: fn.slug,\n\t\t\t\t},\n\t\t\t\treason: `custom domain \"${domain}\" is registered to entity type \"${existing.entityType}\", which neon.ts cannot retarget. Delete it with \\`neon function domains delete\\` or stop declaring it.`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (existing.entityId === fn.slug) continue;\n\t\tif (options.updateExisting) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"retarget-custom-domain\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t\tfunctionSlug: fn.slug,\n\t\t\t\tpreviousSlug: existing.entityId,\n\t\t\t\tdomain,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tconflicts.push({\n\t\t\tkind: \"branch\",\n\t\t\tidentifier: remote.branch.name,\n\t\t\tfield: \"customDomain\",\n\t\t\tcurrent: existing.entityId,\n\t\t\tdesired: fn.slug,\n\t\t\treason: `custom domain \"${domain}\" is registered to function \"${existing.entityId}\". Pass \\`updateExisting: true\\` (SDK) or \\`--update-existing\\` (CLI) to retarget it to \"${fn.slug}\".`,\n\t\t});\n\t}\n}\n\n/**\n * Plan branch-scoped integrations. Enabling is additive (no existing resource to override).\n * The Data API is the one integration that also has a reconcilable *update*: its runtime\n * `settings` can drift once enabled, and reconciling them is an override (gated on\n * `updateExisting`, like compute/TTL/protected). The auth provider / JWKS wiring is fixed at\n * enable time, so it is never updated here. Disabling stays explicit/manual (destructive).\n */\nfunction diffServices(args: {\n\tconfig: ResolvedBranchConfig;\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}): void {\n\tconst { config, remote, options, plan, conflicts } = args;\n\tconst state = remote.services;\n\tif (config.authEnabled && !state.authEnabled) {\n\t\tconst step: PlanStep = {\n\t\t\tkind: \"enable-auth\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t};\n\t\tif (state.databaseName) step.databaseName = state.databaseName;\n\t\tplan.push(step);\n\t}\n\tconst dataApiPolicy =\n\t\tconfig.dataApiPolicy ?? (config.dataApiEnabled ? \"enabled\" : \"omitted\");\n\tif (dataApiPolicy === \"enabled\") {\n\t\tdiffDataApi({ config, remote, options, plan, conflicts });\n\t} else if (dataApiPolicy === \"disabled\" && state.dataApiEnabled) {\n\t\tif (options.updateExisting) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"disable-data-api\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName: remote.branch.name,\n\t\t\t\tdatabaseName: state.databaseName,\n\t\t\t});\n\t\t} else {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: remote.branch.name,\n\t\t\t\tfield: \"dataApi\",\n\t\t\t\tcurrent: true,\n\t\t\t\tdesired: false,\n\t\t\t\treason: \"Existing Data API would be deleted. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t\t});\n\t\t}\n\t}\n}\n\n/**\n * Plan the Data API: a first-time **enable** (carrying the create-time auth wiring +\n * settings), or — when it already exists — a **settings update** if the policy's settings\n * drift from the remote. The update is an override: applied as a plan step under\n * `updateExisting`, otherwise reported as a conflict.\n */\nfunction diffDataApi(args: {\n\tconfig: ResolvedBranchConfig;\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}): void {\n\tconst { config, remote, options, plan, conflicts } = args;\n\tconst state = remote.services;\n\tconst desired = config.dataApi;\n\n\tif (!state.dataApiEnabled) {\n\t\tconst step: PlanStep = {\n\t\t\tkind: \"enable-data-api\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t\tdatabaseName: state.databaseName,\n\t\t};\n\t\tconst input = desired ? enableInputFromResolved(desired) : undefined;\n\t\tif (input) step.input = input;\n\t\tplan.push(step);\n\t\treturn;\n\t}\n\n\t// Already enabled: the only reconcilable change is its runtime settings.\n\tconst desiredSettings = desired?.settings;\n\tif (!desiredSettings) return;\n\tif (!dataApiSettingsDiffer(desiredSettings, state.dataApiSettings)) return;\n\n\tif (options.updateExisting) {\n\t\tplan.push({\n\t\t\tkind: \"update-data-api\",\n\t\t\tprojectId: remote.projectId,\n\t\t\tbranchId: remote.branch.id,\n\t\t\tbranchName: remote.branch.name,\n\t\t\tdatabaseName: state.databaseName,\n\t\t\tsettings: desiredSettings,\n\t\t});\n\t} else {\n\t\tconflicts.push({\n\t\t\tkind: \"branch\",\n\t\t\tidentifier: remote.branch.name,\n\t\t\tfield: \"dataApi.settings\",\n\t\t\tcurrent: state.dataApiSettings ?? undefined,\n\t\t\tdesired: desiredSettings,\n\t\t\treason: \"Existing Data API has different settings. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t});\n\t}\n}\n\n/** Build the create-time {@link EnableDataApiInput} from a resolved Data API config. */\nfunction enableInputFromResolved(\n\tresolved: ResolvedDataApiConfig,\n): EnableDataApiInput {\n\tconst input: EnableDataApiInput = { authProvider: resolved.authProvider };\n\tif (resolved.jwksUrl !== undefined) input.jwksUrl = resolved.jwksUrl;\n\tif (resolved.providerName !== undefined)\n\t\tinput.providerName = resolved.providerName;\n\tif (resolved.jwtAudience !== undefined)\n\t\tinput.jwtAudience = resolved.jwtAudience;\n\tif (resolved.settings) input.settings = resolved.settings;\n\treturn input;\n}\n\n/** The camelCase keys of {@link DataApiSettings}, used to compare desired vs remote settings. */\nconst DATA_API_SETTING_KEYS = [\n\t\"dbAggregatesEnabled\",\n\t\"dbAnonRole\",\n\t\"dbExtraSearchPath\",\n\t\"dbMaxRows\",\n\t\"dbSchemas\",\n\t\"jwtRoleClaimKey\",\n\t\"jwtCacheMaxLifetime\",\n\t\"openapiMode\",\n\t\"serverCorsAllowedOrigins\",\n\t\"serverTimingEnabled\",\n] as const satisfies ReadonlyArray<keyof DataApiSettings>;\n\n/**\n * Whether the policy's Data API `settings` differ from the remote ones. Only the keys the\n * policy actually set are compared (so unset fields never count as drift). When the remote\n * settings are not reported (`null`/absent — non-SubZero), drift can't be computed and this\n * returns `false` so no spurious update is planned.\n */\nfunction dataApiSettingsDiffer(\n\tdesired: DataApiSettings,\n\tcurrent: DataApiSettings | null | undefined,\n): boolean {\n\tif (!current) return false;\n\tfor (const key of DATA_API_SETTING_KEYS) {\n\t\tif (desired[key] === undefined) continue;\n\t\tif (JSON.stringify(desired[key]) !== JSON.stringify(current[key])) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\ninterface BranchConfigArgs {\n\tconfig: ResolvedBranchConfig;\n\tremote: RemoteState;\n\toptions: DiffOptions;\n\tplan: PlanStep[];\n\tconflicts: ConflictReport[];\n}\n\nfunction diffBranchConfig(args: BranchConfigArgs): void {\n\tconst { config, remote, options, plan, conflicts } = args;\n\tconst branchName = remote.branch.name;\n\tconst computeSettings = config.postgres?.computeSettings;\n\n\tif (computeSettings) {\n\t\tconst endpoint = remote.endpoint;\n\t\tif (!endpoint) {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: branchName,\n\t\t\t\tfield: \"endpoint\",\n\t\t\t\tcurrent: undefined,\n\t\t\t\tdesired: computeSettings,\n\t\t\t\treason: \"Branch has no read-write endpoint; cannot apply compute settings.\",\n\t\t\t});\n\t\t} else {\n\t\t\tconst drift = computeDriftBetween(computeSettings, endpoint);\n\t\t\tif (drift) {\n\t\t\t\tif (options.updateExisting) {\n\t\t\t\t\tplan.push({\n\t\t\t\t\t\tkind: \"update-endpoint\",\n\t\t\t\t\t\tprojectId: remote.projectId,\n\t\t\t\t\t\tbranchName,\n\t\t\t\t\t\tendpointId: endpoint.id,\n\t\t\t\t\t\tsettings: computeSettings,\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tconflicts.push({\n\t\t\t\t\t\tkind: \"branch\",\n\t\t\t\t\t\tidentifier: branchName,\n\t\t\t\t\t\tfield: \"computeSettings\",\n\t\t\t\t\t\tcurrent: drift.current,\n\t\t\t\t\t\tdesired: drift.desired,\n\t\t\t\t\t\treason: \"Existing branch has different compute settings. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (\n\t\tconfig.protected !== undefined &&\n\t\tconfig.protected !== remote.branch.protected\n\t) {\n\t\tif (options.updateExisting) {\n\t\t\tplan.push({\n\t\t\t\tkind: \"update-branch-protected\",\n\t\t\t\tprojectId: remote.projectId,\n\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\tbranchName,\n\t\t\t\tprotected: config.protected,\n\t\t\t});\n\t\t} else {\n\t\t\tconflicts.push({\n\t\t\t\tkind: \"branch\",\n\t\t\t\tidentifier: branchName,\n\t\t\t\tfield: \"protected\",\n\t\t\t\tcurrent: remote.branch.protected,\n\t\t\t\tdesired: config.protected,\n\t\t\t\treason: \"Existing branch has a different `protected` flag. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t\t});\n\t\t}\n\t}\n\n\tif (config.ttlSeconds !== undefined) {\n\t\tconst current = remote.branch.expiresAt\n\t\t\t? Math.max(\n\t\t\t\t\t0,\n\t\t\t\t\tMath.round(\n\t\t\t\t\t\t(Date.parse(remote.branch.expiresAt) - Date.now()) /\n\t\t\t\t\t\t\t1000,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t: undefined;\n\t\tif (\n\t\t\tcurrent === undefined ||\n\t\t\tMath.abs(current - config.ttlSeconds) > 30\n\t\t) {\n\t\t\tconst expiresAt = new Date(\n\t\t\t\tDate.now() + config.ttlSeconds * 1000,\n\t\t\t).toISOString();\n\t\t\tif (options.updateExisting) {\n\t\t\t\tplan.push({\n\t\t\t\t\tkind: \"update-branch-ttl\",\n\t\t\t\t\tprojectId: remote.projectId,\n\t\t\t\t\tbranchId: remote.branch.id,\n\t\t\t\t\tbranchName,\n\t\t\t\t\texpiresAt,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconflicts.push({\n\t\t\t\t\tkind: \"branch\",\n\t\t\t\t\tidentifier: branchName,\n\t\t\t\t\tfield: \"ttl\",\n\t\t\t\t\tcurrent: remote.branch.expiresAt,\n\t\t\t\t\tdesired: expiresAt,\n\t\t\t\t\treason: \"Existing branch has a different TTL. Pass `updateExisting: true` (SDK) or `--update-existing` (CLI) to apply.\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction computeDriftBetween(\n\tdesired: ComputeSettings,\n\tendpoint: NeonEndpointSnapshot,\n): {\n\tcurrent: Partial<ComputeSettings>;\n\tdesired: Partial<ComputeSettings>;\n} | null {\n\tconst currentDrift: Partial<ComputeSettings> = {};\n\tconst desiredDrift: Partial<ComputeSettings> = {};\n\tlet drift = false;\n\n\tif (\n\t\tdesired.autoscalingLimitMinCu !== undefined &&\n\t\tdesired.autoscalingLimitMinCu !== endpoint.autoscalingLimitMinCu\n\t) {\n\t\tcurrentDrift.autoscalingLimitMinCu = endpoint.autoscalingLimitMinCu;\n\t\tdesiredDrift.autoscalingLimitMinCu = desired.autoscalingLimitMinCu;\n\t\tdrift = true;\n\t}\n\tif (\n\t\tdesired.autoscalingLimitMaxCu !== undefined &&\n\t\tdesired.autoscalingLimitMaxCu !== endpoint.autoscalingLimitMaxCu\n\t) {\n\t\tcurrentDrift.autoscalingLimitMaxCu = endpoint.autoscalingLimitMaxCu;\n\t\tdesiredDrift.autoscalingLimitMaxCu = desired.autoscalingLimitMaxCu;\n\t\tdrift = true;\n\t}\n\tif (\n\t\tdesired.suspendTimeout !== undefined &&\n\t\tdesired.suspendTimeout !== endpoint.suspendTimeout\n\t) {\n\t\tcurrentDrift.suspendTimeout = endpoint.suspendTimeout;\n\t\tdesiredDrift.suspendTimeout = desired.suspendTimeout;\n\t\tdrift = true;\n\t}\n\treturn drift ? { current: currentDrift, desired: desiredDrift } : null;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"neon-api-real.d.ts","names":["DeployFunctionInput","NeonApi","CreateNeonAuthRestInput","createRealNeonApi","RetryConfig","retryOnLocked","T","Promise","collectCursorPages","isPreviewFeatureUnavailable","customDomainsUnavailableError","previewUnavailableError","createNeonAuthRestInput","buildFunctionDeployForm","FormData","readJsonBody","Response","DeployFunctionInput","NeonApi","CreateNeonAuthRestInput","auth_provider","database_name","createRealNeonApi","options","apiKey","baseUrl","retryOnLocked","maxAttempts","initialDelayMs","maxDelayMs","RetryConfig","fn","Promise","T","config","collectCursorPages","fetchPage","cursor","items","next","isPreviewFeatureUnavailable","err","customDomainsUnavailableError","previewUnavailableError","featureLabel","createNeonAuthRestInput","input","databaseName","buildFunctionDeployForm","FormData","readJsonBody","res","Response"],"sources":["../../src/lib/neon-api-real.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"neon-api-real.d.ts","names":["DeployFunctionInput","NeonApi","CreateNeonAuthRestInput","createRealNeonApi","RetryConfig","retryOnLocked","T","Promise","collectCursorPages","isPreviewFeatureUnavailable","customDomainsUnavailableError","previewUnavailableError","createNeonAuthRestInput","buildFunctionDeployForm","FormData","readJsonBody","Response","DeployFunctionInput","NeonApi","CreateNeonAuthRestInput","auth_provider","database_name","createRealNeonApi","options","apiKey","baseUrl","retryOnLocked","maxAttempts","initialDelayMs","maxDelayMs","RetryConfig","fn","Promise","T","config","collectCursorPages","fetchPage","cursor","items","next","isPreviewFeatureUnavailable","err","customDomainsUnavailableError","previewUnavailableError","featureLabel","createNeonAuthRestInput","input","databaseName","buildFunctionDeployForm","FormData","readJsonBody","res","Response"],"sources":["../../src/lib/neon-api-real.ts"],"mappings":";;;UAiXUE,uBAAAA;;EAAAA,aAAAA,CAAAA,EAAAA,MAAAA;AAeV;AA4CC;AAeD;AAAmC;AAChBI;AAARC;AACFH,iBA7DOD,iBAAAA,CA6DPC,OAAAA,EAAAA;EACEE,MAAAA,EAAAA,MAAAA;EAARC,OAAAA,CAAAA,EAAAA,MAAAA;EAAO;AA6BV;AAAwC;AAGjBD;AAAjBC;EACKD,aAAAA,CAAAA,EAAAA;IAARC,WAAAA,CAAAA,EAAAA,MAAAA;IAAOqB,cAAA,CAAA,EAAA,MAAA;IAm6CMnB,UAAAA,CAAAA,EAAAA,MAAAA;EAgGAC,CAAAA;AAuDhB,CAAA,CAAA,EA5oDIT,OA4oDYU;AAqFhB,UAhsDUP,WAAAA,CAgsDMQ;EAoBAC,WAAAA,EAAAA,MAAAA;EAAuBe,cAAA,EAAA,MAAA;EAAQ5B,UAAAA,EAAAA,MAAAA;AAAsBc;AAAQ;AAwB7E;AAAkC;AAAME;AAAWT;AAAO;;iBA/tDpCF,2BACXE,QAAQD,YACVF,cACNG,QAAQD;iBA6BWE,iEAGhBD;SAAiBD;;KACpBC,QAAQD;;;;;;;;;;;;iBAm6CKG,2BAAAA;;;;;iBAgGAC,6BAAAA;;;;;;;;;;;;iBAuDAC,uBAAAA;iBAqFAC,uBAAAA;;IAEZV;;;;;;;;;;;;iBAkBYW,uBAAAA,QAA+Bb,sBAAsBc;;;;;;;;;;;iBAwB/CC,YAAAA,MAAkBC,WAAWT"}
|
|
@@ -3,7 +3,7 @@ import { formatSuspendTimeout, parseSuspendTimeout } from "./duration.js";
|
|
|
3
3
|
import { wrapNeonError } from "./wrap-neon-error.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { createNeonClient } from "@neon/sdk";
|
|
6
|
-
import { createProject, createProjectBranch, createProjectBranchDataApi, deleteProjectBranchDataApi, getConnectionUri, getNeonAuth, getProject, getProjectBranchDataApi, listProjectBranchDatabases, listProjectBranchRoles, listProjectBranches, listProjectEndpoints, listProjects, updateProject, updateProjectBranch, updateProjectBranchDataApi, updateProjectEndpoint } from "@neon/sdk/raw";
|
|
6
|
+
import { createProject, createProjectBranch, createProjectBranchDataApi, deleteProjectBranchDataApi, disableProjectBranchRealtime, enableProjectBranchRealtime, getConnectionUri, getNeonAuth, getProject, getProjectBranchDataApi, getProjectBranchRealtime, getProjectBranchRealtimeSecret, listProjectBranchDatabases, listProjectBranchRoles, listProjectBranches, listProjectEndpoints, listProjects, updateProject, updateProjectBranch, updateProjectBranchDataApi, updateProjectEndpoint } from "@neon/sdk/raw";
|
|
7
7
|
//#region src/lib/neon-api-real.ts
|
|
8
8
|
const DEFAULT_NEON_API_BASE_URL = "https://console.neon.tech/api/v2";
|
|
9
9
|
/**
|
|
@@ -87,6 +87,24 @@ function dataApiSnapshotFromResponse(data) {
|
|
|
87
87
|
if (settings) snapshot.settings = settings;
|
|
88
88
|
return snapshot;
|
|
89
89
|
}
|
|
90
|
+
function realtimeOptionsToApi(input) {
|
|
91
|
+
return input?.allowedOrigins === void 0 ? {} : { allowed_origins: [...input.allowedOrigins] };
|
|
92
|
+
}
|
|
93
|
+
function realtimeSnapshotFromApi(data) {
|
|
94
|
+
return {
|
|
95
|
+
enabled: data.enabled,
|
|
96
|
+
pending: data.pending,
|
|
97
|
+
...data.invocation_url !== void 0 ? { invocationUrl: data.invocation_url } : {},
|
|
98
|
+
...data.revision !== void 0 ? { revision: data.revision } : {},
|
|
99
|
+
...data.allowed_origins !== void 0 ? { allowedOrigins: [...data.allowed_origins] } : {}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function realtimeSecretFromApi(data) {
|
|
103
|
+
return {
|
|
104
|
+
secret: data.secret,
|
|
105
|
+
pending: data.pending
|
|
106
|
+
};
|
|
107
|
+
}
|
|
90
108
|
const bucketSchema = z.object({
|
|
91
109
|
name: z.string(),
|
|
92
110
|
access_level: z.string().optional()
|
|
@@ -495,6 +513,7 @@ var RealNeonApi = class {
|
|
|
495
513
|
if (err instanceof PlatformError && err.code === ErrorCode.Conflict) {
|
|
496
514
|
const existing = await this.getNeonAuth(projectId, branchId);
|
|
497
515
|
if (existing) return existing;
|
|
516
|
+
throw neonAuthProvisioningConflict(err, projectId, branchId);
|
|
498
517
|
}
|
|
499
518
|
throw err;
|
|
500
519
|
}
|
|
@@ -625,6 +644,53 @@ var RealNeonApi = class {
|
|
|
625
644
|
throw err;
|
|
626
645
|
}
|
|
627
646
|
}
|
|
647
|
+
async getProjectBranchRealtime(projectId, branchId) {
|
|
648
|
+
return this.call(`getProjectBranchRealtime(${projectId}/${branchId})`, async () => realtimeSnapshotFromApi(unwrap(await getProjectBranchRealtime({
|
|
649
|
+
client: this.client,
|
|
650
|
+
path: {
|
|
651
|
+
project_id: projectId,
|
|
652
|
+
branch_id: branchId
|
|
653
|
+
}
|
|
654
|
+
}))), { projectId });
|
|
655
|
+
}
|
|
656
|
+
async getProjectBranchRealtimeSecret(projectId, branchId) {
|
|
657
|
+
return this.call(`getProjectBranchRealtimeSecret(${projectId}/${branchId})`, async () => realtimeSecretFromApi(unwrap(await getProjectBranchRealtimeSecret({
|
|
658
|
+
client: this.client,
|
|
659
|
+
path: {
|
|
660
|
+
project_id: projectId,
|
|
661
|
+
branch_id: branchId
|
|
662
|
+
}
|
|
663
|
+
}))), { projectId });
|
|
664
|
+
}
|
|
665
|
+
async enableProjectBranchRealtime(projectId, branchId, input) {
|
|
666
|
+
await this.call(`enableProjectBranchRealtime(${projectId}/${branchId})`, async () => {
|
|
667
|
+
unwrap(await enableProjectBranchRealtime({
|
|
668
|
+
client: this.client,
|
|
669
|
+
path: {
|
|
670
|
+
project_id: projectId,
|
|
671
|
+
branch_id: branchId
|
|
672
|
+
},
|
|
673
|
+
body: realtimeOptionsToApi(input)
|
|
674
|
+
}));
|
|
675
|
+
}, {
|
|
676
|
+
projectId,
|
|
677
|
+
mutating: true
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
async disableProjectBranchRealtime(projectId, branchId) {
|
|
681
|
+
await this.call(`disableProjectBranchRealtime(${projectId}/${branchId})`, async () => {
|
|
682
|
+
unwrap(await disableProjectBranchRealtime({
|
|
683
|
+
client: this.client,
|
|
684
|
+
path: {
|
|
685
|
+
project_id: projectId,
|
|
686
|
+
branch_id: branchId
|
|
687
|
+
}
|
|
688
|
+
}));
|
|
689
|
+
}, {
|
|
690
|
+
projectId,
|
|
691
|
+
mutating: true
|
|
692
|
+
});
|
|
693
|
+
}
|
|
628
694
|
async listBranchBuckets(projectId, branchId) {
|
|
629
695
|
try {
|
|
630
696
|
return await this.call(`listBranchBuckets(${projectId}/${branchId})`, async () => {
|
|
@@ -1150,6 +1216,20 @@ function neonAuthResponseToSnapshot(data) {
|
|
|
1150
1216
|
if (data.base_url) snapshot.baseUrl = data.base_url;
|
|
1151
1217
|
return snapshot;
|
|
1152
1218
|
}
|
|
1219
|
+
/**
|
|
1220
|
+
* A 409 from enabling Neon Auth on a branch that still has no integration. The cause is
|
|
1221
|
+
* whatever the API says (for example an existing `neon_auth` schema), so its message replaces
|
|
1222
|
+
* the generic name-collision hint that `wrapNeonError` adds to every 409.
|
|
1223
|
+
*/
|
|
1224
|
+
function neonAuthProvisioningConflict(err, projectId, branchId) {
|
|
1225
|
+
const { neonMessage, requestId } = err.details;
|
|
1226
|
+
const requestIdSuffix = typeof requestId === "string" ? ` (request id ${requestId})` : "";
|
|
1227
|
+
const reason = typeof neonMessage === "string" ? `Neon API said: "${neonMessage}"${requestIdSuffix}.` : `Neon Auth is not enabled on this branch and could not be provisioned (HTTP 409)${requestIdSuffix}.`;
|
|
1228
|
+
return new PlatformError(ErrorCode.Conflict, `enableNeonAuth(${projectId}/${branchId}) failed: ${reason}`, {
|
|
1229
|
+
cause: err,
|
|
1230
|
+
details: err.details
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1153
1233
|
function createNeonAuthRestInput(input) {
|
|
1154
1234
|
return {
|
|
1155
1235
|
auth_provider: "better_auth",
|