{"version":3,"sources":["../src/components/FeatureHub.tsx","../src/hooks/useFeature.tsx","../src/hooks/useFeatureHubClient.tsx","../src/hooks/useFeatureHub.tsx"],"names":["createContext","useEffect","useMemo","useRef","useState","EdgeFeatureHubConfig","FeatureHubPollingClient","Readyness","fh","jsx","FeatureHubContext","FeatureHub","url","apiKey","userKey","username","pollInterval","children","repo","c","config","context","client","activeListenerIdRef","listener","readyness","__async","userInfo","listenerId","useContext","useFeatureHubClient","featureHub","useFeatureHubClient_default","useFeature","key","value","setValue","fsh","useFeature_default","useFeatureHub","useFeatureHub_default"],"mappings":"6MAAA,OAAS,iBAAAA,EAA0B,aAAAC,EAAW,WAAAC,EAAS,UAAAC,EAAQ,YAAAC,MAAgB,QAC/E,OAEE,wBAAAC,EACA,2BAAAC,EAEA,aAAAC,EACA,cAAcC,MACT,mCAsGH,cAAAC,MAAA,oBA7FG,IAAMC,EAAoBV,EAA6B,MAAS,EACvEU,EAAkB,YAAc,aA6BjB,SAARC,EAA4B,CACjC,IAAAC,EACA,OAAAC,EACA,QAAAC,EACA,SAAAC,EACA,aAAAC,EAAe,IACf,SAAAC,CACF,EAAuB,CACrBf,EAAQ,IAAM,CAIZ,QAAQ,KAAK,wCAAwC,EACrDG,EAAqB,2BAA8B,CAACa,EAAMC,IAAM,IAAIb,EAAwBY,EAAMC,EAAGH,CAAY,EACjH,IAAMI,EAASf,EAAqB,OAAOO,EAAKC,CAAM,EAChDQ,EAAUD,EAAO,WAAW,EAClCZ,EAAG,IAAIY,EAAQC,CAAO,EACtBA,EAAQ,MAAM,CAChB,EAAG,CAACT,EAAKC,EAAQG,CAAY,CAAC,EAE9B,GAAM,CAACM,CAAM,EAAIlB,EAASI,EAAG,OAAO,EAC9Be,EAAsBpB,EAAuC,IAAI,EAEvE,OAAAF,EAAU,IAAM,CACd,IAAMuB,EAAkBC,GAAyBC,EAAA,sBAC/C,OAAQD,EAAW,CACjB,KAAKlB,EAAU,OACb,QAAQ,MAAM,0CAA0C,EACxD,MACF,KAAKA,EAAU,SACb,QAAQ,KAAK,iDAAiD,EAC9D,MACF,QAAS,CAEP,IAAMoB,EAAWZ,GAAA,KAAAA,EAAYD,EAE7B,GAAI,CAACa,EAAU,CACb,QAAQ,KAAK,uEAAuE,EACpF,MACF,CAEA,QAAQ,KAAK,yEAAyE,EACtF,MAAML,EAAO,QAAQK,CAAQ,EAAE,MAAM,CACvC,CACF,CACF,GAEIJ,EAAoB,UAAY,MAElCf,EAAG,OAAO,wBAAwBe,EAAoB,OAAO,EAG/D,IAAMK,EAAapB,EAAG,OAAO,qBAAqBgB,EAAU,EAAI,EAChE,OAAAD,EAAoB,QAAUK,EAEvB,IAAM,CACX,QAAQ,KAAK,mEAAmE,EAChFpB,EAAG,OAAO,wBAAwBoB,CAAU,EAC5CpB,EAAG,OAAO,MAAM,CAClB,CACF,EAAG,CAACM,CAAO,CAAC,EAGVL,EAACC,EAAkB,SAAlB,CAA2B,MAAO,CAAE,OAAQF,EAAG,OAAQ,OAAAc,CAAO,EAC5D,SAAAL,EACH,CAEJ,CClHA,OAAS,aAAAhB,EAAW,YAAAG,MAAgB,QCApC,OAAS,cAAAyB,MAAkB,QAS3B,SAASC,GAAqC,CAC5C,IAAMC,EAAaF,EAAWnB,CAAiB,EAE/C,GAAI,CAACqB,EACH,MAAM,IAAI,MACR,6FACF,EAGF,OAAOA,EAAW,MACpB,CAEA,IAAOC,EAAQF,EDVf,SAASG,EAAwBC,EAA4B,CAC3D,IAAMZ,EAASU,EAAoB,EAC7B,CAACG,EAAOC,CAAQ,EAAIhC,EAASkB,EAAO,QAAuBY,CAAG,EAAE,KAAK,EAE3E,OAAAjC,EAAU,IAAM,CACd,IAAMuB,EAAYa,GAA2CD,EAASC,EAAI,KAAK,EAE/E,OAAAf,EAAO,QAAQY,CAAG,EAAE,YAAYV,CAAQ,EAEjC,IAAM,CACXF,EAAO,QAAQY,CAAG,EAAE,eAAeV,CAAQ,CAC7C,CACF,EAAG,CAACF,EAAQY,CAAG,CAAC,EAETC,CACT,CAEA,IAAOG,EAAQL,EE5Bf,OAAS,cAAAJ,MAAkB,QAO3B,SAASU,GAA+B,CACtC,IAAMR,EAAaF,EAAWnB,CAAiB,EAE/C,GAAI,CAACqB,EACH,MAAM,IAAI,MACR,6FACF,EAGF,OAAOA,CACT,CAEA,IAAOS,EAAQD","sourcesContent":["import { createContext, ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport {\n  ClientContext,\n  EdgeFeatureHubConfig,\n  FeatureHubPollingClient,\n  ReadinessListenerHandle,\n  Readyness,\n  FeatureHub as fh, FeatureHubConfig\n} from \"featurehub-javascript-client-sdk\";\n\nexport type UseFeatureHub = {\n  readonly config: FeatureHubConfig;\n  readonly client: ClientContext;\n};\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nexport const FeatureHubContext = createContext<UseFeatureHub>(undefined);\nFeatureHubContext.displayName = \"FeatureHub\";\n\ntype Props = {\n  /** The url to the running instance of the FeatureHub EDGE API */\n  readonly url: string;\n  /** The FeatureHub API key -- can be found in the FeatureHub Admin Console */\n  readonly apiKey: string;\n  /** Scopes FeatureHub context to userKey -- otherwise, context will be anonymous. */\n  readonly userKey?: string;\n  /** @deprecated use 'userKey` instead. */\n  /** Use `userKey` prop instead. Scopes FeatureHub context to username -- otherwise, context will be anonymous. */\n  readonly username?: string;\n  /** Interval (in milliseconds) to poll FeatureHub for updates. [default: 60 seconds] */\n  readonly pollInterval?: number;\n  /** The React application tree to inject the FeatureHub client into */\n  readonly children: ReactNode;\n};\n\n/**\n * The FeatureHub React component. Use this as a top-level wrapper around your\n * main App component.\n *\n * @param {string} url - the url of the FeatureHub instance (required)\n * @param {string} apiKey - the apiKey key to use. Make sure it is the server-eval key! (required)\n * @param {string} userKey - the optional userKey to add user information to the FeatureHub context (optional)\n * @param {number} pollInterval - the desired polling interval (ms) to check for value updates (optional -- default 60 seconds)\n * @param {JSX} children - the React component tree to inject FeatureHub into (required)\n *\n */\nexport default function FeatureHub({\n  url,\n  apiKey,\n  userKey,\n  username,\n  pollInterval = 60000,\n  children\n}: Props): JSX.Element {\n  useMemo(() => {\n    // Need to guarantee creation of only ONE EdgeFeatureHubConfig instance.\n    // Noticed that React has a tendency to create two with the nature of the render cycles\n    // despite leveraging useMemo. So we keep a static reference to help us achieve the outcome.\n    console.info(\"FeatureHub React SDK: Creating config.\");\n    EdgeFeatureHubConfig.defaultEdgeServiceSupplier = ((repo, c) => new FeatureHubPollingClient(repo, c, pollInterval));\n    const config = EdgeFeatureHubConfig.config(url, apiKey);\n    const context = config.newContext();\n    fh.set(config, context);\n    context.build();\n  }, [url, apiKey, pollInterval]);\n\n  const [client] = useState(fh.context);\n  const activeListenerIdRef = useRef<ReadinessListenerHandle | null>(null);\n\n  useEffect(() => {\n    const listener = async (readyness: Readyness) => {\n      switch (readyness) {\n        case Readyness.Failed:\n          console.error(\"FeatureHub React SDK: Connection failed!\");\n          break;\n        case Readyness.NotReady:\n          console.warn(\"FeatureHub React SDK: Connection not ready yet!\");\n          break;\n        default: {\n          // TODO: Remove deprecated username prop at some point since userKey keeps API language consistent\n          const userInfo = username ?? userKey;\n\n          if (!userInfo) {\n            console.info(\"FeatureHub React SDK: Connection ready! Using anonymous user context.\");\n            return;\n          }\n\n          console.info(\"FeatureHub React SDK: Connection ready! Using context with userKey set.\");\n          await client.userKey(userInfo).build(); // still the same userKey, doesn't change\n        }\n      }\n    };\n\n    if (activeListenerIdRef.current !== null) {\n      // Remove potential previous existing listener (for use-case when the username updates while component still mounted)\n      fh.config.removeReadinessListener(activeListenerIdRef.current);\n    }\n\n    const listenerId = fh.config.addReadinessListener(listener, true);\n    activeListenerIdRef.current = listenerId; // Keep track of registered listener\n\n    return () => {\n      console.warn(\"FeatureHub React SDK: Context unmounting. Terminating connection!\");\n      fh.config.removeReadinessListener(listenerId);\n      fh.config.close();\n    };\n  }, [userKey]);\n\n  return (\n    <FeatureHubContext.Provider value={{ config: fh.config, client }}>\n      {children}\n    </FeatureHubContext.Provider>\n  );\n}\n","import { useEffect, useState } from \"react\";\nimport useFeatureHubClient from \"./useFeatureHubClient\";\nimport { FeatureStateHolder } from \"featurehub-javascript-client-sdk\";\n\n/**\n * React hook to subscribe to FeatureHub feature key.\n * NOTE: The key must be defined in your FeatureHub Admin Console.\n *\n * @param {string} key - the feature key\n * @returns {T | undefined} value - generic type of feature value (default boolean)\n */\nfunction useFeature<T = boolean>(key: string): T | undefined {\n  const client = useFeatureHubClient();\n  const [value, setValue] = useState(client.feature<T | undefined>(key).value);\n\n  useEffect(() => {\n    const listener = (fsh: FeatureStateHolder<T | undefined>) => setValue(fsh.value);\n\n    client.feature(key).addListener(listener);\n\n    return () => {\n      client.feature(key).removeListener(listener);\n    };\n  }, [client, key]);\n\n  return value;\n}\n\nexport default useFeature;\n","import { useContext } from \"react\";\nimport { FeatureHubContext } from \"../components/FeatureHub\";\nimport { ClientContext } from \"featurehub-javascript-client-sdk\";\n\n/**\n * @deprecated Use `useFeatureHub` instead.\n * Fetches the FeatureHub client context object\n * @returns {ClientContext} - the FeatureHub client\n */\nfunction useFeatureHubClient(): ClientContext {\n  const featureHub = useContext(FeatureHubContext);\n\n  if (!featureHub) {\n    throw new Error(\n      \"Cannot get FeatureHub client inside of component not wrapped by the <FeatureHub> component!\"\n    );\n  }\n\n  return featureHub.client;\n}\n\nexport default useFeatureHubClient;\n","import { useContext } from \"react\";\nimport { FeatureHubContext, UseFeatureHub } from \"../components/FeatureHub\";\n\n/**\n * Fetches the FeatureHub config and client context objects\n * @returns {UseFeatureHub} - struct containing the FeatureHub config and client\n */\nfunction useFeatureHub(): UseFeatureHub {\n  const featureHub = useContext(FeatureHubContext);\n\n  if (!featureHub) {\n    throw new Error(\n      \"Cannot get FeatureHub client inside of component not wrapped by the <FeatureHub> component!\"\n    );\n  }\n\n  return featureHub;\n}\n\nexport default useFeatureHub;\n"]}