centralize URLs into single canonical URL var
This commit is contained in:
@@ -28,6 +28,12 @@ function resolveDbUrl(configPath?: string) {
|
||||
|
||||
function resolveBaseUrl(configPath?: string, explicitBaseUrl?: string) {
|
||||
if (explicitBaseUrl) return explicitBaseUrl.replace(/\/+$/, "");
|
||||
const fromEnv =
|
||||
process.env.PAPERCLIP_PUBLIC_URL ??
|
||||
process.env.PAPERCLIP_AUTH_PUBLIC_BASE_URL ??
|
||||
process.env.BETTER_AUTH_URL ??
|
||||
process.env.BETTER_AUTH_BASE_URL;
|
||||
if (fromEnv?.trim()) return fromEnv.trim().replace(/\/+$/, "");
|
||||
const config = readConfig(configPath);
|
||||
if (config?.auth.baseUrlMode === "explicit" && config.auth.publicBaseUrl) {
|
||||
return config.auth.publicBaseUrl.replace(/\/+$/, "");
|
||||
|
||||
@@ -118,6 +118,29 @@ function collectDeploymentEnvRows(config: PaperclipConfig | null, configPath: st
|
||||
const dbUrl = process.env.DATABASE_URL ?? config?.database?.connectionString ?? "";
|
||||
const databaseMode = config?.database?.mode ?? "embedded-postgres";
|
||||
const dbUrlSource: EnvSource = process.env.DATABASE_URL ? "env" : config?.database?.connectionString ? "config" : "missing";
|
||||
const publicUrl =
|
||||
process.env.PAPERCLIP_PUBLIC_URL ??
|
||||
process.env.PAPERCLIP_AUTH_PUBLIC_BASE_URL ??
|
||||
process.env.BETTER_AUTH_URL ??
|
||||
process.env.BETTER_AUTH_BASE_URL ??
|
||||
config?.auth?.publicBaseUrl ??
|
||||
"";
|
||||
const publicUrlSource: EnvSource =
|
||||
process.env.PAPERCLIP_PUBLIC_URL
|
||||
? "env"
|
||||
: process.env.PAPERCLIP_AUTH_PUBLIC_BASE_URL || process.env.BETTER_AUTH_URL || process.env.BETTER_AUTH_BASE_URL
|
||||
? "env"
|
||||
: config?.auth?.publicBaseUrl
|
||||
? "config"
|
||||
: "missing";
|
||||
let trustedOriginsDefault = "";
|
||||
if (publicUrl) {
|
||||
try {
|
||||
trustedOriginsDefault = new URL(publicUrl).origin;
|
||||
} catch {
|
||||
trustedOriginsDefault = "";
|
||||
}
|
||||
}
|
||||
|
||||
const heartbeatInterval = process.env.HEARTBEAT_SCHEDULER_INTERVAL_MS ?? DEFAULT_HEARTBEAT_SCHEDULER_INTERVAL_MS;
|
||||
const heartbeatEnabled = process.env.HEARTBEAT_SCHEDULER_ENABLED ?? "true";
|
||||
@@ -192,6 +215,24 @@ function collectDeploymentEnvRows(config: PaperclipConfig | null, configPath: st
|
||||
required: false,
|
||||
note: "HTTP listen port",
|
||||
},
|
||||
{
|
||||
key: "PAPERCLIP_PUBLIC_URL",
|
||||
value: publicUrl,
|
||||
source: publicUrlSource,
|
||||
required: false,
|
||||
note: "Canonical public URL for auth/callback/invite origin wiring",
|
||||
},
|
||||
{
|
||||
key: "BETTER_AUTH_TRUSTED_ORIGINS",
|
||||
value: process.env.BETTER_AUTH_TRUSTED_ORIGINS ?? trustedOriginsDefault,
|
||||
source: process.env.BETTER_AUTH_TRUSTED_ORIGINS
|
||||
? "env"
|
||||
: trustedOriginsDefault
|
||||
? "default"
|
||||
: "missing",
|
||||
required: false,
|
||||
note: "Comma-separated auth origin allowlist (auto-derived from PAPERCLIP_PUBLIC_URL when possible)",
|
||||
},
|
||||
{
|
||||
key: "PAPERCLIP_AGENT_JWT_TTL_SECONDS",
|
||||
value: process.env.PAPERCLIP_AGENT_JWT_TTL_SECONDS ?? DEFAULT_AGENT_JWT_TTL_SECONDS,
|
||||
|
||||
@@ -46,6 +46,7 @@ type OnboardOptions = {
|
||||
type OnboardDefaults = Pick<PaperclipConfig, "database" | "logging" | "server" | "auth" | "storage" | "secrets">;
|
||||
|
||||
const ONBOARD_ENV_KEYS = [
|
||||
"PAPERCLIP_PUBLIC_URL",
|
||||
"DATABASE_URL",
|
||||
"PAPERCLIP_DB_BACKUP_ENABLED",
|
||||
"PAPERCLIP_DB_BACKUP_INTERVAL_MINUTES",
|
||||
@@ -60,6 +61,7 @@ const ONBOARD_ENV_KEYS = [
|
||||
"PAPERCLIP_AUTH_BASE_URL_MODE",
|
||||
"PAPERCLIP_AUTH_PUBLIC_BASE_URL",
|
||||
"BETTER_AUTH_URL",
|
||||
"BETTER_AUTH_BASE_URL",
|
||||
"PAPERCLIP_STORAGE_PROVIDER",
|
||||
"PAPERCLIP_STORAGE_LOCAL_DIR",
|
||||
"PAPERCLIP_STORAGE_S3_BUCKET",
|
||||
@@ -99,6 +101,12 @@ function quickstartDefaultsFromEnv(): { defaults: OnboardDefaults; usedEnvKeys:
|
||||
const defaultStorage = defaultStorageConfig();
|
||||
const defaultSecrets = defaultSecretsConfig();
|
||||
const databaseUrl = process.env.DATABASE_URL?.trim() || undefined;
|
||||
const publicUrl =
|
||||
process.env.PAPERCLIP_PUBLIC_URL?.trim() ||
|
||||
process.env.PAPERCLIP_AUTH_PUBLIC_BASE_URL?.trim() ||
|
||||
process.env.BETTER_AUTH_URL?.trim() ||
|
||||
process.env.BETTER_AUTH_BASE_URL?.trim() ||
|
||||
undefined;
|
||||
const deploymentMode =
|
||||
parseEnumFromEnv<DeploymentMode>(process.env.PAPERCLIP_DEPLOYMENT_MODE, DEPLOYMENT_MODES) ?? "local_trusted";
|
||||
const deploymentExposureFromEnv = parseEnumFromEnv<DeploymentExposure>(
|
||||
@@ -107,8 +115,7 @@ function quickstartDefaultsFromEnv(): { defaults: OnboardDefaults; usedEnvKeys:
|
||||
);
|
||||
const deploymentExposure =
|
||||
deploymentMode === "local_trusted" ? "private" : (deploymentExposureFromEnv ?? "private");
|
||||
const authPublicBaseUrl =
|
||||
(process.env.PAPERCLIP_AUTH_PUBLIC_BASE_URL ?? process.env.BETTER_AUTH_URL)?.trim() || undefined;
|
||||
const authPublicBaseUrl = publicUrl;
|
||||
const authBaseUrlModeFromEnv = parseEnumFromEnv<AuthBaseUrlMode>(
|
||||
process.env.PAPERCLIP_AUTH_BASE_URL_MODE,
|
||||
AUTH_BASE_URL_MODES,
|
||||
@@ -120,6 +127,15 @@ function quickstartDefaultsFromEnv(): { defaults: OnboardDefaults; usedEnvKeys:
|
||||
.map((value) => value.trim().toLowerCase())
|
||||
.filter((value) => value.length > 0)
|
||||
: [];
|
||||
const hostnameFromPublicUrl = publicUrl
|
||||
? (() => {
|
||||
try {
|
||||
return new URL(publicUrl).hostname.trim().toLowerCase();
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
})()
|
||||
: null;
|
||||
const storageProvider =
|
||||
parseEnumFromEnv<StorageProvider>(process.env.PAPERCLIP_STORAGE_PROVIDER, STORAGE_PROVIDERS) ??
|
||||
defaultStorage.provider;
|
||||
@@ -157,7 +173,7 @@ function quickstartDefaultsFromEnv(): { defaults: OnboardDefaults; usedEnvKeys:
|
||||
exposure: deploymentExposure,
|
||||
host: process.env.HOST ?? "127.0.0.1",
|
||||
port: Number(process.env.PORT) || 3100,
|
||||
allowedHostnames: Array.from(new Set(allowedHostnamesFromEnv)),
|
||||
allowedHostnames: Array.from(new Set([...allowedHostnamesFromEnv, ...(hostnameFromPublicUrl ? [hostnameFromPublicUrl] : [])])),
|
||||
serveUi: parseBooleanFromEnv(process.env.SERVE_UI) ?? true,
|
||||
},
|
||||
auth: {
|
||||
|
||||
Reference in New Issue
Block a user