102 lines
2.6 KiB
TypeScript
102 lines
2.6 KiB
TypeScript
/**
|
|
* Server-only utilities for building auth URLs and config
|
|
* These read from process.env and are NOT bundled into client code
|
|
*/
|
|
|
|
|
|
import "server-only";
|
|
import type { StytchClientConfig } from "./config-types";
|
|
|
|
export interface LoginUrlOptions {
|
|
returnTo?: string;
|
|
}
|
|
|
|
export interface LogoutUrlOptions {
|
|
returnTo?: string;
|
|
}
|
|
|
|
function sanitizeReturnTo(value: string | undefined): string | undefined {
|
|
if (!value) return undefined;
|
|
const trimmed = value.trim();
|
|
if (!trimmed.startsWith("/") || trimmed.startsWith("//")) {
|
|
return undefined;
|
|
}
|
|
return trimmed;
|
|
}
|
|
|
|
export function getBaseUrl(): string {
|
|
let baseUrl =
|
|
process.env.APP_BASE_URL ||
|
|
process.env.NEXT_PUBLIC_BASE_URL ||
|
|
process.env.NEXT_PUBLIC_APP_BASE_URL ||
|
|
process.env.APP_URL ||
|
|
null;
|
|
|
|
const resolved = baseUrl || "http://localhost:3000";
|
|
return resolved.replace(/\/$/, "");
|
|
}
|
|
|
|
function resolveRoute(value: string | undefined, fallback: string): URL {
|
|
const base = getBaseUrl();
|
|
const trimmed = value?.trim();
|
|
|
|
if (!trimmed) {
|
|
return new URL(fallback, `${base}/`);
|
|
}
|
|
|
|
if (/^https?:\/\//i.test(trimmed)) {
|
|
return new URL(trimmed);
|
|
}
|
|
|
|
const path = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
return new URL(path, `${base}/`);
|
|
}
|
|
|
|
export function buildLoginUrl(options?: LoginUrlOptions): string {
|
|
const url = resolveRoute(process.env.NEXT_PUBLIC_STYTCH_LOGIN_PATH, "/auth");
|
|
const returnTo = sanitizeReturnTo(options?.returnTo);
|
|
|
|
if (returnTo) {
|
|
url.searchParams.set("returnTo", returnTo);
|
|
}
|
|
|
|
return url.toString();
|
|
}
|
|
|
|
export function buildLogoutUrl(options?: LogoutUrlOptions): string {
|
|
const url = resolveRoute(
|
|
process.env.NEXT_PUBLIC_STYTCH_LOGOUT_PATH,
|
|
"/api/auth/logout"
|
|
);
|
|
const returnTo = sanitizeReturnTo(options?.returnTo);
|
|
|
|
if (returnTo) {
|
|
url.searchParams.set("returnTo", returnTo);
|
|
}
|
|
|
|
return url.toString();
|
|
}
|
|
|
|
/**
|
|
* Build complete client config from environment variables
|
|
* This should only be called on the server
|
|
*/
|
|
export function buildStytchClientConfig(): StytchClientConfig {
|
|
const publicToken = process.env.NEXT_PUBLIC_STYTCH_PUBLIC_TOKEN;
|
|
if (!publicToken) {
|
|
throw new Error("NEXT_PUBLIC_STYTCH_PUBLIC_TOKEN is required");
|
|
}
|
|
|
|
return {
|
|
publicToken,
|
|
sessionDurationMinutes:
|
|
Number(process.env.NEXT_PUBLIC_STYTCH_SESSION_DURATION_MINUTES ?? "480") ||
|
|
480,
|
|
loginPath: process.env.NEXT_PUBLIC_STYTCH_LOGIN_PATH || "/auth",
|
|
logoutPath:
|
|
process.env.NEXT_PUBLIC_STYTCH_LOGOUT_PATH || "/api/auth/logout",
|
|
redirectPath:
|
|
process.env.NEXT_PUBLIC_STYTCH_REDIRECT_PATH || "/authenticate",
|
|
baseUrl: getBaseUrl(),
|
|
};
|
|
}
|