const DEFAULT_JWT_EXPIRY_SECONDS = 7 * 24 * 60 * 60; const isFiniteNumber = (value: unknown): value is number => typeof value === "number" && Number.isFinite(value) && value > 0; /** * Parse a JWT expiry configuration string (e.g. "15m", "7d") into seconds. * Falls back to a sensible default when parsing fails. */ export const parseJwtExpiry = (expiresIn: string | number | undefined | null): number => { if (isFiniteNumber(expiresIn)) { return Math.floor(expiresIn); } if (typeof expiresIn !== "string") { return DEFAULT_JWT_EXPIRY_SECONDS; } const trimmed = expiresIn.trim(); if (!trimmed) { return DEFAULT_JWT_EXPIRY_SECONDS; } const unit = trimmed.slice(-1); const valuePortion = trimmed.slice(0, -1); const parsedValue = parseInt(valuePortion, 10); const toSeconds = (multiplier: number) => { if (Number.isNaN(parsedValue) || parsedValue <= 0) { return DEFAULT_JWT_EXPIRY_SECONDS; } return parsedValue * multiplier; }; switch (unit) { case "s": return toSeconds(1); case "m": return toSeconds(60); case "h": return toSeconds(60 * 60); case "d": return toSeconds(24 * 60 * 60); default: { const numeric = Number(trimmed); if (isFiniteNumber(numeric)) { return Math.floor(numeric); } return DEFAULT_JWT_EXPIRY_SECONDS; } } }; export const calculateExpiryDate = ( expiresIn: string | number | undefined | null, referenceDate: number = Date.now() ): string => { const seconds = parseJwtExpiry(expiresIn); return new Date(referenceDate + seconds * 1000).toISOString(); }; export const JWT_EXPIRY_DEFAULT_SECONDS = DEFAULT_JWT_EXPIRY_SECONDS;