{"version":3,"file":"getStorageAttributes.mjs","names":[],"sources":["../../../src/utils/getStorageAttributes.ts"],"sourcesContent":["import type {\n  CookiesAttributes,\n  ProcessedCookieAttributes,\n  ProcessedStorageAttributes,\n  RoutingStorageInput,\n  StorageAttributes,\n} from '@intlayer/types/config';\nimport {\n  COOKIE_NAME,\n  HEADER_NAME,\n  LOCALE_STORAGE_NAME,\n} from '../defaultValues/routing';\n\n// ============================================================================\n// Types\n// ============================================================================\n\ntype CookieEntry = {\n  name: string;\n  attributes: ProcessedCookieAttributes;\n};\n\n/** Number of seconds in a day, used to convert a `number` of days. */\nconst SECONDS_PER_DAY = 60 * 60 * 24;\n\ntype WebStorageEntry = {\n  name: string;\n};\n\ntype HeaderEntry = {\n  name: string;\n};\n\ntype StorageEntry =\n  | 'cookie'\n  | 'localStorage'\n  | 'sessionStorage'\n  | 'header'\n  | CookiesAttributes\n  | StorageAttributes;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Merges the user-facing `expires` and `maxAge` into a single, normalized and\n * serialization-safe expiry consumed by the client runtime.\n *\n * Precedence and normalization:\n * - `maxAge` (seconds) wins when set and is the internal unit (relative);\n * - `expires` as a `number` is interpreted as **days** and converted to\n *   seconds (relative);\n * - `expires` as a `Date` (possibly a cross-realm instance, since config files\n *   run in a `node:vm` sandbox) or an ISO string becomes an ISO **string**\n *   (absolute). Strings survive `JSON.stringify`, unlike a `Date`.\n *\n * The result is therefore: a `number` = seconds from creation, a `string` =\n * absolute ISO date, or `undefined` for a session cookie.\n */\nconst normalizeCookieExpiry = (\n  expires: CookiesAttributes['expires'],\n  maxAge: CookiesAttributes['maxAge']\n): number | string | undefined => {\n  if (typeof maxAge === 'number') return maxAge;\n  if (expires === undefined) return undefined;\n  if (\n    expires instanceof Date ||\n    Object.prototype.toString.call(expires) === '[object Date]'\n  ) {\n    return (expires as Date).toISOString();\n  }\n  if (typeof expires === 'string') return expires;\n  return expires * SECONDS_PER_DAY;\n};\n\nconst createCookieEntry = (\n  options?: Partial<CookiesAttributes>\n): CookieEntry => {\n  const {\n    name,\n    path = '/',\n    expires,\n    maxAge,\n    domain,\n    secure,\n    sameSite,\n    httpOnly,\n  } = options ?? {};\n  return {\n    name: name ?? COOKIE_NAME,\n    attributes: {\n      path,\n      expires: normalizeCookieExpiry(expires, maxAge),\n      domain,\n      secure,\n      sameSite,\n      httpOnly,\n    },\n  };\n};\n\nconst createWebStorageEntry = (\n  options?: Partial<StorageAttributes>\n): WebStorageEntry => ({\n  name: options?.name ?? LOCALE_STORAGE_NAME,\n});\n\nconst createHeaderEntry = (\n  options?: Partial<StorageAttributes>\n): HeaderEntry => ({\n  name: options?.name ?? HEADER_NAME,\n});\n\nconst isCookieEntry = (entry: unknown): boolean => {\n  if (typeof entry !== 'object' || entry === null) return false;\n  const e = entry as Record<string, unknown>;\n  return (\n    e['type'] === 'cookie' ||\n    'sameSite' in e ||\n    'httpOnly' in e ||\n    'secure' in e\n  );\n};\n\nconst isStorageType = (\n  value: string\n): value is 'cookie' | 'localStorage' | 'sessionStorage' | 'header' =>\n  value === 'cookie' ||\n  value === 'localStorage' ||\n  value === 'sessionStorage' ||\n  value === 'header';\n\n// ============================================================================\n// Main Function\n// ============================================================================\n\nconst processStorageEntry = (\n  entry: StorageEntry\n): Partial<ProcessedStorageAttributes> => {\n  if (typeof entry === 'string') {\n    if (!isStorageType(entry)) {\n      return { cookies: [], localStorage: [], sessionStorage: [], headers: [] };\n    }\n    if (entry === 'cookie') return { cookies: [createCookieEntry()] };\n    if (entry === 'localStorage')\n      return { localStorage: [createWebStorageEntry()] };\n    if (entry === 'sessionStorage')\n      return { sessionStorage: [createWebStorageEntry()] };\n    if (entry === 'header') return { headers: [createHeaderEntry()] };\n  }\n\n  if (typeof entry === 'object' && entry !== null) {\n    const typedEntry = entry as CookiesAttributes | StorageAttributes;\n\n    if (isCookieEntry(typedEntry)) {\n      return { cookies: [createCookieEntry(typedEntry as CookiesAttributes)] };\n    }\n    if ('type' in typedEntry && typedEntry.type === 'localStorage') {\n      return {\n        localStorage: [createWebStorageEntry(typedEntry as StorageAttributes)],\n      };\n    }\n    if ('type' in typedEntry && typedEntry.type === 'sessionStorage') {\n      return {\n        sessionStorage: [\n          createWebStorageEntry(typedEntry as StorageAttributes),\n        ],\n      };\n    }\n    if ('type' in typedEntry && typedEntry.type === 'header') {\n      return { headers: [createHeaderEntry(typedEntry as StorageAttributes)] };\n    }\n    // Default to localStorage for ambiguous objects\n    return {\n      localStorage: [\n        createWebStorageEntry(typedEntry as Omit<StorageAttributes, 'type'>),\n      ],\n    };\n  }\n\n  return { cookies: [], localStorage: [], sessionStorage: [], headers: [] };\n};\n\nconst mergeStorageAttributes = (\n  accumulated: ProcessedStorageAttributes,\n  partial: Partial<ProcessedStorageAttributes>\n): ProcessedStorageAttributes => ({\n  cookies: [...(accumulated.cookies ?? []), ...(partial.cookies ?? [])],\n  localStorage: [\n    ...(accumulated.localStorage ?? []),\n    ...(partial.localStorage ?? []),\n  ],\n  sessionStorage: [\n    ...(accumulated.sessionStorage ?? []),\n    ...(partial.sessionStorage ?? []),\n  ],\n  headers: [...(accumulated.headers ?? []), ...(partial.headers ?? [])],\n});\n\n/**\n * Extracts and normalizes storage configuration into separate arrays for each storage type.\n * Called at config-build time so the result is pre-computed and stored in the config.\n *\n * @param options - The storage configuration from IntlayerConfig\n * @returns An object containing arrays for cookies, localStorage, sessionStorage and headers\n */\nexport const getStorageAttributes = (\n  options: RoutingStorageInput\n): ProcessedStorageAttributes => {\n  const emptyResult: ProcessedStorageAttributes = {\n    cookies: [],\n    localStorage: [],\n    sessionStorage: [],\n    headers: [],\n  };\n\n  if (options === false || options === undefined) return {};\n\n  const result = Array.isArray(options)\n    ? options.reduce<ProcessedStorageAttributes>((acc, entry) => {\n        const partial = processStorageEntry(entry);\n        return mergeStorageAttributes(acc, partial);\n      }, emptyResult)\n    : mergeStorageAttributes(emptyResult, processStorageEntry(options));\n\n  // Remove empty arrays\n  const cleanedResult: ProcessedStorageAttributes = {};\n\n  if (result.cookies && result.cookies.length > 0) {\n    cleanedResult.cookies = result.cookies;\n  }\n\n  if (result.localStorage && result.localStorage.length > 0) {\n    cleanedResult.localStorage = result.localStorage;\n  }\n\n  if (result.sessionStorage && result.sessionStorage.length > 0) {\n    cleanedResult.sessionStorage = result.sessionStorage;\n  }\n\n  if (result.headers && result.headers.length > 0) {\n    cleanedResult.headers = result.headers;\n  }\n\n  return cleanedResult;\n};\n"],"mappings":"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"}