{"version":3,"sources":["../src/provider.tsx","../src/config.ts","../src/modules/helpers.ts","../src/modules/cache.ts"],"sourcesContent":["import React, { createContext, ReactNode, useContext, useState } from 'react';\n\nimport CacheStore from './modules/cache';\n\nconst CacheContext = createContext<CacheStore | null>(null);\n\ninterface Props {\n  children: ReactNode;\n  name?: string;\n}\n\nexport default function CacheProvider({ children, name }: Props) {\n  const [store] = useState(() => new CacheStore({ name, persistent: true }));\n\n  return <CacheContext.Provider value={store}>{children}</CacheContext.Provider>;\n}\n\nexport function useCacheStore(): CacheStore | null {\n  return useContext(CacheContext);\n}\n","export const CACHE_NAME = 'react-inlinesvg';\nexport const CACHE_MAX_RETRIES = 10;\n\nexport const STATUS = {\n  IDLE: 'idle',\n  LOADING: 'loading',\n  LOADED: 'loaded',\n  FAILED: 'failed',\n  READY: 'ready',\n  UNSUPPORTED: 'unsupported',\n} as const;\n","function randomCharacter(character: string) {\n  return character[Math.floor(Math.random() * character.length)];\n}\n\nexport function canUseDOM(): boolean {\n  return !!(typeof window !== 'undefined' && window.document?.createElement);\n}\n\nexport function isSupportedEnvironment(): boolean {\n  return supportsInlineSVG() && typeof window !== 'undefined' && window !== null;\n}\n\n/**\n *  Remove properties from an object\n */\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(\n  input: T,\n  ...filter: K[]\n): Omit<T, K> {\n  const output: any = {};\n\n  for (const key in input) {\n    if ({}.hasOwnProperty.call(input, key)) {\n      if (!filter.includes(key as unknown as K)) {\n        output[key] = input[key];\n      }\n    }\n  }\n\n  return output as Omit<T, K>;\n}\n\nexport function randomString(length: number): string {\n  const letters = 'abcdefghijklmnopqrstuvwxyz';\n  const numbers = '1234567890';\n  const charset = `${letters}${letters.toUpperCase()}${numbers}`;\n\n  let R = '';\n\n  for (let index = 0; index < length; index++) {\n    R += randomCharacter(charset);\n  }\n\n  return R;\n}\n\nexport async function request(url: string, options?: RequestInit) {\n  const response = await fetch(url, options);\n  const contentType = response.headers.get('content-type');\n  const [fileType] = (contentType ?? '').split(/ ?; ?/);\n\n  if (response.status > 299) {\n    throw new Error('Not found');\n  }\n\n  if (!['image/svg+xml', 'text/plain'].some(d => fileType.includes(d))) {\n    throw new Error(`Content type isn't valid: ${fileType}`);\n  }\n\n  return response.text();\n}\n\nexport function supportsInlineSVG(): boolean {\n  /* c8 ignore next 3 */\n  if (!document) {\n    return false;\n  }\n\n  const div = document.createElement('div');\n\n  div.innerHTML = '<svg />';\n  const svg = div.firstChild as SVGSVGElement;\n\n  return !!svg && svg.namespaceURI === 'http://www.w3.org/2000/svg';\n}\n","import { CACHE_MAX_RETRIES, CACHE_NAME, STATUS } from '../config';\nimport { StorageItem } from '../types';\n\nimport { canUseDOM, request } from './helpers';\n\nexport interface CacheStoreOptions {\n  name?: string;\n  persistent?: boolean;\n}\n\nexport default class CacheStore {\n  private cacheApi: Cache | undefined;\n  private readonly cacheStore: Map<string, StorageItem>;\n  private readonly subscribers: Array<() => void> = [];\n  public isReady = false;\n\n  constructor(options: CacheStoreOptions = {}) {\n    const { name = CACHE_NAME, persistent = false } = options;\n\n    this.cacheStore = new Map<string, StorageItem>();\n\n    const usePersistentCache = persistent && canUseDOM() && 'caches' in window;\n\n    if (usePersistentCache) {\n      // eslint-disable-next-line promise/catch-or-return\n      caches\n        .open(name)\n        .then(cache => {\n          this.cacheApi = cache;\n        })\n        .catch(error => {\n          // eslint-disable-next-line no-console\n          console.error(`Failed to open cache: ${error.message}`);\n          this.cacheApi = undefined;\n        })\n        .finally(() => {\n          this.isReady = true;\n          // Copy to avoid mutation issues\n          const callbacks = [...this.subscribers];\n\n          // Clear array efficiently\n          this.subscribers.length = 0;\n\n          callbacks.forEach(callback => {\n            try {\n              callback();\n            } catch (error: any) {\n              // eslint-disable-next-line no-console\n              console.error(`Error in CacheStore subscriber callback: ${error.message}`);\n            }\n          });\n        });\n    } else {\n      this.isReady = true;\n    }\n  }\n\n  public onReady(callback: () => void): () => void {\n    if (this.isReady) {\n      callback();\n\n      return () => {};\n    }\n\n    this.subscribers.push(callback);\n\n    return () => {\n      const index = this.subscribers.indexOf(callback);\n\n      if (index >= 0) {\n        this.subscribers.splice(index, 1);\n      }\n    };\n  }\n\n  private waitForReady(): Promise<void> {\n    if (this.isReady) {\n      return Promise.resolve();\n    }\n\n    return new Promise(resolve => {\n      this.onReady(resolve);\n    });\n  }\n\n  public async get(url: string, fetchOptions?: RequestInit) {\n    await this.fetchAndCache(url, fetchOptions);\n\n    return this.cacheStore.get(url)?.content ?? '';\n  }\n\n  public getContent(url: string): string {\n    return this.cacheStore.get(url)?.content ?? '';\n  }\n\n  public set(url: string, data: StorageItem) {\n    this.cacheStore.set(url, data);\n  }\n\n  public isCached(url: string) {\n    return this.cacheStore.get(url)?.status === STATUS.LOADED;\n  }\n\n  private async fetchAndCache(url: string, fetchOptions?: RequestInit) {\n    if (!this.isReady) {\n      await this.waitForReady();\n    }\n\n    const cache = this.cacheStore.get(url);\n\n    if (cache?.status === STATUS.LOADED) {\n      return;\n    }\n\n    if (cache?.status === STATUS.LOADING) {\n      await this.handleLoading(url, fetchOptions?.signal || undefined, async () => {\n        this.cacheStore.set(url, { content: '', status: STATUS.IDLE });\n        await this.fetchAndCache(url, fetchOptions);\n      });\n\n      return;\n    }\n\n    this.cacheStore.set(url, { content: '', status: STATUS.LOADING });\n\n    try {\n      const content = this.cacheApi\n        ? await this.fetchFromPersistentCache(url, fetchOptions)\n        : await request(url, fetchOptions);\n\n      this.cacheStore.set(url, { content, status: STATUS.LOADED });\n    } catch (error: any) {\n      this.cacheStore.set(url, { content: '', status: STATUS.FAILED });\n      throw error;\n    }\n  }\n\n  private async fetchFromPersistentCache(url: string, fetchOptions?: RequestInit): Promise<string> {\n    const data = await this.cacheApi?.match(url);\n\n    if (data) {\n      return data.text();\n    }\n\n    await this.cacheApi?.add(new Request(url, fetchOptions));\n\n    const response = await this.cacheApi?.match(url);\n\n    return (await response?.text()) ?? '';\n  }\n\n  private async handleLoading(\n    url: string,\n    signal: AbortSignal | undefined,\n    callback: () => Promise<void>,\n  ) {\n    for (let retryCount = 0; retryCount < CACHE_MAX_RETRIES; retryCount++) {\n      if (signal?.aborted) {\n        throw signal.reason instanceof Error\n          ? signal.reason\n          : new DOMException('The operation was aborted.', 'AbortError');\n      }\n\n      if (this.cacheStore.get(url)?.status !== STATUS.LOADING) {\n        return;\n      }\n\n      await sleep(0.1);\n    }\n\n    await callback();\n  }\n\n  public keys(): Array<string> {\n    return [...this.cacheStore.keys()];\n  }\n\n  public data(): Array<Record<string, StorageItem>> {\n    return [...this.cacheStore.entries()].map(([key, value]) => ({ [key]: value }));\n  }\n\n  public async delete(url: string) {\n    if (this.cacheApi) {\n      await this.cacheApi.delete(url);\n    }\n\n    this.cacheStore.delete(url);\n  }\n\n  public async clear() {\n    if (this.cacheApi) {\n      const keys = await this.cacheApi.keys();\n\n      await Promise.allSettled(keys.map(key => this.cacheApi!.delete(key)));\n    }\n\n    this.cacheStore.clear();\n  }\n}\n\nfunction sleep(seconds = 1) {\n  return new Promise(resolve => {\n    setTimeout(resolve, seconds * 1000);\n  });\n}\n"],"mappings":";;;;;;AAAA,OAAO,SAAS,eAA0B,YAAY,gBAAgB;;;ACA/D,IAAM,aAAa;AACnB,IAAM,oBAAoB;AAE1B,IAAM,SAAS;AAAA,EACpB,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,aAAa;AACf;;;ACNO,SAAS,YAAqB;AACnC,SAAO,CAAC,EAAE,OAAO,WAAW,eAAe,OAAO,UAAU;AAC9D;AAwCA,eAAsB,QAAQ,KAAa,SAAuB;AAChE,QAAM,WAAW,MAAM,MAAM,KAAK,OAAO;AACzC,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;AACvD,QAAM,CAAC,QAAQ,KAAK,eAAe,IAAI,MAAM,OAAO;AAEpD,MAAI,SAAS,SAAS,KAAK;AACzB,UAAM,IAAI,MAAM,WAAW;AAAA,EAC7B;AAEA,MAAI,CAAC,CAAC,iBAAiB,YAAY,EAAE,KAAK,OAAK,SAAS,SAAS,CAAC,CAAC,GAAG;AACpE,UAAM,IAAI,MAAM,6BAA6B,QAAQ,EAAE;AAAA,EACzD;AAEA,SAAO,SAAS,KAAK;AACvB;;;AClDA,IAAqB,aAArB,MAAgC;AAAA,EAM9B,YAAY,UAA6B,CAAC,GAAG;AAL7C,wBAAQ;AACR,wBAAiB;AACjB,wBAAiB,eAAiC,CAAC;AACnD,wBAAO,WAAU;AAGf,UAAM,EAAE,OAAO,YAAY,aAAa,MAAM,IAAI;AAElD,SAAK,aAAa,oBAAI,IAAyB;AAE/C,UAAM,qBAAqB,cAAc,UAAU,KAAK,YAAY;AAEpE,QAAI,oBAAoB;AAEtB,aACG,KAAK,IAAI,EACT,KAAK,WAAS;AACb,aAAK,WAAW;AAAA,MAClB,CAAC,EACA,MAAM,WAAS;AAEd,gBAAQ,MAAM,yBAAyB,MAAM,OAAO,EAAE;AACtD,aAAK,WAAW;AAAA,MAClB,CAAC,EACA,QAAQ,MAAM;AACb,aAAK,UAAU;AAEf,cAAM,YAAY,CAAC,GAAG,KAAK,WAAW;AAGtC,aAAK,YAAY,SAAS;AAE1B,kBAAU,QAAQ,cAAY;AAC5B,cAAI;AACF,qBAAS;AAAA,UACX,SAAS,OAAY;AAEnB,oBAAQ,MAAM,4CAA4C,MAAM,OAAO,EAAE;AAAA,UAC3E;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACL,OAAO;AACL,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA,EAEO,QAAQ,UAAkC;AAC/C,QAAI,KAAK,SAAS;AAChB,eAAS;AAET,aAAO,MAAM;AAAA,MAAC;AAAA,IAChB;AAEA,SAAK,YAAY,KAAK,QAAQ;AAE9B,WAAO,MAAM;AACX,YAAM,QAAQ,KAAK,YAAY,QAAQ,QAAQ;AAE/C,UAAI,SAAS,GAAG;AACd,aAAK,YAAY,OAAO,OAAO,CAAC;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAA8B;AACpC,QAAI,KAAK,SAAS;AAChB,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,WAAO,IAAI,QAAQ,aAAW;AAC5B,WAAK,QAAQ,OAAO;AAAA,IACtB,CAAC;AAAA,EACH;AAAA,EAEA,MAAa,IAAI,KAAa,cAA4B;AACxD,UAAM,KAAK,cAAc,KAAK,YAAY;AAE1C,WAAO,KAAK,WAAW,IAAI,GAAG,GAAG,WAAW;AAAA,EAC9C;AAAA,EAEO,WAAW,KAAqB;AACrC,WAAO,KAAK,WAAW,IAAI,GAAG,GAAG,WAAW;AAAA,EAC9C;AAAA,EAEO,IAAI,KAAa,MAAmB;AACzC,SAAK,WAAW,IAAI,KAAK,IAAI;AAAA,EAC/B;AAAA,EAEO,SAAS,KAAa;AAC3B,WAAO,KAAK,WAAW,IAAI,GAAG,GAAG,WAAW,OAAO;AAAA,EACrD;AAAA,EAEA,MAAc,cAAc,KAAa,cAA4B;AACnE,QAAI,CAAC,KAAK,SAAS;AACjB,YAAM,KAAK,aAAa;AAAA,IAC1B;AAEA,UAAM,QAAQ,KAAK,WAAW,IAAI,GAAG;AAErC,QAAI,OAAO,WAAW,OAAO,QAAQ;AACnC;AAAA,IACF;AAEA,QAAI,OAAO,WAAW,OAAO,SAAS;AACpC,YAAM,KAAK,cAAc,KAAK,cAAc,UAAU,QAAW,YAAY;AAC3E,aAAK,WAAW,IAAI,KAAK,EAAE,SAAS,IAAI,QAAQ,OAAO,KAAK,CAAC;AAC7D,cAAM,KAAK,cAAc,KAAK,YAAY;AAAA,MAC5C,CAAC;AAED;AAAA,IACF;AAEA,SAAK,WAAW,IAAI,KAAK,EAAE,SAAS,IAAI,QAAQ,OAAO,QAAQ,CAAC;AAEhE,QAAI;AACF,YAAM,UAAU,KAAK,WACjB,MAAM,KAAK,yBAAyB,KAAK,YAAY,IACrD,MAAM,QAAQ,KAAK,YAAY;AAEnC,WAAK,WAAW,IAAI,KAAK,EAAE,SAAS,QAAQ,OAAO,OAAO,CAAC;AAAA,IAC7D,SAAS,OAAY;AACnB,WAAK,WAAW,IAAI,KAAK,EAAE,SAAS,IAAI,QAAQ,OAAO,OAAO,CAAC;AAC/D,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,yBAAyB,KAAa,cAA6C;AAC/F,UAAM,OAAO,MAAM,KAAK,UAAU,MAAM,GAAG;AAE3C,QAAI,MAAM;AACR,aAAO,KAAK,KAAK;AAAA,IACnB;AAEA,UAAM,KAAK,UAAU,IAAI,IAAI,QAAQ,KAAK,YAAY,CAAC;AAEvD,UAAM,WAAW,MAAM,KAAK,UAAU,MAAM,GAAG;AAE/C,WAAQ,MAAM,UAAU,KAAK,KAAM;AAAA,EACrC;AAAA,EAEA,MAAc,cACZ,KACA,QACA,UACA;AACA,aAAS,aAAa,GAAG,aAAa,mBAAmB,cAAc;AACrE,UAAI,QAAQ,SAAS;AACnB,cAAM,OAAO,kBAAkB,QAC3B,OAAO,SACP,IAAI,aAAa,8BAA8B,YAAY;AAAA,MACjE;AAEA,UAAI,KAAK,WAAW,IAAI,GAAG,GAAG,WAAW,OAAO,SAAS;AACvD;AAAA,MACF;AAEA,YAAM,MAAM,GAAG;AAAA,IACjB;AAEA,UAAM,SAAS;AAAA,EACjB;AAAA,EAEO,OAAsB;AAC3B,WAAO,CAAC,GAAG,KAAK,WAAW,KAAK,CAAC;AAAA,EACnC;AAAA,EAEO,OAA2C;AAChD,WAAO,CAAC,GAAG,KAAK,WAAW,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC,GAAG,GAAG,MAAM,EAAE;AAAA,EAChF;AAAA,EAEA,MAAa,OAAO,KAAa;AAC/B,QAAI,KAAK,UAAU;AACjB,YAAM,KAAK,SAAS,OAAO,GAAG;AAAA,IAChC;AAEA,SAAK,WAAW,OAAO,GAAG;AAAA,EAC5B;AAAA,EAEA,MAAa,QAAQ;AACnB,QAAI,KAAK,UAAU;AACjB,YAAM,OAAO,MAAM,KAAK,SAAS,KAAK;AAEtC,YAAM,QAAQ,WAAW,KAAK,IAAI,SAAO,KAAK,SAAU,OAAO,GAAG,CAAC,CAAC;AAAA,IACtE;AAEA,SAAK,WAAW,MAAM;AAAA,EACxB;AACF;AAEA,SAAS,MAAM,UAAU,GAAG;AAC1B,SAAO,IAAI,QAAQ,aAAW;AAC5B,eAAW,SAAS,UAAU,GAAI;AAAA,EACpC,CAAC;AACH;;;AHxMA,IAAM,eAAe,cAAiC,IAAI;AAO3C,SAAR,cAA+B,EAAE,UAAU,KAAK,GAAU;AAC/D,QAAM,CAAC,KAAK,IAAI,SAAS,MAAM,IAAI,WAAW,EAAE,MAAM,YAAY,KAAK,CAAC,CAAC;AAEzE,SAAO,oCAAC,aAAa,UAAb,EAAsB,OAAO,SAAQ,QAAS;AACxD;AAEO,SAAS,gBAAmC;AACjD,SAAO,WAAW,YAAY;AAChC;","names":[]}