{"version":3,"file":"localeStorage.cjs","names":["parts: string[]","configuration","getStorageAttributes","getCookie"],"sources":["../../../src/utils/localeStorage.ts"],"sourcesContent":["import configuration from '@intlayer/config/built';\nimport type { CookiesAttributes, Locale, LocalesValues } from '@intlayer/types';\nimport { getStorageAttributes } from '../getStorageAttributes';\nimport { getCookie } from './getCookie';\n\ntype CookieBuildAttributes = {\n  /**\n   * Cookie domain to store the locale information\n   *\n   * Default: undefined\n   *\n   * Define the domain where the cookie is available. Defaults to\n   * the domain of the page where the cookie was created.\n   */\n  domain?: string;\n  /**\n   * Cookie path to store the locale information\n   *\n   * Default: undefined\n   *\n   * Define the path where the cookie is available. Defaults to '/'\n   */\n  path?: string;\n  /**\n   * Cookie secure to store the locale information\n   *\n   * Default: undefined\n   *\n   * A Boolean indicating if the cookie transmission requires a\n   * secure protocol (https). Defaults to false.\n   */\n  secure?: boolean;\n  /**\n   * Cookie httpOnly to store the locale information\n   *\n   * Default: undefined\n   *\n   * The cookie httpOnly where the locale information is stored.\n   */\n  httpOnly?: boolean;\n  /**\n   * Cookie sameSite to store the locale information\n   *\n   * Default: undefined\n   *\n   * Asserts that a cookie must not be sent with cross-origin requests,\n   * providing some protection against cross-site request forgery\n   * attacks (CSRF)\n   */\n  sameSite?: 'strict' | 'lax' | 'none';\n\n  /**\n   * Cookie expires to store the locale information\n   *\n   * Default: undefined\n   *\n   * Define when the cookie will be removed. Value can be a Number\n   * which will be interpreted as days from time of creation or a\n   * Date instance. If omitted, the cookie becomes a session cookie.\n   */\n  expires?: number | undefined;\n};\n\nconst buildCookieString = (\n  name: string,\n  value: string,\n  attributes: Omit<CookiesAttributes, 'name' | 'type'>\n): string => {\n  const encodedValue = encodeURIComponent(value);\n  const parts: string[] = [`${name}=${encodedValue}`];\n\n  if (attributes.path) parts.push(`Path=${attributes.path}`);\n  if (attributes.domain) parts.push(`Domain=${attributes.domain}`);\n  if (attributes.expires instanceof Date)\n    parts.push(`Expires=${attributes.expires.toUTCString()}`);\n\n  if (attributes.secure) parts.push('Secure');\n  if (attributes.sameSite) parts.push(`SameSite=${attributes.sameSite}`);\n  return parts.join('; ');\n};\n\nexport type LocaleStorageOptions = {\n  overwrite?: boolean;\n  isCookieEnabled?: boolean;\n  setCookieStore?: (\n    name: string,\n    value: string,\n    cookie: CookieBuildAttributes\n  ) => void;\n  setCookieString?: (name: string, cookie: string) => void;\n  getCookie?: (name: string) => string | undefined | null;\n  setSessionStorage?: (name: string, value: string) => void;\n  getSessionStorage?: (name: string) => string | undefined | null;\n  setLocaleStorage?: (name: string, value: string) => void;\n  getLocaleStorage?: (name: string) => string | undefined | null;\n  getHeader?: (name: string) => string | undefined | null;\n  setHeader?: (name: string, value: string) => void;\n};\n\n/**\n * Retrieves the locale from various storage mechanisms (cookies, localStorage, sessionStorage, headers).\n * The function checks storage locations in order of priority as defined in the configuration.\n *\n * @returns The locale if found in any storage, or undefined if not found\n */\nexport const getLocaleFromStorage = (\n  options: Pick<\n    LocaleStorageOptions,\n    | 'getCookie'\n    | 'getSessionStorage'\n    | 'getLocaleStorage'\n    | 'getHeader'\n    | 'isCookieEnabled'\n  >\n): Locale | undefined => {\n  const { routing, internationalization } = configuration;\n  const { locales } = internationalization;\n  const { storage } = routing;\n\n  // If storage is disabled, return undefined\n  if (storage === false || options?.isCookieEnabled === false) return undefined;\n\n  const storageAttributes = getStorageAttributes(storage);\n\n  const isValidLocale = (value: string | null | undefined): value is Locale => {\n    if (!value) return false;\n\n    return locales.includes(value as Locale);\n  };\n\n  const readCookie = (name: string): string | undefined => {\n    // Prefer provided getter (server or custom environment)\n    try {\n      const fromOption = options?.getCookie?.(name);\n\n      if (fromOption !== null && fromOption !== undefined) return fromOption;\n    } catch {}\n\n    // Fallback to browser cookie parsing\n    return getCookie(name);\n  };\n\n  // 1) Check cookies first\n  for (let i = 0; i < storageAttributes.cookies.length; i++) {\n    const { name } = storageAttributes.cookies[i];\n\n    const value = readCookie(name);\n\n    if (isValidLocale(value)) return value;\n  }\n\n  // 2) Then check localStorage candidates (browser only)\n  for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n    const { name } = storageAttributes.localStorage[i];\n\n    try {\n      const value = options?.getLocaleStorage?.(name);\n\n      if (isValidLocale(value)) return value;\n    } catch {}\n  }\n\n  // 3) Check sessionStorage candidates (browser only)\n  for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n    const { name } = storageAttributes.sessionStorage[i];\n\n    try {\n      const value = options?.getSessionStorage?.(name);\n\n      if (isValidLocale(value)) return value;\n    } catch {}\n  }\n\n  // 4) Finally check header candidates (server only)\n  for (let i = 0; i < storageAttributes.headers.length; i++) {\n    const { name } = storageAttributes.headers[i];\n\n    try {\n      const value = options?.getHeader?.(name);\n\n      if (isValidLocale(value)) return value;\n    } catch {}\n  }\n};\n\n/**\n * Stores the locale in various storage mechanisms (cookies, localStorage, sessionStorage, headers).\n * The function writes to all configured storage locations according to their attributes.\n * Respects overwrite flags for localStorage and sessionStorage.\n *\n * @param locale - The locale to store\n */\nexport const setLocaleInStorage = (\n  locale: LocalesValues,\n  options?: LocaleStorageOptions\n): void => {\n  // If storage is disabled, do nothing\n  if (\n    configuration.routing.storage === false ||\n    options?.isCookieEnabled === false\n  )\n    return;\n\n  const storageAttributes = getStorageAttributes(configuration.routing.storage);\n\n  // Write to cookies (server via setCookie, client via cookieStore/document)\n  for (let i = 0; i < storageAttributes.cookies.length; i++) {\n    const { name, attributes } = storageAttributes.cookies[i];\n\n    try {\n      if (options?.setCookieStore) {\n        options?.setCookieStore?.(name, locale, {\n          ...attributes,\n          expires:\n            attributes.expires instanceof Date\n              ? attributes.expires.getTime()\n              : attributes.expires,\n        });\n      }\n    } catch {\n      try {\n        if (options?.setCookieString) {\n          const cookieString = buildCookieString(name, locale, attributes);\n\n          options?.setCookieString?.(name, cookieString);\n        }\n      } catch {}\n    }\n  }\n\n  // Write to localStorage (browser only)\n  if (options?.setLocaleStorage) {\n    for (let i = 0; i < storageAttributes.localStorage.length; i++) {\n      const { name } = storageAttributes.localStorage[i];\n\n      try {\n        const shouldOverwrite = options?.overwrite ?? true;\n\n        if (!shouldOverwrite && options?.getLocaleStorage) {\n          const existing = options?.getLocaleStorage?.(name);\n          if (existing) continue;\n        }\n        options?.setLocaleStorage?.(name, locale);\n      } catch {}\n    }\n  }\n\n  // Write to sessionStorage (browser only)\n  if (options?.setSessionStorage) {\n    for (let i = 0; i < storageAttributes.sessionStorage.length; i++) {\n      const { name } = storageAttributes.sessionStorage[i];\n\n      try {\n        const shouldOverwrite = options?.overwrite ?? true;\n\n        if (!shouldOverwrite && options?.getSessionStorage) {\n          const existing = options?.getSessionStorage?.(name);\n          if (existing) continue;\n        }\n\n        options?.setSessionStorage?.(name, locale);\n      } catch {}\n    }\n  }\n\n  // Write to headers (server only)\n  if (options?.setHeader) {\n    for (let i = 0; i < storageAttributes.headers.length; i++) {\n      const { name } = storageAttributes.headers[i];\n\n      try {\n        options?.setHeader?.(name, locale);\n      } catch {}\n    }\n  }\n};\n\n/**\n * Utility object to get and set the locale in the storage by considering the configuration\n *\n * @property getLocale - Retrieves the locale from various storage mechanisms (cookies, localStorage, sessionStorage, headers).\n * Retrieves the locale from various storage mechanisms (cookies, localStorage, sessionStorage, headers).\n * The function checks storage locations in order of priority as defined in the configuration.\n *\n * @property setLocale - Stores the locale in various storage mechanisms (cookies, localStorage, sessionStorage, headers).\n * The function writes to all configured storage locations according to their attributes.\n * Respects overwrite flags for localStorage and sessionStorage.\n *\n * @returns The locale if found in any storage, or undefined if not found\n */\nexport const LocaleStorage = (options: LocaleStorageOptions) => ({\n  getLocale: () => getLocaleFromStorage(options),\n  setLocale: (locale: LocalesValues) => setLocaleInStorage(locale, options),\n});\n"],"mappings":"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"}