UNPKG

@unleash/proxy-client-react

Version:
1 lines 16.4 kB
{"version":3,"file":"unleash-react.umd.cjs","sources":["../src/FlagContext.ts","../src/FlagProvider.tsx","../src/useFlagContext.ts","../src/useFlag.ts","../src/useFlags.ts","../src/useFlagsStatus.ts","../src/useVariant.ts","../src/useUnleashContext.ts","../src/useUnleashClient.ts"],"sourcesContent":["import React from 'react';\nimport type { UnleashClient } from 'unleash-proxy-client';\n\nexport interface IFlagContextValue\n extends Pick<\n UnleashClient,\n 'on' | 'off' | 'updateContext' | 'isEnabled' | 'getVariant'\n > {\n client: UnleashClient;\n flagsReady: boolean;\n setFlagsReady: React.Dispatch<\n React.SetStateAction<IFlagContextValue['flagsReady']>\n >;\n flagsError: any;\n setFlagsError: React.Dispatch<\n React.SetStateAction<IFlagContextValue['flagsError']>\n >;\n}\n\nconst FlagContext = React.createContext<IFlagContextValue | null>(null);\n\nexport default FlagContext;\n","/** @format */\n\nimport React, { type FC, type PropsWithChildren, useEffect, useMemo, useState } from 'react';\nimport { type IConfig, UnleashClient } from 'unleash-proxy-client';\nimport FlagContext, { type IFlagContextValue } from './FlagContext';\n\nexport interface IFlagProvider {\n config?: IConfig;\n unleashClient?: UnleashClient;\n startClient?: boolean;\n stopClient?: boolean;\n startTransition?: (fn: () => void) => void;\n}\n\nconst offlineConfig: IConfig = {\n bootstrap: [],\n disableRefresh: true,\n disableMetrics: true,\n url: 'http://localhost',\n appName: 'offline',\n clientKey: 'not-used',\n};\n\n// save startTransition as var to avoid webpack analysis (https://github.com/webpack/webpack/issues/14814)\nconst _startTransition = 'startTransition';\n// fallback for React <18 which doesn't support startTransition\n// Fallback for React <18 and exclude startTransition if in React Native\nconst defaultStartTransition = React[_startTransition] || (fn => fn());\n\nconst FlagProvider: FC<PropsWithChildren<IFlagProvider>> = ({\n config: customConfig,\n children,\n unleashClient,\n startClient = true,\n stopClient = true,\n startTransition = defaultStartTransition\n}) => {\n const config = customConfig || offlineConfig;\n const client = React.useRef<UnleashClient>(\n unleashClient || new UnleashClient(config)\n );\n const [flagsReady, setFlagsReady] = React.useState(\n Boolean(\n unleashClient\n ? (customConfig?.bootstrap && customConfig?.bootstrapOverride !== false) || unleashClient.isReady?.()\n : config.bootstrap && config.bootstrapOverride !== false\n )\n );\n const [flagsError, setFlagsError] = useState(client.current.getError?.() || null);\n\n useEffect(() => {\n if (!config && !unleashClient) {\n console.error(\n `You must provide either a config or an unleash client to the flag provider.\n If you are initializing the client in useEffect, you can avoid this warning\n by checking if the client exists before rendering.`\n );\n }\n\n const errorCallback = (e: any) => {\n startTransition(() => {\n setFlagsError((currentError: any) => currentError || e);\n });\n };\n\n const clearErrorCallback = (e: any) => {\n startTransition(() => {\n setFlagsError(null);\n });\n }\n\n let timeout: ReturnType<typeof setTimeout> | null = null;\n const readyCallback = () => {\n // wait for flags to resolve after useFlag gets the same event\n timeout = setTimeout(() => {\n startTransition(() => {\n setFlagsReady(true);\n });\n }, 0);\n };\n\n client.current.on('ready', readyCallback);\n client.current.on('error', errorCallback);\n client.current.on('recovered', clearErrorCallback);\n\n if (startClient) {\n // defensively stop the client first\n client.current.stop();\n // start the client\n client.current.start();\n }\n\n // stop unleash client on unmount\n return function cleanup() {\n if (client.current) {\n client.current.off('error', errorCallback);\n client.current.off('ready', readyCallback);\n client.current.off('recovered', clearErrorCallback);\n if (stopClient) {\n client.current.stop();\n }\n }\n if (timeout) {\n clearTimeout(timeout);\n }\n };\n }, []);\n\n const context = useMemo<IFlagContextValue>(\n () => ({\n on: ((event, callback, ctx) => client.current.on(event, callback, ctx)) as IFlagContextValue['on'],\n off: ((event, callback) => client.current.off(event, callback)) as IFlagContextValue['off'],\n updateContext: async (context) => await client.current.updateContext(context),\n isEnabled: (toggleName) => client.current.isEnabled(toggleName),\n getVariant: (toggleName) => client.current.getVariant(toggleName),\n client: client.current,\n flagsReady,\n flagsError,\n setFlagsReady,\n setFlagsError,\n }),\n [flagsReady, flagsError]\n );\n\n return (\n <FlagContext.Provider value={context}>{children}</FlagContext.Provider>\n );\n};\n\nexport default FlagProvider;\n","import { useContext } from \"react\";\nimport FlagContext, { type IFlagContextValue } from \"./FlagContext\";\nimport type { UnleashClient } from \"unleash-proxy-client\";\n\nconst methods = {\n\ton: (event: string, callback: Function, ctx?: any): UnleashClient => {\n\t\tconsole.error(\"on() must be used within a FlagProvider\");\n\t\treturn mockUnleashClient;\n\t},\n\toff: (event: string, callback?: Function): UnleashClient => {\n\t\tconsole.error(\"off() must be used within a FlagProvider\");\n\t\treturn mockUnleashClient;\n\t},\n\tupdateContext: async () => {\n\t\tconsole.error(\"updateContext() must be used within a FlagProvider\");\n\t\treturn undefined;\n\t},\n\tisEnabled: () => {\n\t\tconsole.error(\"isEnabled() must be used within a FlagProvider\");\n\t\treturn false;\n\t},\n\tgetVariant: () => {\n\t\tconsole.error(\"getVariant() must be used within a FlagProvider\");\n\t\treturn { name: \"disabled\", enabled: false };\n\t}\n};\n\nconst mockUnleashClient = {\n\t...methods,\n\ttoggles: [],\n\timpressionDataAll: {},\n\tcontext: {},\n\tstorage: {},\n\tstart: () => {},\n\tstop: () => {},\n\tisReady: () => false,\n\tgetError: () => null,\n\tgetAllToggles: () => []\n} as unknown as UnleashClient;\n\nconst defaultContextValue: IFlagContextValue = {\n\t...methods,\n\tclient: mockUnleashClient,\n\tflagsReady: false,\n\tsetFlagsReady: () => {\n\t\tconsole.error(\"setFlagsReady() must be used within a FlagProvider\");\n\t},\n\tflagsError: null,\n\tsetFlagsError: () => {\n\t\tconsole.error(\"setFlagsError() must be used within a FlagProvider\");\n\t}\n};\n\nexport function useFlagContext() {\n\tconst context = useContext(FlagContext);\n\tif (!context) {\n\t\tconsole.error(\"useFlagContext() must be used within a FlagProvider\");\n\t\treturn defaultContextValue;\n\t}\n\treturn context;\n}\n","import { useEffect, useState, useRef } from 'react';\nimport { useFlagContext } from './useFlagContext';\n\nconst useFlag = (featureName: string) => {\n const { isEnabled, client } = useFlagContext();\n const [flag, setFlag] = useState(!!isEnabled(featureName));\n const flagRef = useRef<typeof flag>();\n flagRef.current = flag;\n\n useEffect(() => {\n if (!client) return;\n\n const updateHandler = () => {\n const enabled = isEnabled(featureName);\n if (enabled !== flagRef.current) {\n flagRef.current = enabled;\n setFlag(!!enabled);\n }\n };\n\n const readyHandler = () => {\n const enabled = isEnabled(featureName);\n flagRef.current = enabled;\n setFlag(enabled);\n };\n\n client.on('update', updateHandler);\n client.on('ready', readyHandler);\n\n return () => {\n client.off('update', updateHandler);\n client.off('ready', readyHandler);\n };\n }, [client]);\n\n return flag;\n};\n\nexport default useFlag;\n","import { useEffect, useState } from 'react';\nimport { useFlagContext } from './useFlagContext';\n\nconst useFlags = () => {\n const { client } = useFlagContext();\n const [flags, setFlags] = useState(client.getAllToggles());\n\n useEffect(() => {\n const onUpdate = () => {\n setFlags(client.getAllToggles());\n };\n\n client.on('update', onUpdate);\n\n return () => {\n client.off('update', onUpdate);\n };\n }, []);\n\n return flags;\n};\n\nexport default useFlags;\n","/** @format */\nimport { useFlagContext } from './useFlagContext';\n\nconst useFlagsStatus = () => {\n const { flagsReady, flagsError } = useFlagContext();\n\n return { flagsReady, flagsError };\n};\n\nexport default useFlagsStatus;\n","import { useState, useEffect, useRef } from 'react';\nimport { IVariant } from 'unleash-proxy-client';\nimport { useFlagContext } from './useFlagContext';\n\nexport const variantHasChanged = (\n oldVariant: IVariant,\n newVariant?: IVariant,\n): boolean => {\n const variantsAreEqual =\n oldVariant.name === newVariant?.name &&\n oldVariant.enabled === newVariant?.enabled &&\n oldVariant.feature_enabled === newVariant?.feature_enabled &&\n oldVariant.payload?.type === newVariant?.payload?.type &&\n oldVariant.payload?.value === newVariant?.payload?.value;\n\n return !variantsAreEqual;\n};\n\nconst useVariant = (featureName: string): Partial<IVariant> => {\n const { getVariant, client } = useFlagContext();\n\n const [variant, setVariant] = useState(getVariant(featureName));\n const variantRef = useRef<typeof variant>({\n name: variant.name,\n enabled: variant.enabled,\n });\n variantRef.current = variant;\n\n useEffect(() => {\n if (!client) return;\n\n const updateHandler = () => {\n const newVariant = getVariant(featureName);\n if (variantHasChanged(variantRef.current, newVariant)) {\n setVariant(newVariant);\n variantRef.current = newVariant;\n }\n };\n\n const readyHandler = () => {\n const variant = getVariant(featureName);\n variantRef.current.name = variant?.name;\n variantRef.current.enabled = variant?.enabled;\n setVariant(variant);\n };\n\n client.on('update', updateHandler);\n client.on('ready', readyHandler);\n\n return () => {\n client.off('update', updateHandler);\n client.off('ready', readyHandler);\n };\n }, [client]);\n\n return variant || {};\n};\n\nexport default useVariant;\n","import { useFlagContext } from './useFlagContext';\n\nconst useUnleashContext = () => {\n const { updateContext } = useFlagContext();\n\n return updateContext;\n};\n\nexport default useUnleashContext;\n","import { useFlagContext } from './useFlagContext';\n\nconst useUnleashClient = () => {\n const { client } = useFlagContext();\n return client;\n};\n\nexport default useUnleashClient;\n"],"names":["FlagContext","React","offlineConfig","defaultStartTransition","fn","FlagProvider","customConfig","children","unleashClient","startClient","stopClient","startTransition","config","client","UnleashClient","flagsReady","setFlagsReady","_a","flagsError","setFlagsError","useState","_c","_b","useEffect","errorCallback","e","currentError","clearErrorCallback","timeout","readyCallback","context","useMemo","event","callback","ctx","toggleName","methods","mockUnleashClient","defaultContextValue","useFlagContext","useContext","useFlag","featureName","isEnabled","flag","setFlag","flagRef","useRef","updateHandler","enabled","readyHandler","useFlags","flags","setFlags","onUpdate","useFlagsStatus","variantHasChanged","oldVariant","newVariant","_d","useVariant","getVariant","variant","setVariant","variantRef","useUnleashContext","updateContext","useUnleashClient"],"mappings":"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"}