All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 50s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
111 lines
4.4 KiB
TypeScript
111 lines
4.4 KiB
TypeScript
export const PORT = Number(Deno.env.get("GERBEUR_PORT")) || 8000;
|
|
export const SMTPS_URL = Deno.env.get("GERBEUR_SMTPS_URL")?.trim() || "";
|
|
export const FROM_EMAIL = Deno.env.get("GERBEUR_FROM_EMAIL")?.trim() || "";
|
|
|
|
const DEFAULT_WELCOME_EMAIL_BODY = `# Welcome to {{site_name}}!
|
|
|
|
Hi **{{username}}**,
|
|
|
|
Your account has been created successfully. Welcome aboard!`;
|
|
|
|
export const WELCOME_EMAIL_BODY =
|
|
Deno.env.get("GERBEUR_WELCOME_EMAIL_BODY")?.trim() ||
|
|
DEFAULT_WELCOME_EMAIL_BODY;
|
|
export const JWT_SECRET = Deno.env.get("GERBEUR_JWT_SECRET")?.trim() || "";
|
|
// GERBEUR_LISTEN_HOST controls the network interface Oak binds to.
|
|
// Defaults to 0.0.0.0 so Docker port-forwarding works out of the box.
|
|
// Set to 127.0.0.1 to restrict to loopback only.
|
|
export const LISTEN_HOST = Deno.env.get("GERBEUR_LISTEN_HOST") || "0.0.0.0";
|
|
// Public-facing URL of the server — used for CORS, WebSocket origin checks,
|
|
// email links, and OG image URLs. Behind a reverse proxy, set this to the
|
|
// externally-visible URL (e.g. https://example.com). No trailing slash.
|
|
// Defaults to http://localhost:PORT for local development.
|
|
export const PUBLIC_URL =
|
|
Deno.env.get("GERBEUR_PUBLIC_URL")?.trim().replace(/\/$/, "") ||
|
|
`http://localhost:${PORT}`;
|
|
// In single-container deployments the API serves the frontend, so FRONTEND_URL
|
|
// equals PUBLIC_URL. Override with GERBEUR_FRONTEND_URL when running the
|
|
// frontend on a separate host/port (e.g. Vite dev server or a CDN origin).
|
|
export const FRONTEND_URL = Deno.env.get("GERBEUR_FRONTEND_URL")?.trim() ||
|
|
PUBLIC_URL;
|
|
// Overridable so the test suite can run against a throwaway database and
|
|
// uploads directory (see api/test/setup.ts).
|
|
export const DB_PATH = Deno.env.get("GERBEUR_DB_PATH") || "api/sql/gerbeur.db";
|
|
|
|
// Upload/files
|
|
export const UPLOADS_DIR = Deno.env.get("GERBEUR_UPLOADS_DIR") || "api/uploads";
|
|
export const DUMPS_DIR = `${UPLOADS_DIR}/dumps`;
|
|
export const AVATARS_DIR = `${UPLOADS_DIR}/avatars`;
|
|
export const PLAYLIST_IMAGES_DIR = `${UPLOADS_DIR}/playlist-images`;
|
|
export const ATTACHMENTS_DIR = `${UPLOADS_DIR}/attachments`;
|
|
export const THUMBNAILS_DIR = `${UPLOADS_DIR}/thumbnails`;
|
|
|
|
export const MAX_IMAGE_SIZE_BYTES = 5 * 1024 * 1024; // 5 MB
|
|
export const ALLOWED_IMAGE_MIMES = new Set([
|
|
"image/jpeg",
|
|
"image/png",
|
|
"image/gif",
|
|
"image/webp",
|
|
]);
|
|
|
|
export const DUMP_ALLOWED_MIME_PREFIXES = [
|
|
"text/",
|
|
"image/",
|
|
"video/",
|
|
"audio/",
|
|
];
|
|
export const DUMP_ALLOWED_MIME_TYPES = new Set([
|
|
"application/pdf",
|
|
"application/json",
|
|
"application/zip",
|
|
"application/x-zip-compressed",
|
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
"application/msword",
|
|
"application/vnd.ms-excel",
|
|
"application/vnd.ms-powerpoint",
|
|
]);
|
|
|
|
// Pagination
|
|
export const PAGINATION_DEFAULT_LIMIT = 20;
|
|
export const PAGINATION_MAX_LIMIT = 100;
|
|
|
|
// Startup housekeeping
|
|
export const ORPHANED_ATTACHMENTS_RETENTION_HOURS = 1;
|
|
export const UNUSED_INVITES_RETENTION_DAYS = 7;
|
|
|
|
// SEO/OG
|
|
export const OG_SITE_NAME = Deno.env.get("GERBEUR_SITE_NAME") || "gerbeur";
|
|
|
|
// Emoji the favicon set + app header logo are generated/rendered from.
|
|
// Applied at runtime (server startup + index.html injection), so changing it
|
|
// only needs a restart — no rebuild.
|
|
export const SITE_EMOJI = Deno.env.get("GERBEUR_SITE_EMOJI") || "🚚";
|
|
|
|
// Which Bandcamp playback path the frontend uses.
|
|
// "embed" — the bandcamp.com iframe (cannot autoplay)
|
|
// "native" — resolve the page's mp3 streams and play them in the app's own
|
|
// player, which autoplays and supports albums as a queue
|
|
// Anything unrecognised falls back to "embed", so a typo degrades safely.
|
|
export type BandcampPlayer = "embed" | "native";
|
|
export const BANDCAMP_PLAYER: BandcampPlayer =
|
|
Deno.env.get("GERBEUR_BANDCAMP_PLAYER")?.trim() === "native"
|
|
? "native"
|
|
: "embed";
|
|
|
|
// Background color for generated icons and the manifest. Mirrors the
|
|
// hard-coded theme-color in index.html.
|
|
export const THEME_COLOR = "#111827";
|
|
|
|
const rawOrigins = Deno.env.get("GERBEUR_ALLOWED_ORIGINS") ?? "";
|
|
export const ALLOWED_ORIGINS: string[] = Array.from(
|
|
new Set([
|
|
PUBLIC_URL,
|
|
// FRONTEND_URL is auto-included so the separate-frontend case only needs
|
|
// GERBEUR_FRONTEND_URL — no need to repeat it in GERBEUR_ALLOWED_ORIGINS.
|
|
FRONTEND_URL,
|
|
...rawOrigins.split(",").map((o) => o.trim()).filter(Boolean),
|
|
]),
|
|
);
|