/** OTP expiry is stored as epoch milliseconds on user documents. */ export function otpExpireToEpochMs(value: unknown): number { if (value == null) return 0; if (typeof value === "number" && Number.isFinite(value)) { if (value >= 1_000_000_000_000) return value; if (value >= 1_000_000_000 && value < 1_000_000_000_000) { return value * 1000; } return value; } if (value instanceof Date) { return value.getTime(); } if (typeof value === "string") { const asNum = Number(value); if (Number.isFinite(asNum)) return asNum; const parsed = Date.parse(value); if (Number.isFinite(parsed)) return parsed; } return 0; } export function isOtpExpiryActive( otpExpire: unknown, nowMs: number = Date.now(), ): boolean { const exp = otpExpireToEpochMs(otpExpire); return exp > nowMs; } export function computeOtpExpireMs( expireMinutes: number, nowMs: number = Date.now(), ): number { const minutes = Number.isFinite(expireMinutes) && expireMinutes > 0 ? expireMinutes : 2; return nowMs + minutes * 60 * 1000; } export function readOtpExpireMinutesFromEnv(): number { const raw = Number(process.env.EXP_OTP_TIME ?? "2"); return Number.isFinite(raw) && raw > 0 ? raw : 2; }