Files
2026-11-14 09:56:45 +00:00

47 lines
2.2 KiB
JavaScript

// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
import { ConvexHttpClient } from "convex/browser"
// Convex 1.45's CLI lists env through a WebSocket subscription. Linked-service relays are
// deliberately HTTP-only. Query the same system function once over HTTP, then use the CLI's
// update endpoint with its default (no --force) semantics: equal values stay, conflicts fail
// the whole batch, missing values are created, and unlisted variables are untouched.
export async function syncPlatformEnvironment({ url, adminKey, variables, timeoutMs = 30_000 }) {
const controller = new AbortController()
const timer = setTimeout(() => controller.abort(), timeoutMs)
const boundedFetch = (input, options) => fetch(input, { ...options, signal: controller.signal, redirect: "error" })
try {
const client = new ConvexHttpClient(url, { logger: false, fetch: boundedFetch })
client.setAdminAuth(adminKey)
const existing = await client.query("_system/cli/queryEnvironmentVariables", {})
if (
!Array.isArray(existing) ||
existing.some((entry) => typeof entry?.name !== "string" || typeof entry?.value !== "string")
) {
throw new Error("Invalid environment response")
}
const current = new Map(existing.map(({ name, value }) => [name, value]))
const changes = []
for (const [name, value] of Object.entries(variables)) {
if (current.has(name) && current.get(name) !== value) {
throw new Error("Environment conflict")
}
if (!current.has(name)) changes.push({ name, value })
}
if (changes.length > 0) {
const response = await boundedFetch(new URL("/api/update_environment_variables", url), {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: `Convex ${adminKey}` },
body: JSON.stringify({ changes }),
})
await response.body?.cancel()
if (!response.ok) throw new Error("Environment update refused")
}
} catch {
// Upstream failures can contain environment values or credentials. Never surface their
// bodies, messages or causes in deployment logs, including a conflicting existing value.
throw new Error("Convex platform service environment sync failed")
} finally {
clearTimeout(timer)
}
}