93 lines
3.9 KiB
JavaScript
93 lines
3.9 KiB
JavaScript
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
|
|
// Deploys this app's Better Auth functions (./functions) to its Better Auth Convex deployment, after
|
|
// installing the two variables Better Auth reads there: SITE_URL, the app's public origin and the
|
|
// only origin Better Auth trusts, and BETTER_AUTH_SECRET. The migrate job runs it on the Postgres
|
|
// profile (apps/worker/src/migrate.ts), the convex-deploy job on the Convex profile; a development
|
|
// machine runs `node better-auth/deploy.mjs`. The temporary env file is mode 0600 and removed on
|
|
// success and on failure; no value is printed.
|
|
//
|
|
// BETTER_AUTH_CONVEX_URL the Better Auth deployment's URL
|
|
// BETTER_AUTH_CONVEX_ADMIN_KEY its admin key (this job and the web server's revocation relay only)
|
|
// BETTER_AUTH_SECRET Better Auth's secret, at least 32 characters (this job only)
|
|
// CONUSAI_PUBLIC_URL the app's public origin
|
|
|
|
import { spawnSync } from "node:child_process"
|
|
import { mkdtempSync, rmSync, writeFileSync } from "node:fs"
|
|
import { tmpdir } from "node:os"
|
|
import { join } from "node:path"
|
|
import { fileURLToPath } from "node:url"
|
|
|
|
const required = (name, value, why) => {
|
|
const trimmed = value?.trim()
|
|
if (!trimmed) throw new Error(`${name} is not set: ${why}`)
|
|
if (/[\r\n]/.test(trimmed)) throw new Error(`${name} holds a line break`)
|
|
return trimmed
|
|
}
|
|
|
|
export function deployBetterAuth(env = process.env) {
|
|
const url = required(
|
|
"BETTER_AUTH_CONVEX_URL",
|
|
env.BETTER_AUTH_CONVEX_URL,
|
|
"the URL of this app's Better Auth deployment",
|
|
)
|
|
const adminKey = required(
|
|
"BETTER_AUTH_CONVEX_ADMIN_KEY",
|
|
env.BETTER_AUTH_CONVEX_ADMIN_KEY,
|
|
"the admin key of the Better Auth deployment",
|
|
)
|
|
const secret = required(
|
|
"BETTER_AUTH_SECRET",
|
|
env.BETTER_AUTH_SECRET,
|
|
"Better Auth's secret, 32 random characters or more",
|
|
)
|
|
if (secret.length < 32) throw new Error("BETTER_AUTH_SECRET is shorter than 32 characters")
|
|
const publicUrl = required(
|
|
"CONUSAI_PUBLIC_URL",
|
|
env.CONUSAI_PUBLIC_URL,
|
|
"the app's public origin, which Better Auth trusts",
|
|
)
|
|
const site = new URL(publicUrl).origin
|
|
const project = fileURLToPath(new URL(".", import.meta.url))
|
|
const cli = fileURLToPath(new URL("../node_modules/convex/bin/main.js", import.meta.url))
|
|
const childEnv = { ...env, CONVEX_SELF_HOSTED_URL: url, CONVEX_SELF_HOSTED_ADMIN_KEY: adminKey }
|
|
delete childEnv.CONVEX_DEPLOYMENT
|
|
delete childEnv.CONVEX_DEPLOY_KEY
|
|
|
|
const directory = mkdtempSync(join(tmpdir(), "conusai-better-auth-env-"))
|
|
const envFile = join(directory, ".env")
|
|
try {
|
|
writeFileSync(envFile, `SITE_URL=${site}\nBETTER_AUTH_SECRET=${secret}\n`, { mode: 0o600, flag: "wx" })
|
|
const seeded = spawnSync(process.execPath, [cli, "env", "set", "--from-file", envFile, "--force"], {
|
|
cwd: project,
|
|
env: childEnv,
|
|
stdio: ["ignore", "ignore", "pipe"],
|
|
encoding: "utf8",
|
|
})
|
|
if (seeded.error || seeded.status !== 0) {
|
|
// The CLI names what failed (the connection, the key); it does not print the values it was given.
|
|
throw new Error(
|
|
`the Better Auth deployment's environment could not be set: ${seeded.stderr?.trim().split("\n").at(-1) ?? ""}`,
|
|
)
|
|
}
|
|
const deployed = spawnSync(process.execPath, [cli, "deploy", "--yes", "--typecheck", "disable"], {
|
|
cwd: project,
|
|
env: childEnv,
|
|
stdio: "inherit",
|
|
})
|
|
if (deployed.error) throw deployed.error
|
|
if (deployed.status !== 0) throw new Error(`convex deploy of the Better Auth functions exited ${deployed.status}`)
|
|
} finally {
|
|
rmSync(directory, { recursive: true, force: true })
|
|
}
|
|
}
|
|
|
|
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
|
|
try {
|
|
deployBetterAuth()
|
|
console.info("better-auth: functions deployed")
|
|
} catch (error) {
|
|
console.error(`better-auth: ${error instanceof Error ? error.message : String(error)}`)
|
|
process.exit(1)
|
|
}
|
|
}
|