import { Injectable } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import type { Response } from "express"; type CookieOptionsInput = { httpOnly?: boolean; secure?: boolean; sameSite?: "lax" | "strict" | "none"; maxAge?: number; expires?: Date; path?: string; }; type CookieOptions = { httpOnly: boolean; secure: boolean; sameSite: "lax" | "strict"; maxAge?: number; expires?: Date; path: string; }; @Injectable() export class CookieService { constructor(private readonly configService: ConfigService) {} private getCookieOptions(options?: CookieOptionsInput): CookieOptions { const isDevelopment = this.configService.get("NODE_ENV") !== "production"; const isSecure = options?.secure ?? !isDevelopment; const sameSiteOption = options?.sameSite; const defaultSameSite = isDevelopment ? "lax" : "strict"; const sameSite = sameSiteOption === "none" ? defaultSameSite : (sameSiteOption ?? defaultSameSite); return { httpOnly: options?.httpOnly ?? true, secure: isSecure, sameSite, ...(options?.maxAge !== undefined && { maxAge: options.maxAge }), ...(options?.expires !== undefined && { expires: options.expires }), path: options?.path ?? "/", }; } setCookie( res: Response, name: string, value: string, options?: CookieOptionsInput, ): void { const cookieOptions = this.getCookieOptions(options); res.cookie(name, value, cookieOptions); } clearCookie(res: Response, name: string, options?: CookieOptionsInput): void { const clearOptions = this.getCookieOptions({ ...options, maxAge: 0, expires: new Date(0), }); res.clearCookie(name, clearOptions); res.cookie(name, "", clearOptions); } }