{
  "version": 3,
  "sources": ["../src/mod.ts", "../src/util/asserts.ts", "../src/util/guards.ts", "../src/util/once.ts", "../src/util/url.ts", "../src/config.ts", "../src/query.ts", "../src/notification.ts", "../src/helpers/type.ts", "../src/session.ts"],
  "sourcesContent": ["import { type Config, type NotificationConfig, resolveConfig, resolveNotificationConfig } from './config.ts';\nimport { Query } from './query.ts';\nimport { Notification } from './notification.ts';\n\n\n/**\n * Initialization for interacting with the Elevate Storefront API\n * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/\n */\nexport function elevate(config: Config) {\n  const resolvedConfig = resolveConfig(config);\n\n  return Object.freeze({\n    /** The base URL to the Elevate cluster hosting the API */\n    clusterUrl: resolvedConfig.clusterUrl,\n    /** Send queries to retrieve products, facets and more */\n    query: new Query(resolvedConfig),\n    /** Send notifications for clicks, add-to-carts and more */\n    notify: new Notification(resolvedConfig)\n  });\n}\n\n/**\n * @deprecated eSales has changed name to Elevate.\n * @see https://docs.elevate.voyado.cloud/elevate/4/changelog/#esales-is-voyado-elevate\n */\nexport const esales = elevate;\n\n/**\n * Initialization for interacting with the Elevate Storefront Queries API\n * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/\n */\nexport function queries(config: Config) {\n  return new Query(resolveConfig(config));\n}\n\n/**\n * Initialization for interacting with the Elevate Storefront Notifications API\n * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/\n */\nexport function notifications(config: NotificationConfig) {\n  return new Notification(resolveNotificationConfig(config));\n}\n\n\n// Export Typescript interfaces/types\nexport * from './models/mod.ts';\nexport type { Config, NotificationConfig, Session, SessionMetadata, Touchpoint } from './config.ts';\n\n// Helper functions\nexport * from './helpers/mod.ts';\nexport { type LocalStorageSession, localStorageBackedSession } from './session.ts';\n", "export class AssertionError extends Error {\n  override name = 'AssertionError';\n  constructor(message: string) {\n    super(message);\n  }\n}\n\n/** Asserts that the provided condition is truthy */\nexport function assert(condition: unknown, message = ''): asserts condition {\n  if (!condition) throw new AssertionError(message);\n}\n\n/** Asserts that the provided value is a non-empty string */\nexport function assertString(value: unknown, message?: string): asserts value is string {\n  assert(typeof value === 'string' && value.length > 0, message);\n}\n", "/** Returns `true` if provided value is not `undefined | null` */\nexport function isDefined<T>(value: T): value is NonNullable<T> {\n  return value != null;\n}\n\n/** Returns `true` if provided value is a non-empty string */\nexport function isString(value: unknown): value is string {\n  return typeof value === 'string' && value.length > 0;\n}\n", "/**\n * Only ever execute the supplied function once. Subsequent calls\n * will return the value from the first invocation.\n */\nexport function once<T extends (...args: unknown[]) => unknown>(method: T): T {\n  let executed = false;\n  let returnValue: unknown;\n\n  return function onceInner(this: unknown, ...args: unknown[]) {\n    if (!executed) {\n      executed = true;\n      returnValue = method.apply(this, args);\n    }\n    return returnValue;\n  } as T;\n}\n", "import type { BaseOptions } from '../config.ts';\nimport type { FacetParams } from '../mod.ts';\nimport { isDefined } from './guards.ts';\n\n\n/** Convert interface to a record-type, to allow passing it to index-signature methods */\nexport type Type<T extends object> = Record<keyof T, T[keyof T]>;\nexport type UrlParams = Record<string, PrimitiveParam>;\nexport type PrimitiveParam = string | number | boolean | string[] | number[] | boolean[] | null | undefined;\n\nexport class ResponseError extends Error {\n  constructor(readonly details: { message: string }) {\n    super(details.message);\n  }\n}\n\n/**\n * Creates the base URL for the Elevate server, including required parameters such as:\n * - customerKey\n * - sessionKey\n * - market\n */\nexport async function createBaseUrl(endpoint: `queries/${string}` | `notifications/${string}`, config: BaseOptions) {\n  const { market, clusterUrl, session } = config;\n  const { customerKey, sessionKey } = await session();\n  const url = new URL(`/api/storefront/v3/${endpoint}`, clusterUrl);\n\n  addUrlParams(url, { market, customerKey, sessionKey });\n\n  return url;\n}\n\n/**\n * Converts arrays of parameters into pipe separated values,\n * and adds their values to the provided URL object.\n */\nexport function addUrlParams(url: URL, params: UrlParams) {\n  for (const [key, value] of Object.entries(params)) {\n    if (isDefined(value)) {\n      const values = Array.isArray(value) ? value : [value];\n      url.searchParams.set(key, values.map(String).join('|'));\n    }\n  }\n}\n\n/** Converts `facets` parameter to a `UrlParams` object */\nexport function facetsToParams(facets: FacetParams = {}) {\n  const result: UrlParams = {};\n  for (const [name, value] of Object.entries(facets)) {\n    if (Array.isArray(value) || typeof value !== 'object') {\n      result[`f.${name}`] = value;\n    } else {\n      // TODO(csv): skip checking for undefined? Already filtered in `addUrlParams()`\n      if (isDefined(value.min)) result[`f.${name}.min`] = value.min;\n      if (isDefined(value.max)) result[`f.${name}.max`] = value.max;\n    }\n  }\n  return result;\n}\n", "import { assert, assertString } from './util/mod.ts';\n\n\n/** Used to determine server settings to use. */\ntype Touchpoint = 'desktop' | 'mobile';\n\n/** Session is used to handle session information for a specific visitor. */\ninterface Session {\n  /**\n   * Method for retrieving session information, synchronously\n   * or asynchronously. Returns a `SessionMetadata` object that\n   * contains `customerKey` and `sessionKey`.\n   *\n   * @example\n   * ```ts\n   * declare const session: Session;\n   *\n   * const { customerKey, sessionKey } = await session();\n   * ```\n   */\n  (): SessionMetadata | Promise<SessionMetadata>;\n}\n\n/** Metadata information regarding a visitor, used during requests to the Elevate Storefront API. */\ninterface SessionMetadata {\n  /**\n   * A key that uniquely identifies the current visitor. Using UUIDs as keys are recommended.\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/common/query-parameters/#mandatory-parameters\n   */\n  customerKey: string;\n  /**\n   * A unique key, identifying the session. Using UUIDs as keys are recommended.\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/common/query-parameters/#mandatory-parameters\n   */\n  sessionKey: string;\n}\n\n/**\n * Configuration required during initialization for the Elevate Storefront API.\n *\n * @example\n * ```ts\n * const config: Config = { ... };\n * const api = elevate(config);\n * ```\n */\ninterface Config {\n  /**\n   * The ID for the Elevate cluster for all subsequent API requests.\n   * Production/Test/Development clusters each have their own unique ID.\n   * The value for `clusterId` can be found in credentials tab in\n   * the Voyado Elevate app,\n   *\n   * The value should be:\n   * - An identifier in a format similar to `'w00000000'`\n   * - A URL with the origin to the Elevate cluster, e.g.\n   *   `'https://w00000000.api.esales.apptus.cloud/'`\n   *\n   * @example\n   * ```ts\n   * const api = elevate({ clusterId: 'w00000000' });\n   * ```\n   */\n  clusterId: string;\n  /** Required for loading correct products and behavior data. */\n  market: string;\n  /** Required for loading localized product and facet data. */\n  locale: string;\n  /** Used to determine various server settings. */\n  touchpoint: Touchpoint;\n  /** Configures how session metadata (customerKey & sessionKey) is retrieved before requests to the API */\n  session: Session;\n}\n\n/**\n * Subset of Config for interacting with the Notifications API.\n * @see Config\n */\ntype NotificationConfig = Pick<Config, 'clusterId' | 'market' | 'session'>;\n\n/**\n * Created from a validated `Config`. Used internally.\n * @internal\n */\ninterface BaseOptions extends Omit<NotificationConfig, 'clusterId'> {\n  clusterUrl: string;\n}\n\n/**\n * Created from a validated `Config`. Used internally.\n * @internal\n */\ninterface FullOptions extends Omit<Config, 'clusterId'> {\n  clusterUrl: string;\n}\n\nfunction validateBaseConfig(config: unknown): asserts config is NotificationConfig {\n  assert(typeof config === 'object' && config !== null, 'API config must be an \"object\"');\n\n  const c: Partial<NotificationConfig> = config;\n\n  assertString(c.clusterId, 'Property \"clusterId\" must be a non-empty string');\n  assertString(c.market, 'Property \"market\" must be a non-empty string');\n  assert(typeof c.session === 'function', 'Property \"session\" must be a method.');\n}\n\n/**\n * Validates that user supplied config is in a correct format. `unknown` is used as parameter\n * value to indicate that we do not yet trust the user input.\n *\n * @param config raw configuration for creating the API library to be validated\n */\nexport function validateConfig(config: unknown): asserts config is Config {\n  validateBaseConfig(config);\n\n  const c: Partial<Config> = config;\n  const touchpoints: Touchpoint[] = ['desktop', 'mobile'];\n\n  assertString(c.locale, 'Property \"locale\" must be a string and valid locale, e.g. \"en-US\".');\n  assert(touchpoints.includes(c.touchpoint!), `Property \"touchpoint\" must be one of: ${touchpoints.join(', ')}`);\n}\n\nfunction resolveClusterUrl<T extends NotificationConfig>(config: T) {\n  const { clusterId, ...rest } = config;\n\n  const clusterUrl = (() => {\n    /** Ensures consistent casing and trailing slash of URL's */\n    const normalizeUrl = (url: string) => new URL(url).href;\n\n    try {\n      // Will throw for invalid URL, and normalize trailing slash\n      return normalizeUrl(clusterId);\n    } catch { /* empty */ }\n    return normalizeUrl(`https://${clusterId}.api.esales.apptus.cloud/`);\n  })();\n\n  return { ...rest, clusterUrl };\n}\n\n/** Prepares user-supplied configuration for internal use. */\nexport function resolveConfig(config: Config): FullOptions {\n  // TODO(csv): Allow this code to be removed in a production build?\n  validateConfig(config);\n  return resolveClusterUrl(config);\n}\n\n/** Prepares user-supplied configuration for internal use. */\nexport function resolveNotificationConfig(config: NotificationConfig): BaseOptions {\n  // TODO(csv): Allow this code to be removed in a production build?\n  validateBaseConfig(config);\n  return resolveClusterUrl(config);\n}\n\nexport type { Config, NotificationConfig, BaseOptions, FullOptions, Session, SessionMetadata, Touchpoint };\n", "import { assert, addUrlParams, createBaseUrl, facetsToParams, ResponseError, type Type, type UrlParams } from './util/mod.ts';\nimport type { FullOptions } from './config.ts';\nimport type { FacetParams } from './mod.ts';\nimport type * as m from './models/mod.ts';\n\n\nexport class Query {\n  constructor(private readonly __config: FullOptions) {}\n\n  /**\n   * Retrieve recommendations for a product that has just been added to the cart.\n   *\n   * @param params query parameter options to submit\n   * @param body configuration options to submit\n   *\n   * @example\n   * ```ts\n   * const res = await api.query.addToCartPopup({ variantKey: 'variant-key-123' }, {\n   *   recommendationLists: [{\n   *     id: 'addons',\n   *     algorithm: 'ADD_TO_CART_RECS'\n   *   }]\n   * });\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/add-to-cart-popup/\n   */\n  addToCartPopup(params: m.AddToCartPopupParams, recommendationLists: m.AddToCartPopupBody) {\n    return this.__query<m.AddToCartPopup>('add-to-cart-popup', {\n      params: params as Type<m.AddToCartPopupParams>,\n      body: { recommendationLists }\n    });\n  }\n\n  /**\n   * Autocomplete based on provided query parameter, for search suggestions,\n   * product suggestions, and more.\n   *\n   * @param params query parameter options to submit\n   * @param body configuration options to submit\n   *\n   * @example\n   * ```ts\n   * const res = await api.query.autocomplete({ q: 'shirt' });\n   * const sale = await api.query.autocomplete({ q: 'dress' }, {\n   *   productFilter: { discount: 50 }\n   * p});\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/autocomplete/\n   */\n  autocomplete(params: m.AutocompleteParams, body?: m.AutocompleteBody) {\n    return this.__query<m.Autocomplete>('autocomplete', { params: params as Type<m.AutocompleteParams>, body });\n  }\n\n  /**\n   * Retrieve the complete navigation tree, suitable for a top/mobile navigation of the site.\n   *\n   * @param params query parameter options to submit\n   *\n   * @example\n   * ```ts\n   * const tree = await api.query.navigationTree();\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/navigation-tree/\n   */\n  navigationTree(params?: m.NavigationTreeParams) {\n    return this.__query<m.NavigationTree>('navigation-tree', { params: params as Type<m.NavigationTreeParams> });\n  }\n\n  /**\n   * Returns a product listing with facets based on provided query, optionally\n   * with related navigation included.\n   *\n   * @param params query parameter options to submit\n   * @param body configuration options to submit\n   *\n   * @example\n   * ```ts\n   * const res = await api.query.searchPage({ q: 'shirt' });\n   * const sale = await api.query.searchPage({ q: 'dress' }, {\n   *   primaryList: {\n   *     productFilter: { discount: 50 }\n   *   },\n   *   navigation: { include: true }\n   * });\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/search-page/\n   */\n  searchPage(params: m.SearchPageParams, body?: m.SearchPageBody) {\n    const { facets, ...p } = params;\n    return this.__query<m.SearchPage>('search-page', { facets, params: { ...p }, body });\n  }\n\n  /**\n   * Retrieves product information and related info suitable to show on a Product page.\n   * Can be configured to show various recommendation lists based on body configuration settings.\n   *\n   * @param params query parameter options to submit\n   * @param body configuration options to submit\n   *\n   * @example\n   * ```ts\n   * const res = await api.query.productPage({ productKey: 'p123' }, {\n   *   recommendationLists: [{\n   *     id: 'alts',\n   *     algorithm: 'ALTERNATIVES'\n   *   }]\n   * });\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/product-page/\n   */\n  productPage(params: m.ProductPageParams, body?: m.ProductPageBody) {\n    return this.__query<m.ProductPage>('product-page', { params: params as Type<m.ProductPageParams>, body });\n  }\n\n  /**\n   * Retrieve products - and possibly recommendation lists - suitable for display\n   * on a cart page.\n   *\n   * @param params query parameter options to submit\n   * @param body configuration options to submit\n   *\n   * @example\n   * ```ts\n   * const res = await api.query.cartPage({ cart: ['p123', 'p456'] }, {\n   *   recommendationLists: [{\n   *     id: 'addons',\n   *     algorithm: 'CART'\n   *   }]\n   * });\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/cart-page/\n   */\n  cartPage(params: m.CartPageParams, body?: m.CartPageBody) {\n    return this.__query<m.CartPage>('cart-page', { params: params as Type<m.CartPageParams>, body });\n  }\n\n  /**\n   * Request for generic landing pages, or category pages. Can return product listing with facets,\n   * recommendation lists, or both. Suitable for the start/home page, intermediate category pages,\n   * brand pages, and more.\n   *\n   * @param params query parameter options to submit\n   * @param body configuration options to submit\n   *\n   * @example\n   * ```ts\n   * const res = await api.query.landingPage();\n   * const sale = await api.query.landingPage({ limit: 30, skip: 0 }, {\n   *   primaryList: {\n   *     productFilter: { discount: 50 }\n   *   },\n   *   recommendationLists: [{\n   *     id: 'personal',\n   *     algorithm: 'PERSONAL'\n   *   }]\n   * });\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/landing-page/\n   */\n  landingPage(params: m.LandingPageParams = {}, body?: m.LandingPageBody) {\n    const { facets, ...p } = params;\n    return this.__query<m.LandingPage>('landing-page', { facets, params: { ...p }, body });\n  }\n\n  /**\n   * Request for retrieving a list of sponsored products for a Page.\n   *\n   * @beta \u26A0\uFE0F This request is currently limited to a private beta and will fail otherwise.\n   *\n   * @param params query parameter options to submit\n   *\n   * @example\n   * ```ts\n   * const res = await api.query.sponsoredPage({\n   *   pageReference: '/women/tops'\n   * });\n   * ```\n   * @see https://docs.apptus.com/elevate/4/integration/api/specifications/storefront/v3/queries/sponsored-page/\n   */\n  sponsoredPage(params: m.SponsoredPageParams) {\n    return this.__query<m.SponsoredPage>('sponsored-page', { params: params as Type<m.SponsoredPageParams> });\n  }\n\n  /**\n   * Mirrors the Product Page, but for Content instead of Products. Retrieves content\n   * information for the provided `contentKeys` (required).\n   *\n   * @param params query parameter options to submit\n   *\n   * @example\n   * ```ts\n   * const res = await api.query.contentInformation({\n   *   contentKeys: ['ck_123456', 'ck_234567']\n   * });\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/content-information/\n   */\n  contentInformation(params: m.ContentInformationParams) {\n    return this.__query<m.ContentInformation>('content-information', { params: params as Type<m.ContentInformationParams> });\n  }\n\n  /**\n   * Mirrors the Search Page request, but for Content instead of Products. Returns content\n   * results matching the provided query. Suiteable for searching in e.g. FAQ or customer service,\n   * where no product results are required.\n   *\n   * @param params query parameter options to submit\n   * @param body configuration options to submit\n   *\n   * @example\n   * ```ts\n   * const res = await this.contentSearchPage({ q: 'returns' });\n   * ```\n   * @example\n   * ```ts\n   * const res = await this.contentSearchPage({ q: 'shipping', skip: 20 }, {\n   *   primaryList: {\n   *     contentFilter: {\n   *       type: 'faq'\n   *     }\n   *   }\n   * });\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/queries/content-search-page/\n   */\n  contentSearchPage(params: m.ContentSearchPageParams, body?: m.ContentSearchPageBody) {\n    return this.__query<m.ContentSearchPage>('content-search-page', { params: params as Type<m.ContentSearchPageParams>, body });\n  }\n\n  private async __query<T>(endpoint: string, options: { params?: UrlParams, facets?: FacetParams, body?: object }) {\n    const { params = {}, facets, body } = options;\n    assert(typeof params === 'object', 'If provided, params must be an object');\n\n    const url = await createBaseUrl(`queries/${endpoint}`, this.__config);\n    const { locale, touchpoint } = this.__config;\n    addUrlParams(url, { locale, touchpoint, ...params, ...facetsToParams(facets) });\n\n    const init: RequestInit = !body ?\n      { method: 'GET' } :\n      { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body: JSON.stringify(body) };\n    const res = await fetch(url, init);\n    const content = await res.json();\n\n    // TODO: res.ok\n    if (res.status >= 200 && res.status < 400) {\n      return content as T;\n    }\n\n    throw new ResponseError(content);\n  }\n}\n", "import { assert, createBaseUrl } from './util/mod.ts';\nimport type { BaseOptions } from './config.ts';\nimport type { FavoritePayload } from './models/notifications.ts';\n\n\nexport class Notification {\n  constructor(private readonly __config: BaseOptions) {}\n\n  /**\n   * Send click notification with ticket. Tries to queue fetch\n   * request with `keepalive` option, with one retry if it fails.\n   *\n   * @param ticket is present on product and variant\n   *\n   * @example\n   * ```ts\n   * await api.notify.click('OzE7cHJ...yM7Mjg7');\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/notifications/click/\n   */\n  click(ticket: string) {\n    return this.__notification('click', { ticket });\n  }\n\n  /**\n   * Send impression notification. Tries to queue fetch\n   * request with `keepalive` option, with one retry if it fails.\n   *\n   * @beta \u26A0\uFE0F This request is currently limited to a private beta and will fail otherwise.\n   *\n   * @param ticket attached to a sponsored product or list\n   *\n   * @example\n   * ```ts\n   * await api.notify.adImpression('OzE7cHJ...yM7Mjg7');\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/notifications/ad-impression/\n   */\n  adImpression(ticket: string) {\n    return this.__notification('ad-impression', { ticket });\n  }\n\n  /**\n   * Send add to cart notification with ticket. Tries to queue fetch\n   * request with `keepalive` option, with one retry if it fails.\n   *\n   * @param ticket is present on product and variant\n   *\n   * @example\n   * ```ts\n   * await api.notify.addToCart('OzE7cHJ...jOzI4Ow');\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/notifications/add-to-cart/\n   */\n  addToCart(ticket: string) {\n    return this.__notification('add-to-cart', { ticket });\n  }\n\n   /**\n   * Send add favorite notification with product-key. Tries to queue fetch\n   * request with `keepalive` option, with one retry if it fails.\n   *\n   * @param productKeyOrPayload a `Product.key` or object with variant or product key\n   *\n   * @example\n   * ```ts\n   * await api.notify.addFavorite('pk_123456');\n   * await api.notify.addFavorite({ variantKey: 'vk_234567' });\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/notifications/add-favorite/\n   */\n  addFavorite(productKeyOrPayload: string | FavoritePayload) {\n    const body = typeof productKeyOrPayload === 'string' ?\n      { productKey: productKeyOrPayload } : productKeyOrPayload;\n    return this.__notification('add-favorite', body);\n  }\n\n  /**\n   * Send remove favorite notification with product-key. Tries to queue fetch\n   * request with `keepalive` option, with one retry if it fails.\n   *\n   * @param productKeyOrPayload a `Product.key` or object with variant or product key\n   *\n   * @example\n   * ```ts\n   * await api.notify.removeFavorite('pk_123456');\n   * await api.notify.removeFavorite({ variantKey: 'vk_234567' });\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/notifications/remove-favorite/\n   */\n  removeFavorite(productKeyOrPayload: string | FavoritePayload) {\n    const body = typeof productKeyOrPayload === 'string' ?\n      { productKey: productKeyOrPayload } : productKeyOrPayload;\n    return this.__notification('remove-favorite', body);\n  }\n\n  /**\n   * Send a notification to remove recent searches for the current `customerKey`.\n   *\n   * The values in the array should match values on `RecentSearch.q` returned\n   * from `Autocomplete.recentSearches`, to ensure they are removed correctly.\n   *\n   * Tries to queue fetch request with `keepalive` option, with one retry if it fails.\n   *\n   * @param phrases An array of recent search phrases to remove or the string 'removeAll' to remove all phrases.\n   *\n   * @example\n   * ```ts\n   * await api.notify.removeRecentSearches('removeAll');\n   * await api.notify.removeRecentSearches(['gift card']);\n   * await api.notify.removeRecentSearches(['dress', 'jacket', 'shoes']);\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/notifications/remove-recent-searches/\n   */\n  removeRecentSearches(phrases: string[] | 'removeAll') {\n    return this.__notification('remove-recent-searches', phrases === 'removeAll' ?\n      { removeAll: true } : { phrases });\n  }\n\n  /**\n   * Send a notification to remove recently viewed products for the current `customerKey`.\n   *\n   * When removing individual products, `Product.key` should be used as ID for specific products\n   * to remove from Recently viewed.\n   *\n   * Tries to queue fetch request with `keepalive` option, with one retry if it fails.\n   *\n   * @param productKeys An array of productKeys to remove or the string 'removeAll' to remove all products.\n   *\n   * @example\n   * ```ts\n   * await api.notify.removeRecentlyViewed('removeAll');\n   * await api.notify.removeRecentlyViewed(['pk_123456']);\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/notifications/remove-recently-viewed/\n   */\n  removeRecentlyViewed(productKeys: string[] | 'removeAll') {\n    return this.__notification('remove-recently-viewed', productKeys === 'removeAll' ?\n      { removeAll: true } : { productKeys });\n  }\n\n  /**\n   * Send end notification. Tries to queue fetch request with `keepalive` option,\n   * with one retry if it fails.\n   *\n   * @example\n   * ```ts\n   * await api.notify.end();\n   * ```\n   * @see https://docs.elevate.voyado.cloud/elevate/4/integration/api/specifications/storefront/v3/notifications/end/\n   */\n  end() {\n    return this.__notification('end');\n  }\n\n  private async __notification(endpoint: string, body?: object) {\n    const send = async (keepalive: boolean) => {\n      const url = await createBaseUrl(`notifications/${endpoint}`, this.__config);\n      const data = body ? JSON.stringify(body) : undefined;\n      const res = await fetch(url, { method: 'POST', body: data, keepalive });\n      assert(res.ok);\n    };\n\n    try {\n      await send(true);\n    } catch {\n      // TODO(csv): Add `this.__config` option to skip retrying without keepalive?\n      // E.g. `Config.notificationMode: 'keepaliveWithRetry' | 'keepalive' | 'regular'\n\n      // Retry without `keepalive`\n      await send(false);\n    }\n  }\n}\n", "import type { CheckboxFacet, ColorFacet, Facet, RangeFacet, SizeFacet, TextFacet } from '../models/mod.ts';\n\n\n/** Will return `true` if the provided facet is a text facet */\nexport const isTextFacet = (facet: Facet): facet is TextFacet => facet.type === 'TEXT';\n\n/** Will return `true` if the provided facet is a color facet */\nexport const isColorFacet = (facet: Facet): facet is ColorFacet => facet.type === 'COLOR';\n\n/** Will return `true` if the provided facet is a range facet */\nexport const isRangeFacet = (facet: Facet): facet is RangeFacet => facet.type === 'RANGE';\n\n/** Will return `true` if the provided facet is a size facet */\nexport const isSizeFacet = (facet: Facet): facet is SizeFacet => facet.type === 'SIZE';\n\n/** Will return `true` if the provided facet is a checkbox facet */\nexport const isCheckboxFacet = (facet: Facet): facet is CheckboxFacet => facet.type === 'CHECKBOX';\n", "import { assert, assertString, once, isString } from './util/mod.ts';\nimport type { Session, SessionMetadata } from './config.ts';\n\n\n/** Helps retrieve and update session metadata and persist it in LocalStorage. */\nexport interface LocalStorageSession extends Session {\n  /**\n   * Method for retrieving session information synchronously\n   * from `LocalStorage`. Returns a `SessionMetadata` object that\n   * contains `customerKey` and `sessionKey`.\n   *\n   * @example\n   * ```ts\n   * declare const session: LocalStorageSession;\n   *\n   * const { customerKey, sessionKey } = session();\n   * ```\n   */\n  (): SessionMetadata;\n  /**\n   * Generates new customer- & sessionKeys via `crypto.randomUUID()` and persists them.\n   * Suitable to use e.g. when a visitor logs out.\n   */\n  reset(): void;\n  /**\n   * Updates the `customerKey` to the provided value and persists it.\n   * Suitable to use e.g. when a visitor is identified by signing in to their account.\n   */\n  updateCustomerKey(key: string): void;\n}\n\nconst __storage: Storage = /* @__PURE__ */ (() => globalThis.localStorage)();\n\n/** @internal exported for testing */\nexport const __sessionMetadataCache = new Map<string, SessionMetadata>();\n\n/**\n * Create a `Session` compatible object for retrieving and mutating session metadata.\n * This method is only intended to be used in Browsers.\n *\n * Storage is backed by LocalStorage, where reads/writes will happen. Reads are cached\n * in memory, and invalidated by `storage` events on Window. This method can be called\n * multiple times, but shares Window listener between them.\n *\n * If session information does not exist, customer- & sessionKeys will be generated\n * automatically via `crypto.randomUUID()`.\n *\n * @param storageKey - The key that will be used to store session metadata. Defaults to `'voyado.session'`.\n *\n * @example\n * ```ts\n * import { elevate, localStorageBackedSession } from '@apptus/esales-api';\n *\n * const api = elevate({\n *   // ...\n *   session: localStorageBackedSession()\n * });\n * ```\n * @example\n * ```ts\n * const session = localStorageBackedSession();\n *\n * // Set a specific customerKey (e.g. on visitor sign-in)\n * session.updateCustomerKey(user.id);\n *\n * // Generate new customer/sessionKeys (e.g. on visitor signout)\n * session.reset();\n * ```\n */\nexport function localStorageBackedSession(storageKey = 'voyado.session'): LocalStorageSession {\n  enableCachePruning();\n\n  const fetcher = () => read(storageKey);\n  fetcher.updateCustomerKey = (customerKey: string) => update(storageKey, { ...fetcher(), customerKey });\n  fetcher.reset = () => update(storageKey, generateSession());\n\n  return fetcher;\n}\n\nconst enableCachePruning = /* @__PURE__ */ once(() => {\n  globalThis.addEventListener('storage', ({ key, storageArea }: StorageEvent) => {\n    if (key && storageArea === __storage) __sessionMetadataCache.delete(key);\n  });\n});\n\nfunction generateSession(): SessionMetadata {\n  return { customerKey: crypto.randomUUID(), sessionKey: crypto.randomUUID() };\n}\n\nfunction read(key: string): SessionMetadata {\n  // Update cached value by reading from LocalStorage if needed\n  if (!__sessionMetadataCache.has(key)) {\n    const strData = __storage.getItem(key);\n    const session = generateSession();\n\n    try {\n      assertString(strData);\n\n      const d: unknown = JSON.parse(strData);\n      assert(d && typeof d === 'object');\n\n      if ('customerKey' in d && isString(d.customerKey)) session.customerKey = d.customerKey;\n      if ('sessionKey' in d && isString(d.sessionKey)) session.sessionKey = d.sessionKey;\n\n      update(key, session, strData);\n    } catch {\n      update(key, session);\n    }\n  }\n\n  return __sessionMetadataCache.get(key)!;\n}\n\nfunction update(key: string, data: SessionMetadata, prevData = '') {\n  updateCache(key, data);\n  const currData = JSON.stringify(data);\n  if (prevData !== currData) __storage.setItem(key, currData);\n}\n\nfunction updateCache(key: string, data: SessionMetadata) {\n  __sessionMetadataCache.set(key, data);\n}\n"],
  "mappings": "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",
  "names": []
}
