UNPKG

ngx-cookie-service-ssr

Version:
1 lines 21.1 kB
{"version":3,"file":"ngx-cookie-service-ssr.mjs","sources":["../../../projects/ngx-cookie-service-ssr/src/lib/ssr-cookie.service.ts","../../../projects/ngx-cookie-service-ssr/src/public-api.ts","../../../projects/ngx-cookie-service-ssr/src/ngx-cookie-service-ssr.ts"],"sourcesContent":["import { isPlatformBrowser } from '@angular/common';\nimport { DOCUMENT, inject, Injectable, PLATFORM_ID, REQUEST, RESPONSE_INIT } from '@angular/core';\n\nexport type SameSite = 'Lax' | 'None' | 'Strict';\n\nexport interface CookieOptions {\n expires?: number | Date;\n path?: string;\n domain?: string;\n secure?: boolean;\n sameSite?: SameSite;\n partitioned?: boolean;\n httpOnly?: boolean;\n maxAge?: number;\n}\n\n@Injectable({\n providedIn: 'root',\n})\nexport class SsrCookieService {\n private readonly document = inject(DOCUMENT);\n private readonly platformId = inject(PLATFORM_ID);\n private readonly request = inject(REQUEST, { optional: true });\n private readonly responseInit = inject(RESPONSE_INIT, { optional: true });\n private readonly documentIsAccessible: boolean = isPlatformBrowser(this.platformId);\n\n /**\n * Get cookie Regular Expression\n *\n * @param name Cookie name\n * @returns property RegExp\n *\n * @author: Stepan Suvorov\n * @since: 1.0.0\n */\n static getCookieRegExp(name: string): RegExp {\n const escapedName: string = name.replace(/([[\\]{}()|=;+?,.*^$\\\\])/gi, '\\\\$1');\n\n return new RegExp('(?:^' + escapedName + '|;\\\\s*' + escapedName + ')=(.*?)(?:;|$)');\n }\n\n /**\n * Gets the unencoded version of an encoded component of a Uniform Resource Identifier (URI).\n *\n * @param encodedURIComponent A value representing an encoded URI component.\n *\n * @returns The unencoded version of an encoded component of a Uniform Resource Identifier (URI).\n *\n * @author: Stepan Suvorov\n * @since: 1.0.0\n */\n static safeDecodeURIComponent(encodedURIComponent: string): string {\n try {\n return decodeURIComponent(encodedURIComponent);\n } catch {\n // probably it is not uri encoded. return as is\n return encodedURIComponent;\n }\n }\n\n /**\n * Return `true` if {@link Document} is accessible, otherwise return `false`\n *\n * @param name Cookie name\n * @returns boolean - whether cookie with specified name exists\n *\n * @author: Stepan Suvorov\n * @since: 1.0.0\n */\n check(name: string): boolean {\n name = encodeURIComponent(name);\n const regExp: RegExp = SsrCookieService.getCookieRegExp(name);\n return regExp.test((this.documentIsAccessible ? this.document.cookie : this.getRequestCookies()) ?? '');\n }\n\n /**\n * Get cookies by name\n *\n * @param name Cookie name\n * @returns property value\n *\n * @author: Stepan Suvorov\n * @since: 1.0.0\n */\n get(name: string): string {\n if (this.check(name)) {\n name = encodeURIComponent(name);\n const regExp: RegExp = SsrCookieService.getCookieRegExp(name);\n const result = regExp.exec((this.documentIsAccessible ? this.document.cookie : this.getRequestCookies()) ?? '');\n return result?.[1] ? SsrCookieService.safeDecodeURIComponent(result[1]) : '';\n }\n return '';\n }\n\n /**\n * Get all cookies in JSON format\n *\n * @returns all the cookies in json\n *\n * @author: Stepan Suvorov\n * @since: 1.0.0\n */\n getAll(): Record<string, string> {\n const cookies: Record<string, string> = {};\n const cookieString: any = this.documentIsAccessible ? this.document?.cookie : this.getRequestCookies();\n\n if (cookieString && cookieString !== '') {\n cookieString.split(';').forEach((currentCookie: string) => {\n const trimmedCookie = currentCookie.trim();\n if (!trimmedCookie) {\n return;\n }\n // Find the first '=' to handle cookie values that contain '='\n const equalIndex = trimmedCookie.indexOf('=');\n if (equalIndex === -1) {\n // Cookie without value (invalid, but handle gracefully)\n return;\n }\n const cookieName = trimmedCookie.substring(0, equalIndex);\n const cookieValue = trimmedCookie.substring(equalIndex + 1);\n cookies[SsrCookieService.safeDecodeURIComponent(cookieName)] = SsrCookieService.safeDecodeURIComponent(cookieValue);\n });\n }\n\n return cookies;\n }\n\n /**\n * Set cookie based on provided information\n *\n * Cookie's parameters:\n * <pre>\n * expires Number of days until the cookies expires or an actual `Date`\n * path Cookie path\n * domain Cookie domain\n * secure Cookie secure flag\n * sameSite OWASP same site token `Lax`, `None`, or `Strict`. Defaults to `Lax`\n * </pre>\n *\n * @param name Cookie name\n * @param value Cookie value\n * @param options Body with cookie's params\n *\n * @author: Stepan Suvorov\n * @since: 1.0.0\n */\n set(name: string, value: string, options?: CookieOptions): void;\n\n set(\n name: string,\n value: string,\n expiresOrOptions?: number | Date | CookieOptions,\n path?: string,\n domain?: string,\n secure?: boolean,\n sameSite?: SameSite,\n partitioned?: boolean\n ): void {\n const options = this.normalizeOptions(expiresOrOptions, path, domain, secure, sameSite, partitioned);\n\n if (!this.documentIsAccessible) {\n if (this.responseInit) {\n this.setServerCookie(name, value, options);\n }\n return;\n }\n\n // Warn if SameSite=None without Secure on browser\n if (options.sameSite === 'None' && !options.secure) {\n options.secure = true;\n console.warn(\n `[ngx-cookie-service] Cookie ${name} was forced with secure flag because SameSite=None.` +\n `More details : https://github.com/stevermeister/ngx-cookie-service/issues/86#issuecomment-597720130`\n );\n }\n\n const cookieString = this.buildCookieString(name, value, options);\n this.document.cookie = cookieString;\n }\n\n /**\n * Delete cookie by name at given path and domain. If not path is not specified, cookie at '/' path will be deleted.\n *\n * @param name Cookie name\n * @param path Cookie path\n * @param domain Cookie domain\n * @param secure Cookie secure flag\n * @param sameSite Cookie sameSite flag - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite\n *\n * @author: Stepan Suvorov\n * @since: 1.0.0\n */\n delete(name: string, path?: string, domain?: string, secure?: boolean, sameSite: 'Lax' | 'None' | 'Strict' = 'Lax'): void {\n if (!this.documentIsAccessible && !this.responseInit) {\n return;\n }\n const expiresDate = new Date('Thu, 01 Jan 1970 00:00:01 GMT');\n this.set(name, '', { expires: expiresDate, path, domain, secure, sameSite });\n }\n\n /**\n * Delete all cookies at given path and domain. If not path is not specified, all cookies at '/' path will be deleted.\n *\n * @param path Cookie path\n * @param domain Cookie domain\n * @param secure Is the Cookie secure\n * @param sameSite Is the cookie same site\n *\n * @author: Stepan Suvorov\n * @since: 1.0.0\n */\n deleteAll(path?: string, domain?: string, secure?: boolean, sameSite: 'Lax' | 'None' | 'Strict' = 'Lax'): void {\n if (!this.documentIsAccessible && !this.responseInit) {\n return;\n }\n\n const cookies: any = this.getAll();\n\n for (const cookieName in cookies) {\n if (cookies.hasOwnProperty(cookieName)) {\n this.delete(cookieName, path, domain, secure, sameSite);\n }\n }\n }\n\n /**\n * Helper method to safely get cookies from request object\n * Handles both Angular's REQUEST interface (Web API Request) and Express's req interface\n */\n private getRequestCookies(): string | null {\n if (!this.request) {\n return null;\n }\n\n // Handle Web API Request object (Angular 19+ with AngularNodeAppEngine)\n // The REQUEST token provides a standard Web API Request object\n if (this.request.headers && typeof this.request.headers.get === 'function') {\n return this.request.headers.get('cookie');\n }\n\n // Handle Express request object (for backward compatibility or custom setups)\n const reqAny = this.request as any;\n if (typeof reqAny.get === 'function') {\n const cookie = reqAny.get('cookie') || reqAny.get('Cookie');\n if (cookie) {\n return cookie;\n }\n }\n\n // Handle direct headers object access (Express typically uses lowercase 'cookie')\n const headers = this.request.headers;\n if (headers && typeof headers === 'object') {\n // Check both lowercase and capitalized versions\n if ((headers as any)['cookie']) {\n return (headers as any)['cookie'];\n }\n if ((headers as any)['Cookie']) {\n return (headers as any)['Cookie'];\n }\n }\n return null;\n }\n\n /**\n * Helper method to set cookies on the server response\n *\n * @param name Cookie name\n * @param value Cookie value\n * @param options Cookie options\n *\n * @author: Pavankumar Jadda\n * @since: 21.2.0\n */\n private setServerCookie(name: string, value: string, options: CookieOptions = {}): void {\n if (!this.responseInit) {\n return;\n }\n\n // SameSite=None requires Secure\n if (options.sameSite === 'None' && !options.secure) {\n options.secure = true;\n }\n\n const cookieString = this.buildCookieString(name, value, options);\n this.appendSetCookieHeader(cookieString);\n }\n\n /**\n * Normalizes cookie options from either an options object or individual parameters\n *\n * @param expiresOrOptions Either a CookieOptions object, expiration (number of days or Date), or undefined\n * @param path Cookie path\n * @param domain Cookie domain\n * @param secure Cookie secure flag\n * @param sameSite Cookie sameSite flag\n * @param partitioned Cookie partitioned flag\n * @returns Normalized CookieOptions object\n *\n * @author: Pavankumar Jadda\n * @since: 21.2.0\n */\n private normalizeOptions(\n expiresOrOptions?: number | Date | CookieOptions,\n path?: string,\n domain?: string,\n secure?: boolean,\n sameSite?: SameSite,\n partitioned?: boolean\n ): CookieOptions {\n // If it's an object but not a Date, treat it as CookieOptions\n if (typeof expiresOrOptions === 'object' && !(expiresOrOptions instanceof Date)) {\n return { ...expiresOrOptions };\n }\n\n // Otherwise, it's either a number, Date, or undefined - build options from individual params\n return {\n expires: expiresOrOptions,\n path,\n domain,\n secure,\n sameSite,\n partitioned,\n };\n }\n\n /**\n * Builds a cookie string from name, value, and options\n *\n * @param name Cookie name\n * @param value Cookie value\n * @param options Cookie options\n * @returns Formatted cookie string\n *\n * @author: Pavankumar Jadda\n * @since: 21.2.0\n */\n private buildCookieString(name: string, value: string, options: CookieOptions = {}): string {\n let cookieString = encodeURIComponent(name) + '=' + encodeURIComponent(value) + ';';\n\n if (options.expires) {\n if (typeof options.expires === 'number') {\n const dateExpires = new Date(Date.now() + options.expires * 1000 * 60 * 60 * 24);\n cookieString += 'Expires=' + dateExpires.toUTCString() + ';';\n } else {\n cookieString += 'Expires=' + options.expires.toUTCString() + ';';\n }\n }\n\n if (options.maxAge !== undefined) {\n cookieString += 'Max-Age=' + options.maxAge + ';';\n }\n\n if (options.path) {\n cookieString += 'Path=' + options.path + ';';\n }\n\n if (options.domain) {\n cookieString += 'Domain=' + options.domain + ';';\n }\n\n if (options.secure) {\n cookieString += 'Secure;';\n }\n\n cookieString += 'SameSite=' + (options.sameSite ?? 'Lax') + ';';\n\n if (options.partitioned) {\n cookieString += 'Partitioned;';\n }\n\n if (options.httpOnly) {\n cookieString += 'HttpOnly;';\n }\n\n return cookieString;\n }\n\n /**\n * Appends a Set-Cookie header to the response\n * Handles different header formats (Headers object, array, or plain object)\n *\n * @param cookieString The formatted cookie string to append\n *\n * @author: Pavankumar Jadda\n * @since: 21.2.0\n */\n private appendSetCookieHeader(cookieString: string): void {\n if (!this.responseInit) {\n return;\n }\n\n // Initialize headers if missing\n if (!this.responseInit.headers) {\n this.responseInit.headers = new Headers();\n }\n\n const headers = this.responseInit.headers;\n\n if (headers instanceof Headers) {\n headers.append('Set-Cookie', cookieString);\n } else if (Array.isArray(headers)) {\n // If it's an array (sequence of sequences), push new header\n (headers as string[][]).push(['Set-Cookie', cookieString]);\n } else {\n // Handle plain object format\n const headersObj = headers as Record<string, string | string[]>;\n const existing = headersObj['Set-Cookie'];\n if (existing) {\n headersObj['Set-Cookie'] = Array.isArray(existing) ? [...existing, cookieString] : [existing, cookieString];\n } else {\n headersObj['Set-Cookie'] = cookieString;\n }\n }\n }\n}\n","/*\n * Public API Surface of ngx-cookie-service-ssr\n */\n\nexport * from './lib/ssr-cookie.service';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}