@openfeature/react-sdk 0.0.6-experimental → 0.1.0-experimental

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,7 +33,7 @@ Here's a basic example of how to use the current API with the in-memory provider
33
33
  ```tsx
34
34
  import logo from './logo.svg';
35
35
  import './App.css';
36
- import { OpenFeatureProvider, useFeatureFlag, OpenFeature } from '@openfeature/react-sdk';
36
+ import { EvaluationContext, OpenFeatureProvider, useBooleanFlagValue, useBooleanFlagDetails, OpenFeature } from '@openfeature/react-sdk';
37
37
  import { FlagdWebProvider } from '@openfeature/flagd-web-provider';
38
38
 
39
39
  const flagConfig = {
@@ -64,12 +64,12 @@ function App() {
64
64
  }
65
65
 
66
66
  function Page() {
67
- const booleanFlag = useFeatureFlag('new-message', false);
67
+ const newMessage = useBooleanFlagValue('new-message', false);
68
68
  return (
69
69
  <div className="App">
70
70
  <header className="App-header">
71
71
  <img src={logo} className="App-logo" alt="logo" />
72
- {booleanFlag.value ? <p>Welcome to this OpenFeature-enabled React app!</p> : <p>Welcome to this React app.</p>}
72
+ {newMessage ? <p>Welcome to this OpenFeature-enabled React app!</p> : <p>Welcome to this React app.</p>}
73
73
  </header>
74
74
  </div>
75
75
  )
@@ -78,6 +78,19 @@ function Page() {
78
78
  export default App;
79
79
  ```
80
80
 
81
+ You use the detailed flag evaluation hooks to evaluate the flag and get additional information about the flag and the evaluation.
82
+
83
+ ```tsx
84
+ import { useBooleanFlagDetails} from '@openfeature/react-sdk';
85
+
86
+ const {
87
+ value,
88
+ variant,
89
+ reason,
90
+ flagMetadata
91
+ } = useBooleanFlagDetails('new-message', false);
92
+ ```
93
+
81
94
  ### Multiple Providers and Scoping
82
95
 
83
96
  Multiple providers and scoped clients can be configured by passing a `clientName` to the `OpenFeatureProvider`:
@@ -103,11 +116,11 @@ OpenFeature.getClient('myClient');
103
116
 
104
117
  By default, if the OpenFeature [evaluation context](https://openfeature.dev/docs/reference/concepts/evaluation-context) is modified, components will be re-rendered.
105
118
  This is useful in cases where flag values are dependant on user-attributes or other application state (user logged in, items in card, etc).
106
- You can disable this feature in the `useFeatureFlag` hook options:
119
+ You can disable this feature in the hook options:
107
120
 
108
121
  ```tsx
109
122
  function Page() {
110
- const booleanFlag = useFeatureFlag('new-message', false, { updateOnContextChanged: false });
123
+ const newMessage = useBooleanFlagValue('new-message', false, { updateOnContextChanged: false });
111
124
  return (
112
125
  <MyComponents></MyComponents>
113
126
  )
@@ -120,11 +133,11 @@ For more information about how evaluation context works in the React SDK, see th
120
133
 
121
134
  By default, if the underlying provider emits a `ConfigurationChanged` event, components will be re-rendered.
122
135
  This is useful if you want your UI to immediately reflect changes in the backend flag configuration.
123
- You can disable this feature in the `useFeatureFlag` hook options:
136
+ You can disable this feature in the hook options:
124
137
 
125
138
  ```tsx
126
139
  function Page() {
127
- const booleanFlag = useFeatureFlag('new-message', false, { updateOnConfigurationChanged: false });
140
+ const newMessage = useBooleanFlagValue('new-message', false, { updateOnConfigurationChanged: false });
128
141
  return (
129
142
  <MyComponents></MyComponents>
130
143
  )
@@ -151,11 +164,11 @@ function Content() {
151
164
 
152
165
  function Message() {
153
166
  // component to render after READY.
154
- const { value: showNewMessage } = useFeatureFlag('new-message', false);
167
+ const newMessage = useBooleanFlagValue('new-message', false);
155
168
 
156
169
  return (
157
170
  <>
158
- {showNewMessage ? (
171
+ {newMessage ? (
159
172
  <p>Welcome to this OpenFeature-enabled React app!</p>
160
173
  ) : (
161
174
  <p>Welcome to this plain old React app!</p>
@@ -168,4 +181,4 @@ function Fallback() {
168
181
  // component to render before READY.
169
182
  return <p>Waiting for provider to be ready...</p>;
170
183
  }
171
- ```
184
+ ```
package/dist/cjs/index.js CHANGED
@@ -46,8 +46,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
46
46
  var src_exports = {};
47
47
  __export(src_exports, {
48
48
  OpenFeatureProvider: () => OpenFeatureProvider,
49
- useFeatureFlag: () => useFeatureFlag,
50
- useOpenFeatureClient: () => useOpenFeatureClient
49
+ useBooleanFlagDetails: () => useBooleanFlagDetails,
50
+ useBooleanFlagValue: () => useBooleanFlagValue,
51
+ useNumberFlagDetails: () => useNumberFlagDetails,
52
+ useNumberFlagValue: () => useNumberFlagValue,
53
+ useObjectFlagDetails: () => useObjectFlagDetails,
54
+ useObjectFlagValue: () => useObjectFlagValue,
55
+ useOpenFeatureClient: () => useOpenFeatureClient,
56
+ useStringFlagDetails: () => useStringFlagDetails,
57
+ useStringFlagValue: () => useStringFlagValue
51
58
  });
52
59
  module.exports = __toCommonJS(src_exports);
53
60
 
@@ -81,7 +88,39 @@ var DEFAULT_OPTIONS = {
81
88
  updateOnConfigurationChanged: true,
82
89
  suspend: true
83
90
  };
84
- function useFeatureFlag(flagKey, defaultValue, options) {
91
+ function useBooleanFlagValue(flagKey, defaultValue, options) {
92
+ return useBooleanFlagDetails(flagKey, defaultValue, options).value;
93
+ }
94
+ function useBooleanFlagDetails(flagKey, defaultValue, options) {
95
+ return attachHandlersAndResolve(flagKey, defaultValue, (client) => {
96
+ return client.getBooleanDetails;
97
+ }, options);
98
+ }
99
+ function useStringFlagValue(flagKey, defaultValue, options) {
100
+ return useStringFlagDetails(flagKey, defaultValue, options).value;
101
+ }
102
+ function useStringFlagDetails(flagKey, defaultValue, options) {
103
+ return attachHandlersAndResolve(flagKey, defaultValue, (client) => {
104
+ return client.getStringDetails;
105
+ }, options);
106
+ }
107
+ function useNumberFlagValue(flagKey, defaultValue, options) {
108
+ return useNumberFlagDetails(flagKey, defaultValue, options).value;
109
+ }
110
+ function useNumberFlagDetails(flagKey, defaultValue, options) {
111
+ return attachHandlersAndResolve(flagKey, defaultValue, (client) => {
112
+ return client.getNumberDetails;
113
+ }, options);
114
+ }
115
+ function useObjectFlagValue(flagKey, defaultValue, options) {
116
+ return useObjectFlagDetails(flagKey, defaultValue, options).value;
117
+ }
118
+ function useObjectFlagDetails(flagKey, defaultValue, options) {
119
+ return attachHandlersAndResolve(flagKey, defaultValue, (client) => {
120
+ return client.getObjectDetails;
121
+ }, options);
122
+ }
123
+ function attachHandlersAndResolve(flagKey, defaultValue, resolver, options) {
85
124
  const defaultedOptions = __spreadValues(__spreadValues({}, DEFAULT_OPTIONS), options);
86
125
  const [, updateState] = (0, import_react.useState)();
87
126
  const forceUpdate = () => {
@@ -107,18 +146,7 @@ function useFeatureFlag(flagKey, defaultValue, options) {
107
146
  client.removeHandler(import_web_sdk2.ProviderEvents.ConfigurationChanged, forceUpdate);
108
147
  };
109
148
  }, [client]);
110
- return getFlag(client, flagKey, defaultValue);
111
- }
112
- function getFlag(client, flagKey, defaultValue) {
113
- if (typeof defaultValue === "boolean") {
114
- return client.getBooleanDetails(flagKey, defaultValue);
115
- } else if (typeof defaultValue === "string") {
116
- return client.getStringDetails(flagKey, defaultValue);
117
- } else if (typeof defaultValue === "number") {
118
- return client.getNumberDetails(flagKey, defaultValue);
119
- } else {
120
- return client.getObjectDetails(flagKey, defaultValue);
121
- }
149
+ return resolver(client).call(client, flagKey, defaultValue);
122
150
  }
123
151
  function suspend(client, updateState) {
124
152
  let suspendResolver;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts", "../../src/use-feature-flag.ts", "../../src/provider.tsx"],
4
- "sourcesContent": ["export * from './use-feature-flag';\nexport * from './provider';\n// re-export the web-sdk so consumers can access that API from the react-sdk\nexport * from '@openfeature/web-sdk';\n", "import { Client, EvaluationDetails, FlagEvaluationOptions, FlagValue, ProviderEvents, ProviderStatus } from '@openfeature/web-sdk';\nimport { Dispatch, SetStateAction, useEffect, useState } from 'react';\nimport { useOpenFeatureClient } from './provider';\n\ntype ReactFlagEvaluationOptions = {\n /**\n * Suspend flag evaluations while the provider is not ready.\n * Set to false if you don't want to use React Suspense API.\n * Defaults to true.\n */\n suspend?: boolean,\n /**\n * Update the component if the provider emits a ConfigurationChanged event.\n * Set to false to prevent components from re-rendering when flag value changes\n * are received by the associated provider.\n * Defaults to true.\n */\n updateOnConfigurationChanged?: boolean,\n /**\n * Update the component when the OpenFeature context changes.\n * Set to false to prevent components from re-rendering when attributes which \n * may be factors in flag evaluation change.\n * Defaults to true.\n */\n updateOnContextChanged?: boolean,\n} & FlagEvaluationOptions;\n\nconst DEFAULT_OPTIONS: ReactFlagEvaluationOptions = {\n updateOnContextChanged: true,\n updateOnConfigurationChanged: true,\n suspend: true,\n};\n\nenum SuspendState {\n Pending,\n Success,\n Error\n}\n\n/**\n * Evaluates a feature flag, returning evaluation details.\n * @param {string}flagKey the flag identifier\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @template T flag type\n * @returns { EvaluationDetails<T>} a EvaluationDetails object for this evaluation\n */\nexport function useFeatureFlag<T extends FlagValue>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T> {\n const defaultedOptions = { ...DEFAULT_OPTIONS, ...options };\n const [, updateState] = useState<object | undefined>();\n const forceUpdate = () => {\n updateState({});\n };\n const client = useOpenFeatureClient();\n\n useEffect(() => {\n\n if (client.providerStatus !== ProviderStatus.READY) {\n // update when the provider is ready\n client.addHandler(ProviderEvents.Ready, forceUpdate);\n if (defaultedOptions.suspend) {\n suspend(client, updateState);\n }\n }\n\n if (defaultedOptions.updateOnContextChanged) {\n // update when the context changes\n client.addHandler(ProviderEvents.ContextChanged, forceUpdate);\n }\n\n if (defaultedOptions.updateOnConfigurationChanged) {\n // update when the provider configuration changes\n client.addHandler(ProviderEvents.ConfigurationChanged, forceUpdate);\n }\n return () => {\n // cleanup the handlers (we can do this unconditionally with no impact)\n client.removeHandler(ProviderEvents.Ready, forceUpdate);\n client.removeHandler(ProviderEvents.ContextChanged, forceUpdate);\n client.removeHandler(ProviderEvents.ConfigurationChanged, forceUpdate);\n };\n }, [client]);\n\n return getFlag(client, flagKey, defaultValue);\n}\n\nfunction getFlag<T extends FlagValue>(client: Client, flagKey: string, defaultValue: T): EvaluationDetails<T> {\n if (typeof defaultValue === 'boolean') {\n return client.getBooleanDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n } else if (typeof defaultValue === 'string') {\n return client.getStringDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n } else if (typeof defaultValue === 'number') {\n return client.getNumberDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n } else {\n return client.getObjectDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n }\n}\n\n/**\n * Suspend function. If this runs, components using the calling hook will be suspended.\n * @param {Client} client the OpenFeature client\n * @param {Function} updateState the state update function\n */\nfunction suspend(client: Client, updateState: Dispatch<SetStateAction<object | undefined>>) {\n let suspendResolver: () => void;\n let suspendRejecter: () => void;\n const suspendPromise = new Promise<void>((resolve) => {\n suspendResolver = () => {\n resolve();\n client.removeHandler(ProviderEvents.Ready, suspendResolver); // remove handler once it's run\n };\n suspendRejecter = () => {\n resolve(); // we still resolve here, since we don't want to throw errors\n client.removeHandler(ProviderEvents.Error, suspendRejecter); // remove handler once it's run\n };\n client.addHandler(ProviderEvents.Ready, suspendResolver);\n client.addHandler(ProviderEvents.Error, suspendRejecter);\n });\n updateState(suspenseWrapper(suspendPromise));\n}\n\n/**\n * Promise wrapper that throws unresolved promises to support React suspense.\n * @param {Promise<T>} promise to wrap\n * @template T flag type\n * @returns {Function} suspense-compliant lambda\n */\nfunction suspenseWrapper <T>(promise: Promise<T>) {\n let status: SuspendState = SuspendState.Pending;\n let result: T;\n\n const suspended = promise.then(\n (value) => {\n status = SuspendState.Success;\n result = value;\n },\n (error) => {\n status = SuspendState.Error;\n result = error;\n }\n );\n\n return () => {\n switch (status) {\n case SuspendState.Pending:\n throw suspended;\n case SuspendState.Success:\n return result;\n case SuspendState.Error:\n throw result;\n default:\n throw new Error('Suspending promise is in an unknown state.');\n }\n };\n};", "import * as React from 'react';\nimport { Client, OpenFeature } from '@openfeature/web-sdk';\n\ntype ClientOrClientName =\n | {\n /**\n * The name of the client.\n * @see OpenFeature.setProvider() and overloads.\n */\n clientName: string;\n /**\n * OpenFeature client to use.\n */\n client?: never;\n }\n | {\n /**\n * OpenFeature client to use.\n */\n client: Client;\n /**\n * The name of the client.\n * @see OpenFeature.setProvider() and overloads.\n */\n clientName?: never;\n };\n\ntype ProviderProps = {\n children?: React.ReactNode;\n} & ClientOrClientName;\n\nconst Context = React.createContext<Client | undefined>(undefined);\n\nexport const OpenFeatureProvider = ({ client, clientName, children }: ProviderProps) => {\n if (!client) {\n client = OpenFeature.getClient(clientName);\n }\n\n return <Context.Provider value={client}>{children}</Context.Provider>;\n};\n\nexport const useOpenFeatureClient = () => {\n const client = React.useContext(Context);\n\n if (!client) {\n throw new Error(\n 'No OpenFeature client available - components using OpenFeature must be wrapped with an <OpenFeatureProvider>'\n );\n }\n\n return client;\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export * from './use-feature-flag';\nexport * from './provider';\n// re-export the web-sdk so consumers can access that API from the react-sdk\nexport * from '@openfeature/web-sdk';\n", "import { Client, EvaluationDetails, FlagEvaluationOptions, FlagValue, JsonValue, ProviderEvents, ProviderStatus } from '@openfeature/web-sdk';\nimport { Dispatch, SetStateAction, useEffect, useState } from 'react';\nimport { useOpenFeatureClient } from './provider';\n\ntype ReactFlagEvaluationOptions = {\n /**\n * Suspend flag evaluations while the provider is not ready.\n * Set to false if you don't want to use React Suspense API.\n * Defaults to true.\n */\n suspend?: boolean,\n /**\n * Update the component if the provider emits a ConfigurationChanged event.\n * Set to false to prevent components from re-rendering when flag value changes\n * are received by the associated provider.\n * Defaults to true.\n */\n updateOnConfigurationChanged?: boolean,\n /**\n * Update the component when the OpenFeature context changes.\n * Set to false to prevent components from re-rendering when attributes which \n * may be factors in flag evaluation change.\n * Defaults to true.\n */\n updateOnContextChanged?: boolean,\n} & FlagEvaluationOptions;\n\nconst DEFAULT_OPTIONS: ReactFlagEvaluationOptions = {\n updateOnContextChanged: true,\n updateOnConfigurationChanged: true,\n suspend: true,\n};\n\nenum SuspendState {\n Pending,\n Success,\n Error\n}\n\n/**\n * Evaluates a feature flag, returning a boolean.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @param {boolean} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { boolean} a EvaluationDetails object for this evaluation\n */\nexport function useBooleanFlagValue(flagKey: string, defaultValue: boolean, options?: ReactFlagEvaluationOptions): boolean {\n return useBooleanFlagDetails(flagKey, defaultValue, options).value;\n}\n\n/**\n * Evaluates a feature flag, returning evaluation details.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @param {boolean} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { EvaluationDetails<boolean>} a EvaluationDetails object for this evaluation\n */\nexport function useBooleanFlagDetails(flagKey: string, defaultValue: boolean, options?: ReactFlagEvaluationOptions): EvaluationDetails<boolean> {\n return attachHandlersAndResolve(flagKey, defaultValue, (client) => {\n return client.getBooleanDetails;\n }, options);\n}\n\n/**\n * Evaluates a feature flag, returning a string.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @template {string} [T=string] A optional generic argument constraining the string\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { boolean} a EvaluationDetails object for this evaluation\n */\nexport function useStringFlagValue<T extends string = string>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): T {\n return useStringFlagDetails(flagKey, defaultValue, options).value;\n}\n\n/**\n * Evaluates a feature flag, returning evaluation details.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @template {string} [T=string] A optional generic argument constraining the string\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { EvaluationDetails<string>} a EvaluationDetails object for this evaluation\n */\nexport function useStringFlagDetails<T extends string = string>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T> {\n return attachHandlersAndResolve(flagKey, defaultValue, (client) => {\n return client.getStringDetails<T>;\n }, options);\n}\n\n/**\n * Evaluates a feature flag, returning a number.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @template {number} [T=number] A optional generic argument constraining the number\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { boolean} a EvaluationDetails object for this evaluation\n */\nexport function useNumberFlagValue<T extends number = number>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): T {\n return useNumberFlagDetails(flagKey, defaultValue, options).value;\n}\n\n/**\n * Evaluates a feature flag, returning evaluation details.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @template {number} [T=number] A optional generic argument constraining the number\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { EvaluationDetails<number>} a EvaluationDetails object for this evaluation\n */\nexport function useNumberFlagDetails<T extends number = number>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T> {\n return attachHandlersAndResolve(flagKey, defaultValue, (client) => {\n return client.getNumberDetails<T>;\n }, options);\n}\n\n/**\n * Evaluates a feature flag, returning an object.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @template {JsonValue} [T=JsonValue] A optional generic argument describing the structure\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { boolean} a EvaluationDetails object for this evaluation\n */\nexport function useObjectFlagValue<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): T {\n return useObjectFlagDetails<T>(flagKey, defaultValue, options).value;\n}\n\n/**\n * Evaluates a feature flag, returning evaluation details.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @param {T} defaultValue the default value\n * @template {JsonValue} [T=JsonValue] A optional generic argument describing the structure\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { EvaluationDetails<T>} a EvaluationDetails object for this evaluation\n */\nexport function useObjectFlagDetails<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T> {\n return attachHandlersAndResolve(flagKey, defaultValue, (client) => {\n return client.getObjectDetails<T>;\n }, options);\n}\n\nfunction attachHandlersAndResolve<T extends FlagValue>(flagKey: string, defaultValue: T, resolver: (client: Client) => (flagKey: string, defaultValue: T) => EvaluationDetails<T>, options?: ReactFlagEvaluationOptions): EvaluationDetails<T> {\n const defaultedOptions = { ...DEFAULT_OPTIONS, ...options };\n const [, updateState] = useState<object | undefined>();\n const forceUpdate = () => {\n updateState({});\n };\n const client = useOpenFeatureClient();\n\n useEffect(() => {\n\n if (client.providerStatus !== ProviderStatus.READY) {\n // update when the provider is ready\n client.addHandler(ProviderEvents.Ready, forceUpdate);\n if (defaultedOptions.suspend) {\n suspend(client, updateState);\n }\n }\n\n if (defaultedOptions.updateOnContextChanged) {\n // update when the context changes\n client.addHandler(ProviderEvents.ContextChanged, forceUpdate);\n }\n\n if (defaultedOptions.updateOnConfigurationChanged) {\n // update when the provider configuration changes\n client.addHandler(ProviderEvents.ConfigurationChanged, forceUpdate);\n }\n return () => {\n // cleanup the handlers (we can do this unconditionally with no impact)\n client.removeHandler(ProviderEvents.Ready, forceUpdate);\n client.removeHandler(ProviderEvents.ContextChanged, forceUpdate);\n client.removeHandler(ProviderEvents.ConfigurationChanged, forceUpdate);\n };\n }, [client]);\n\n return resolver(client).call(client, flagKey, defaultValue);\n}\n\n/**\n * Suspend function. If this runs, components using the calling hook will be suspended.\n * @param {Client} client the OpenFeature client\n * @param {Function} updateState the state update function\n */\nfunction suspend(client: Client, updateState: Dispatch<SetStateAction<object | undefined>>) {\n let suspendResolver: () => void;\n let suspendRejecter: () => void;\n const suspendPromise = new Promise<void>((resolve) => {\n suspendResolver = () => {\n resolve();\n client.removeHandler(ProviderEvents.Ready, suspendResolver); // remove handler once it's run\n };\n suspendRejecter = () => {\n resolve(); // we still resolve here, since we don't want to throw errors\n client.removeHandler(ProviderEvents.Error, suspendRejecter); // remove handler once it's run\n };\n client.addHandler(ProviderEvents.Ready, suspendResolver);\n client.addHandler(ProviderEvents.Error, suspendRejecter);\n });\n updateState(suspenseWrapper(suspendPromise));\n}\n\n/**\n * Promise wrapper that throws unresolved promises to support React suspense.\n * @param {Promise<T>} promise to wrap\n * @template T flag type\n * @returns {Function} suspense-compliant lambda\n */\nfunction suspenseWrapper <T>(promise: Promise<T>) {\n let status: SuspendState = SuspendState.Pending;\n let result: T;\n\n const suspended = promise.then(\n (value) => {\n status = SuspendState.Success;\n result = value;\n },\n (error) => {\n status = SuspendState.Error;\n result = error;\n }\n );\n\n return () => {\n switch (status) {\n case SuspendState.Pending:\n throw suspended;\n case SuspendState.Success:\n return result;\n case SuspendState.Error:\n throw result;\n default:\n throw new Error('Suspending promise is in an unknown state.');\n }\n };\n};", "import * as React from 'react';\nimport { Client, OpenFeature } from '@openfeature/web-sdk';\n\ntype ClientOrClientName =\n | {\n /**\n * The name of the client.\n * @see OpenFeature.setProvider() and overloads.\n */\n clientName: string;\n /**\n * OpenFeature client to use.\n */\n client?: never;\n }\n | {\n /**\n * OpenFeature client to use.\n */\n client: Client;\n /**\n * The name of the client.\n * @see OpenFeature.setProvider() and overloads.\n */\n clientName?: never;\n };\n\ntype ProviderProps = {\n children?: React.ReactNode;\n} & ClientOrClientName;\n\nconst Context = React.createContext<Client | undefined>(undefined);\n\nexport const OpenFeatureProvider = ({ client, clientName, children }: ProviderProps) => {\n if (!client) {\n client = OpenFeature.getClient(clientName);\n }\n\n return <Context.Provider value={client}>{children}</Context.Provider>;\n};\n\nexport const useOpenFeatureClient = () => {\n const client = React.useContext(Context);\n\n if (!client) {\n throw new Error(\n 'No OpenFeature client available - components using OpenFeature must be wrapped with an <OpenFeatureProvider>'\n );\n }\n\n return client;\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,kBAAuH;AACvH,mBAA8D;;;ACD9D,YAAuB;AACvB,qBAAoC;AA8BpC,IAAM,UAAgB,oBAAkC,MAAS;AAE1D,IAAM,sBAAsB,CAAC,EAAE,QAAQ,YAAY,SAAS,MAAqB;AACtF,MAAI,CAAC,QAAQ;AACX,aAAS,2BAAY,UAAU,UAAU;AAAA,EAC3C;AAEA,SAAO,oCAAC,QAAQ,UAAR,EAAiB,OAAO,UAAS,QAAS;AACpD;AAEO,IAAM,uBAAuB,MAAM;AACxC,QAAM,SAAe,iBAAW,OAAO;AAEvC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ADxBA,IAAM,kBAA8C;AAAA,EAClD,wBAAwB;AAAA,EACxB,8BAA8B;AAAA,EAC9B,SAAS;AACX;AAgBO,SAAS,oBAAoB,SAAiB,cAAuB,SAA+C;AACzH,SAAO,sBAAsB,SAAS,cAAc,OAAO,EAAE;AAC/D;AAUO,SAAS,sBAAsB,SAAiB,cAAuB,SAAkE;AAC9I,SAAO,yBAAyB,SAAS,cAAc,CAAC,WAAW;AACjE,WAAO,OAAO;AAAA,EAChB,GAAI,OAAO;AACb;AAWO,SAAS,mBAA8C,SAAiB,cAAiB,SAAyC;AACvI,SAAO,qBAAqB,SAAS,cAAc,OAAO,EAAE;AAC9D;AAWO,SAAS,qBAAgD,SAAiB,cAAiB,SAA4D;AAC5J,SAAO,yBAAyB,SAAS,cAAc,CAAC,WAAW;AACjE,WAAO,OAAO;AAAA,EAChB,GAAI,OAAO;AACb;AAWO,SAAS,mBAA8C,SAAiB,cAAiB,SAAyC;AACvI,SAAO,qBAAqB,SAAS,cAAc,OAAO,EAAE;AAC9D;AAWO,SAAS,qBAAgD,SAAiB,cAAiB,SAA4D;AAC5J,SAAO,yBAAyB,SAAS,cAAc,CAAC,WAAW;AACjE,WAAO,OAAO;AAAA,EAChB,GAAI,OAAO;AACb;AAWO,SAAS,mBAAoD,SAAiB,cAAiB,SAAyC;AAC7I,SAAO,qBAAwB,SAAS,cAAc,OAAO,EAAE;AACjE;AAWO,SAAS,qBAAsD,SAAiB,cAAiB,SAA4D;AAClK,SAAO,yBAAyB,SAAS,cAAc,CAAC,WAAW;AACjE,WAAO,OAAO;AAAA,EAChB,GAAI,OAAO;AACb;AAEA,SAAS,yBAA8C,SAAiB,cAAiB,UAA0F,SAA4D;AAC7O,QAAM,mBAAmB,kCAAK,kBAAoB;AAClD,QAAM,CAAC,EAAE,WAAW,QAAI,uBAA6B;AACrD,QAAM,cAAc,MAAM;AACxB,gBAAY,CAAC,CAAC;AAAA,EAChB;AACA,QAAM,SAAS,qBAAqB;AAEpC,8BAAU,MAAM;AAEd,QAAI,OAAO,mBAAmB,+BAAe,OAAO;AAElD,aAAO,WAAW,+BAAe,OAAO,WAAW;AACnD,UAAI,iBAAiB,SAAS;AAC5B,gBAAQ,QAAQ,WAAW;AAAA,MAC7B;AAAA,IACF;AAEA,QAAI,iBAAiB,wBAAwB;AAE3C,aAAO,WAAW,+BAAe,gBAAgB,WAAW;AAAA,IAC9D;AAEA,QAAI,iBAAiB,8BAA8B;AAEjD,aAAO,WAAW,+BAAe,sBAAsB,WAAW;AAAA,IACpE;AACA,WAAO,MAAM;AAEX,aAAO,cAAc,+BAAe,OAAO,WAAW;AACtD,aAAO,cAAc,+BAAe,gBAAgB,WAAW;AAC/D,aAAO,cAAc,+BAAe,sBAAsB,WAAW;AAAA,IACvE;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO,SAAS,MAAM,EAAE,KAAK,QAAQ,SAAS,YAAY;AAC5D;AAOA,SAAS,QAAQ,QAAgB,aAA2D;AAC1F,MAAI;AACJ,MAAI;AACJ,QAAM,iBAAiB,IAAI,QAAc,CAAC,YAAY;AACpD,sBAAkB,MAAM;AACtB,cAAQ;AACR,aAAO,cAAc,+BAAe,OAAO,eAAe;AAAA,IAC5D;AACA,sBAAkB,MAAM;AACtB,cAAQ;AACR,aAAO,cAAc,+BAAe,OAAO,eAAe;AAAA,IAC5D;AACA,WAAO,WAAW,+BAAe,OAAO,eAAe;AACvD,WAAO,WAAW,+BAAe,OAAO,eAAe;AAAA,EACzD,CAAC;AACD,cAAY,gBAAgB,cAAc,CAAC;AAC7C;AAQA,SAAS,gBAAoB,SAAqB;AAChD,MAAI,SAAuB;AAC3B,MAAI;AAEJ,QAAM,YAAY,QAAQ;AAAA,IACxB,CAAC,UAAU;AACT,eAAS;AACT,eAAS;AAAA,IACX;AAAA,IACA,CAAC,UAAU;AACT,eAAS;AACT,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO,MAAM;AACX,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,cAAM;AAAA,MACR,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,cAAM;AAAA,MACR;AACE,cAAM,IAAI,MAAM,4CAA4C;AAAA,IAChE;AAAA,EACF;AACF;;;ADhPA,wBAAc,iCAHd;",
6
6
  "names": ["import_web_sdk"]
7
7
  }
package/dist/esm/index.js CHANGED
@@ -45,7 +45,39 @@ var DEFAULT_OPTIONS = {
45
45
  updateOnConfigurationChanged: true,
46
46
  suspend: true
47
47
  };
48
- function useFeatureFlag(flagKey, defaultValue, options) {
48
+ function useBooleanFlagValue(flagKey, defaultValue, options) {
49
+ return useBooleanFlagDetails(flagKey, defaultValue, options).value;
50
+ }
51
+ function useBooleanFlagDetails(flagKey, defaultValue, options) {
52
+ return attachHandlersAndResolve(flagKey, defaultValue, (client) => {
53
+ return client.getBooleanDetails;
54
+ }, options);
55
+ }
56
+ function useStringFlagValue(flagKey, defaultValue, options) {
57
+ return useStringFlagDetails(flagKey, defaultValue, options).value;
58
+ }
59
+ function useStringFlagDetails(flagKey, defaultValue, options) {
60
+ return attachHandlersAndResolve(flagKey, defaultValue, (client) => {
61
+ return client.getStringDetails;
62
+ }, options);
63
+ }
64
+ function useNumberFlagValue(flagKey, defaultValue, options) {
65
+ return useNumberFlagDetails(flagKey, defaultValue, options).value;
66
+ }
67
+ function useNumberFlagDetails(flagKey, defaultValue, options) {
68
+ return attachHandlersAndResolve(flagKey, defaultValue, (client) => {
69
+ return client.getNumberDetails;
70
+ }, options);
71
+ }
72
+ function useObjectFlagValue(flagKey, defaultValue, options) {
73
+ return useObjectFlagDetails(flagKey, defaultValue, options).value;
74
+ }
75
+ function useObjectFlagDetails(flagKey, defaultValue, options) {
76
+ return attachHandlersAndResolve(flagKey, defaultValue, (client) => {
77
+ return client.getObjectDetails;
78
+ }, options);
79
+ }
80
+ function attachHandlersAndResolve(flagKey, defaultValue, resolver, options) {
49
81
  const defaultedOptions = __spreadValues(__spreadValues({}, DEFAULT_OPTIONS), options);
50
82
  const [, updateState] = useState();
51
83
  const forceUpdate = () => {
@@ -71,18 +103,7 @@ function useFeatureFlag(flagKey, defaultValue, options) {
71
103
  client.removeHandler(ProviderEvents.ConfigurationChanged, forceUpdate);
72
104
  };
73
105
  }, [client]);
74
- return getFlag(client, flagKey, defaultValue);
75
- }
76
- function getFlag(client, flagKey, defaultValue) {
77
- if (typeof defaultValue === "boolean") {
78
- return client.getBooleanDetails(flagKey, defaultValue);
79
- } else if (typeof defaultValue === "string") {
80
- return client.getStringDetails(flagKey, defaultValue);
81
- } else if (typeof defaultValue === "number") {
82
- return client.getNumberDetails(flagKey, defaultValue);
83
- } else {
84
- return client.getObjectDetails(flagKey, defaultValue);
85
- }
106
+ return resolver(client).call(client, flagKey, defaultValue);
86
107
  }
87
108
  function suspend(client, updateState) {
88
109
  let suspendResolver;
@@ -132,7 +153,14 @@ function suspenseWrapper(promise) {
132
153
  export * from "@openfeature/web-sdk";
133
154
  export {
134
155
  OpenFeatureProvider,
135
- useFeatureFlag,
136
- useOpenFeatureClient
156
+ useBooleanFlagDetails,
157
+ useBooleanFlagValue,
158
+ useNumberFlagDetails,
159
+ useNumberFlagValue,
160
+ useObjectFlagDetails,
161
+ useObjectFlagValue,
162
+ useOpenFeatureClient,
163
+ useStringFlagDetails,
164
+ useStringFlagValue
137
165
  };
138
166
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/use-feature-flag.ts", "../../src/provider.tsx", "../../src/index.ts"],
4
- "sourcesContent": ["import { Client, EvaluationDetails, FlagEvaluationOptions, FlagValue, ProviderEvents, ProviderStatus } from '@openfeature/web-sdk';\nimport { Dispatch, SetStateAction, useEffect, useState } from 'react';\nimport { useOpenFeatureClient } from './provider';\n\ntype ReactFlagEvaluationOptions = {\n /**\n * Suspend flag evaluations while the provider is not ready.\n * Set to false if you don't want to use React Suspense API.\n * Defaults to true.\n */\n suspend?: boolean,\n /**\n * Update the component if the provider emits a ConfigurationChanged event.\n * Set to false to prevent components from re-rendering when flag value changes\n * are received by the associated provider.\n * Defaults to true.\n */\n updateOnConfigurationChanged?: boolean,\n /**\n * Update the component when the OpenFeature context changes.\n * Set to false to prevent components from re-rendering when attributes which \n * may be factors in flag evaluation change.\n * Defaults to true.\n */\n updateOnContextChanged?: boolean,\n} & FlagEvaluationOptions;\n\nconst DEFAULT_OPTIONS: ReactFlagEvaluationOptions = {\n updateOnContextChanged: true,\n updateOnConfigurationChanged: true,\n suspend: true,\n};\n\nenum SuspendState {\n Pending,\n Success,\n Error\n}\n\n/**\n * Evaluates a feature flag, returning evaluation details.\n * @param {string}flagKey the flag identifier\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @template T flag type\n * @returns { EvaluationDetails<T>} a EvaluationDetails object for this evaluation\n */\nexport function useFeatureFlag<T extends FlagValue>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T> {\n const defaultedOptions = { ...DEFAULT_OPTIONS, ...options };\n const [, updateState] = useState<object | undefined>();\n const forceUpdate = () => {\n updateState({});\n };\n const client = useOpenFeatureClient();\n\n useEffect(() => {\n\n if (client.providerStatus !== ProviderStatus.READY) {\n // update when the provider is ready\n client.addHandler(ProviderEvents.Ready, forceUpdate);\n if (defaultedOptions.suspend) {\n suspend(client, updateState);\n }\n }\n\n if (defaultedOptions.updateOnContextChanged) {\n // update when the context changes\n client.addHandler(ProviderEvents.ContextChanged, forceUpdate);\n }\n\n if (defaultedOptions.updateOnConfigurationChanged) {\n // update when the provider configuration changes\n client.addHandler(ProviderEvents.ConfigurationChanged, forceUpdate);\n }\n return () => {\n // cleanup the handlers (we can do this unconditionally with no impact)\n client.removeHandler(ProviderEvents.Ready, forceUpdate);\n client.removeHandler(ProviderEvents.ContextChanged, forceUpdate);\n client.removeHandler(ProviderEvents.ConfigurationChanged, forceUpdate);\n };\n }, [client]);\n\n return getFlag(client, flagKey, defaultValue);\n}\n\nfunction getFlag<T extends FlagValue>(client: Client, flagKey: string, defaultValue: T): EvaluationDetails<T> {\n if (typeof defaultValue === 'boolean') {\n return client.getBooleanDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n } else if (typeof defaultValue === 'string') {\n return client.getStringDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n } else if (typeof defaultValue === 'number') {\n return client.getNumberDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n } else {\n return client.getObjectDetails(flagKey, defaultValue) as EvaluationDetails<T>;\n }\n}\n\n/**\n * Suspend function. If this runs, components using the calling hook will be suspended.\n * @param {Client} client the OpenFeature client\n * @param {Function} updateState the state update function\n */\nfunction suspend(client: Client, updateState: Dispatch<SetStateAction<object | undefined>>) {\n let suspendResolver: () => void;\n let suspendRejecter: () => void;\n const suspendPromise = new Promise<void>((resolve) => {\n suspendResolver = () => {\n resolve();\n client.removeHandler(ProviderEvents.Ready, suspendResolver); // remove handler once it's run\n };\n suspendRejecter = () => {\n resolve(); // we still resolve here, since we don't want to throw errors\n client.removeHandler(ProviderEvents.Error, suspendRejecter); // remove handler once it's run\n };\n client.addHandler(ProviderEvents.Ready, suspendResolver);\n client.addHandler(ProviderEvents.Error, suspendRejecter);\n });\n updateState(suspenseWrapper(suspendPromise));\n}\n\n/**\n * Promise wrapper that throws unresolved promises to support React suspense.\n * @param {Promise<T>} promise to wrap\n * @template T flag type\n * @returns {Function} suspense-compliant lambda\n */\nfunction suspenseWrapper <T>(promise: Promise<T>) {\n let status: SuspendState = SuspendState.Pending;\n let result: T;\n\n const suspended = promise.then(\n (value) => {\n status = SuspendState.Success;\n result = value;\n },\n (error) => {\n status = SuspendState.Error;\n result = error;\n }\n );\n\n return () => {\n switch (status) {\n case SuspendState.Pending:\n throw suspended;\n case SuspendState.Success:\n return result;\n case SuspendState.Error:\n throw result;\n default:\n throw new Error('Suspending promise is in an unknown state.');\n }\n };\n};", "import * as React from 'react';\nimport { Client, OpenFeature } from '@openfeature/web-sdk';\n\ntype ClientOrClientName =\n | {\n /**\n * The name of the client.\n * @see OpenFeature.setProvider() and overloads.\n */\n clientName: string;\n /**\n * OpenFeature client to use.\n */\n client?: never;\n }\n | {\n /**\n * OpenFeature client to use.\n */\n client: Client;\n /**\n * The name of the client.\n * @see OpenFeature.setProvider() and overloads.\n */\n clientName?: never;\n };\n\ntype ProviderProps = {\n children?: React.ReactNode;\n} & ClientOrClientName;\n\nconst Context = React.createContext<Client | undefined>(undefined);\n\nexport const OpenFeatureProvider = ({ client, clientName, children }: ProviderProps) => {\n if (!client) {\n client = OpenFeature.getClient(clientName);\n }\n\n return <Context.Provider value={client}>{children}</Context.Provider>;\n};\n\nexport const useOpenFeatureClient = () => {\n const client = React.useContext(Context);\n\n if (!client) {\n throw new Error(\n 'No OpenFeature client available - components using OpenFeature must be wrapped with an <OpenFeatureProvider>'\n );\n }\n\n return client;\n};\n", "export * from './use-feature-flag';\nexport * from './provider';\n// re-export the web-sdk so consumers can access that API from the react-sdk\nexport * from '@openfeature/web-sdk';\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA,SAAsE,gBAAgB,sBAAsB;AAC5G,SAAmC,WAAW,gBAAgB;;;ACD9D,YAAY,WAAW;AACvB,SAAiB,mBAAmB;AA8BpC,IAAM,UAAgB,oBAAkC,MAAS;AAE1D,IAAM,sBAAsB,CAAC,EAAE,QAAQ,YAAY,SAAS,MAAqB;AACtF,MAAI,CAAC,QAAQ;AACX,aAAS,YAAY,UAAU,UAAU;AAAA,EAC3C;AAEA,SAAO,oCAAC,QAAQ,UAAR,EAAiB,OAAO,UAAS,QAAS;AACpD;AAEO,IAAM,uBAAuB,MAAM;AACxC,QAAM,SAAe,iBAAW,OAAO;AAEvC,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;ADxBA,IAAM,kBAA8C;AAAA,EAClD,wBAAwB;AAAA,EACxB,8BAA8B;AAAA,EAC9B,SAAS;AACX;AAgBO,SAAS,eAAoC,SAAiB,cAAiB,SAA4D;AAChJ,QAAM,mBAAmB,kCAAK,kBAAoB;AAClD,QAAM,CAAC,EAAE,WAAW,IAAI,SAA6B;AACrD,QAAM,cAAc,MAAM;AACxB,gBAAY,CAAC,CAAC;AAAA,EAChB;AACA,QAAM,SAAS,qBAAqB;AAEpC,YAAU,MAAM;AAEd,QAAI,OAAO,mBAAmB,eAAe,OAAO;AAElD,aAAO,WAAW,eAAe,OAAO,WAAW;AACnD,UAAI,iBAAiB,SAAS;AAC5B,gBAAQ,QAAQ,WAAW;AAAA,MAC7B;AAAA,IACF;AAEA,QAAI,iBAAiB,wBAAwB;AAE3C,aAAO,WAAW,eAAe,gBAAgB,WAAW;AAAA,IAC9D;AAEA,QAAI,iBAAiB,8BAA8B;AAEjD,aAAO,WAAW,eAAe,sBAAsB,WAAW;AAAA,IACpE;AACA,WAAO,MAAM;AAEX,aAAO,cAAc,eAAe,OAAO,WAAW;AACtD,aAAO,cAAc,eAAe,gBAAgB,WAAW;AAC/D,aAAO,cAAc,eAAe,sBAAsB,WAAW;AAAA,IACvE;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AAEX,SAAO,QAAQ,QAAQ,SAAS,YAAY;AAC9C;AAEA,SAAS,QAA6B,QAAgB,SAAiB,cAAuC;AAC5G,MAAI,OAAO,iBAAiB,WAAW;AACrC,WAAO,OAAO,kBAAkB,SAAS,YAAY;AAAA,EACvD,WAAW,OAAO,iBAAiB,UAAU;AAC3C,WAAO,OAAO,iBAAiB,SAAS,YAAY;AAAA,EACtD,WAAW,OAAO,iBAAiB,UAAU;AAC3C,WAAO,OAAO,iBAAiB,SAAS,YAAY;AAAA,EACtD,OAAO;AACL,WAAO,OAAO,iBAAiB,SAAS,YAAY;AAAA,EACtD;AACF;AAOA,SAAS,QAAQ,QAAgB,aAA2D;AAC1F,MAAI;AACJ,MAAI;AACJ,QAAM,iBAAiB,IAAI,QAAc,CAAC,YAAY;AACpD,sBAAkB,MAAM;AACtB,cAAQ;AACR,aAAO,cAAc,eAAe,OAAO,eAAe;AAAA,IAC5D;AACA,sBAAkB,MAAM;AACtB,cAAQ;AACR,aAAO,cAAc,eAAe,OAAO,eAAe;AAAA,IAC5D;AACA,WAAO,WAAW,eAAe,OAAO,eAAe;AACvD,WAAO,WAAW,eAAe,OAAO,eAAe;AAAA,EACzD,CAAC;AACD,cAAY,gBAAgB,cAAc,CAAC;AAC7C;AAQA,SAAS,gBAAoB,SAAqB;AAChD,MAAI,SAAuB;AAC3B,MAAI;AAEJ,QAAM,YAAY,QAAQ;AAAA,IACxB,CAAC,UAAU;AACT,eAAS;AACT,eAAS;AAAA,IACX;AAAA,IACA,CAAC,UAAU;AACT,eAAS;AACT,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO,MAAM;AACX,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,cAAM;AAAA,MACR,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,cAAM;AAAA,MACR;AACE,cAAM,IAAI,MAAM,4CAA4C;AAAA,IAChE;AAAA,EACF;AACF;;;AEtJA,cAAc;",
4
+ "sourcesContent": ["import { Client, EvaluationDetails, FlagEvaluationOptions, FlagValue, JsonValue, ProviderEvents, ProviderStatus } from '@openfeature/web-sdk';\nimport { Dispatch, SetStateAction, useEffect, useState } from 'react';\nimport { useOpenFeatureClient } from './provider';\n\ntype ReactFlagEvaluationOptions = {\n /**\n * Suspend flag evaluations while the provider is not ready.\n * Set to false if you don't want to use React Suspense API.\n * Defaults to true.\n */\n suspend?: boolean,\n /**\n * Update the component if the provider emits a ConfigurationChanged event.\n * Set to false to prevent components from re-rendering when flag value changes\n * are received by the associated provider.\n * Defaults to true.\n */\n updateOnConfigurationChanged?: boolean,\n /**\n * Update the component when the OpenFeature context changes.\n * Set to false to prevent components from re-rendering when attributes which \n * may be factors in flag evaluation change.\n * Defaults to true.\n */\n updateOnContextChanged?: boolean,\n} & FlagEvaluationOptions;\n\nconst DEFAULT_OPTIONS: ReactFlagEvaluationOptions = {\n updateOnContextChanged: true,\n updateOnConfigurationChanged: true,\n suspend: true,\n};\n\nenum SuspendState {\n Pending,\n Success,\n Error\n}\n\n/**\n * Evaluates a feature flag, returning a boolean.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @param {boolean} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { boolean} a EvaluationDetails object for this evaluation\n */\nexport function useBooleanFlagValue(flagKey: string, defaultValue: boolean, options?: ReactFlagEvaluationOptions): boolean {\n return useBooleanFlagDetails(flagKey, defaultValue, options).value;\n}\n\n/**\n * Evaluates a feature flag, returning evaluation details.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @param {boolean} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { EvaluationDetails<boolean>} a EvaluationDetails object for this evaluation\n */\nexport function useBooleanFlagDetails(flagKey: string, defaultValue: boolean, options?: ReactFlagEvaluationOptions): EvaluationDetails<boolean> {\n return attachHandlersAndResolve(flagKey, defaultValue, (client) => {\n return client.getBooleanDetails;\n }, options);\n}\n\n/**\n * Evaluates a feature flag, returning a string.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @template {string} [T=string] A optional generic argument constraining the string\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { boolean} a EvaluationDetails object for this evaluation\n */\nexport function useStringFlagValue<T extends string = string>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): T {\n return useStringFlagDetails(flagKey, defaultValue, options).value;\n}\n\n/**\n * Evaluates a feature flag, returning evaluation details.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @template {string} [T=string] A optional generic argument constraining the string\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { EvaluationDetails<string>} a EvaluationDetails object for this evaluation\n */\nexport function useStringFlagDetails<T extends string = string>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T> {\n return attachHandlersAndResolve(flagKey, defaultValue, (client) => {\n return client.getStringDetails<T>;\n }, options);\n}\n\n/**\n * Evaluates a feature flag, returning a number.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @template {number} [T=number] A optional generic argument constraining the number\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { boolean} a EvaluationDetails object for this evaluation\n */\nexport function useNumberFlagValue<T extends number = number>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): T {\n return useNumberFlagDetails(flagKey, defaultValue, options).value;\n}\n\n/**\n * Evaluates a feature flag, returning evaluation details.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @template {number} [T=number] A optional generic argument constraining the number\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { EvaluationDetails<number>} a EvaluationDetails object for this evaluation\n */\nexport function useNumberFlagDetails<T extends number = number>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T> {\n return attachHandlersAndResolve(flagKey, defaultValue, (client) => {\n return client.getNumberDetails<T>;\n }, options);\n}\n\n/**\n * Evaluates a feature flag, returning an object.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @template {JsonValue} [T=JsonValue] A optional generic argument describing the structure\n * @param {T} defaultValue the default value\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { boolean} a EvaluationDetails object for this evaluation\n */\nexport function useObjectFlagValue<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): T {\n return useObjectFlagDetails<T>(flagKey, defaultValue, options).value;\n}\n\n/**\n * Evaluates a feature flag, returning evaluation details.\n * By default, components will re-render when the flag value changes.\n * @param {string} flagKey the flag identifier\n * @param {T} defaultValue the default value\n * @template {JsonValue} [T=JsonValue] A optional generic argument describing the structure\n * @param {ReactFlagEvaluationOptions} options options for this evaluation\n * @returns { EvaluationDetails<T>} a EvaluationDetails object for this evaluation\n */\nexport function useObjectFlagDetails<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T> {\n return attachHandlersAndResolve(flagKey, defaultValue, (client) => {\n return client.getObjectDetails<T>;\n }, options);\n}\n\nfunction attachHandlersAndResolve<T extends FlagValue>(flagKey: string, defaultValue: T, resolver: (client: Client) => (flagKey: string, defaultValue: T) => EvaluationDetails<T>, options?: ReactFlagEvaluationOptions): EvaluationDetails<T> {\n const defaultedOptions = { ...DEFAULT_OPTIONS, ...options };\n const [, updateState] = useState<object | undefined>();\n const forceUpdate = () => {\n updateState({});\n };\n const client = useOpenFeatureClient();\n\n useEffect(() => {\n\n if (client.providerStatus !== ProviderStatus.READY) {\n // update when the provider is ready\n client.addHandler(ProviderEvents.Ready, forceUpdate);\n if (defaultedOptions.suspend) {\n suspend(client, updateState);\n }\n }\n\n if (defaultedOptions.updateOnContextChanged) {\n // update when the context changes\n client.addHandler(ProviderEvents.ContextChanged, forceUpdate);\n }\n\n if (defaultedOptions.updateOnConfigurationChanged) {\n // update when the provider configuration changes\n client.addHandler(ProviderEvents.ConfigurationChanged, forceUpdate);\n }\n return () => {\n // cleanup the handlers (we can do this unconditionally with no impact)\n client.removeHandler(ProviderEvents.Ready, forceUpdate);\n client.removeHandler(ProviderEvents.ContextChanged, forceUpdate);\n client.removeHandler(ProviderEvents.ConfigurationChanged, forceUpdate);\n };\n }, [client]);\n\n return resolver(client).call(client, flagKey, defaultValue);\n}\n\n/**\n * Suspend function. If this runs, components using the calling hook will be suspended.\n * @param {Client} client the OpenFeature client\n * @param {Function} updateState the state update function\n */\nfunction suspend(client: Client, updateState: Dispatch<SetStateAction<object | undefined>>) {\n let suspendResolver: () => void;\n let suspendRejecter: () => void;\n const suspendPromise = new Promise<void>((resolve) => {\n suspendResolver = () => {\n resolve();\n client.removeHandler(ProviderEvents.Ready, suspendResolver); // remove handler once it's run\n };\n suspendRejecter = () => {\n resolve(); // we still resolve here, since we don't want to throw errors\n client.removeHandler(ProviderEvents.Error, suspendRejecter); // remove handler once it's run\n };\n client.addHandler(ProviderEvents.Ready, suspendResolver);\n client.addHandler(ProviderEvents.Error, suspendRejecter);\n });\n updateState(suspenseWrapper(suspendPromise));\n}\n\n/**\n * Promise wrapper that throws unresolved promises to support React suspense.\n * @param {Promise<T>} promise to wrap\n * @template T flag type\n * @returns {Function} suspense-compliant lambda\n */\nfunction suspenseWrapper <T>(promise: Promise<T>) {\n let status: SuspendState = SuspendState.Pending;\n let result: T;\n\n const suspended = promise.then(\n (value) => {\n status = SuspendState.Success;\n result = value;\n },\n (error) => {\n status = SuspendState.Error;\n result = error;\n }\n );\n\n return () => {\n switch (status) {\n case SuspendState.Pending:\n throw suspended;\n case SuspendState.Success:\n return result;\n case SuspendState.Error:\n throw result;\n default:\n throw new Error('Suspending promise is in an unknown state.');\n }\n };\n};", "import * as React from 'react';\nimport { Client, OpenFeature } from '@openfeature/web-sdk';\n\ntype ClientOrClientName =\n | {\n /**\n * The name of the client.\n * @see OpenFeature.setProvider() and overloads.\n */\n clientName: string;\n /**\n * OpenFeature client to use.\n */\n client?: never;\n }\n | {\n /**\n * OpenFeature client to use.\n */\n client: Client;\n /**\n * The name of the client.\n * @see OpenFeature.setProvider() and overloads.\n */\n clientName?: never;\n };\n\ntype ProviderProps = {\n children?: React.ReactNode;\n} & ClientOrClientName;\n\nconst Context = React.createContext<Client | undefined>(undefined);\n\nexport const OpenFeatureProvider = ({ client, clientName, children }: ProviderProps) => {\n if (!client) {\n client = OpenFeature.getClient(clientName);\n }\n\n return <Context.Provider value={client}>{children}</Context.Provider>;\n};\n\nexport const useOpenFeatureClient = () => {\n const client = React.useContext(Context);\n\n if (!client) {\n throw new Error(\n 'No OpenFeature client available - components using OpenFeature must be wrapped with an <OpenFeatureProvider>'\n );\n }\n\n return client;\n};\n", "export * from './use-feature-flag';\nexport * from './provider';\n// re-export the web-sdk so consumers can access that API from the react-sdk\nexport * from '@openfeature/web-sdk';\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/types.d.ts CHANGED
@@ -1014,15 +1014,84 @@ type ReactFlagEvaluationOptions = {
1014
1014
  */
1015
1015
  updateOnContextChanged?: boolean;
1016
1016
  } & FlagEvaluationOptions;
1017
+ /**
1018
+ * Evaluates a feature flag, returning a boolean.
1019
+ * By default, components will re-render when the flag value changes.
1020
+ * @param {string} flagKey the flag identifier
1021
+ * @param {boolean} defaultValue the default value
1022
+ * @param {ReactFlagEvaluationOptions} options options for this evaluation
1023
+ * @returns { boolean} a EvaluationDetails object for this evaluation
1024
+ */
1025
+ declare function useBooleanFlagValue(flagKey: string, defaultValue: boolean, options?: ReactFlagEvaluationOptions): boolean;
1026
+ /**
1027
+ * Evaluates a feature flag, returning evaluation details.
1028
+ * By default, components will re-render when the flag value changes.
1029
+ * @param {string} flagKey the flag identifier
1030
+ * @param {boolean} defaultValue the default value
1031
+ * @param {ReactFlagEvaluationOptions} options options for this evaluation
1032
+ * @returns { EvaluationDetails<boolean>} a EvaluationDetails object for this evaluation
1033
+ */
1034
+ declare function useBooleanFlagDetails(flagKey: string, defaultValue: boolean, options?: ReactFlagEvaluationOptions): EvaluationDetails<boolean>;
1035
+ /**
1036
+ * Evaluates a feature flag, returning a string.
1037
+ * By default, components will re-render when the flag value changes.
1038
+ * @param {string} flagKey the flag identifier
1039
+ * @template {string} [T=string] A optional generic argument constraining the string
1040
+ * @param {T} defaultValue the default value
1041
+ * @param {ReactFlagEvaluationOptions} options options for this evaluation
1042
+ * @returns { boolean} a EvaluationDetails object for this evaluation
1043
+ */
1044
+ declare function useStringFlagValue<T extends string = string>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): T;
1045
+ /**
1046
+ * Evaluates a feature flag, returning evaluation details.
1047
+ * By default, components will re-render when the flag value changes.
1048
+ * @param {string} flagKey the flag identifier
1049
+ * @template {string} [T=string] A optional generic argument constraining the string
1050
+ * @param {T} defaultValue the default value
1051
+ * @param {ReactFlagEvaluationOptions} options options for this evaluation
1052
+ * @returns { EvaluationDetails<string>} a EvaluationDetails object for this evaluation
1053
+ */
1054
+ declare function useStringFlagDetails<T extends string = string>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T>;
1055
+ /**
1056
+ * Evaluates a feature flag, returning a number.
1057
+ * By default, components will re-render when the flag value changes.
1058
+ * @param {string} flagKey the flag identifier
1059
+ * @template {number} [T=number] A optional generic argument constraining the number
1060
+ * @param {T} defaultValue the default value
1061
+ * @param {ReactFlagEvaluationOptions} options options for this evaluation
1062
+ * @returns { boolean} a EvaluationDetails object for this evaluation
1063
+ */
1064
+ declare function useNumberFlagValue<T extends number = number>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): T;
1065
+ /**
1066
+ * Evaluates a feature flag, returning evaluation details.
1067
+ * By default, components will re-render when the flag value changes.
1068
+ * @param {string} flagKey the flag identifier
1069
+ * @template {number} [T=number] A optional generic argument constraining the number
1070
+ * @param {T} defaultValue the default value
1071
+ * @param {ReactFlagEvaluationOptions} options options for this evaluation
1072
+ * @returns { EvaluationDetails<number>} a EvaluationDetails object for this evaluation
1073
+ */
1074
+ declare function useNumberFlagDetails<T extends number = number>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T>;
1075
+ /**
1076
+ * Evaluates a feature flag, returning an object.
1077
+ * By default, components will re-render when the flag value changes.
1078
+ * @param {string} flagKey the flag identifier
1079
+ * @template {JsonValue} [T=JsonValue] A optional generic argument describing the structure
1080
+ * @param {T} defaultValue the default value
1081
+ * @param {ReactFlagEvaluationOptions} options options for this evaluation
1082
+ * @returns { boolean} a EvaluationDetails object for this evaluation
1083
+ */
1084
+ declare function useObjectFlagValue<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): T;
1017
1085
  /**
1018
1086
  * Evaluates a feature flag, returning evaluation details.
1019
- * @param {string}flagKey the flag identifier
1087
+ * By default, components will re-render when the flag value changes.
1088
+ * @param {string} flagKey the flag identifier
1020
1089
  * @param {T} defaultValue the default value
1090
+ * @template {JsonValue} [T=JsonValue] A optional generic argument describing the structure
1021
1091
  * @param {ReactFlagEvaluationOptions} options options for this evaluation
1022
- * @template T flag type
1023
1092
  * @returns { EvaluationDetails<T>} a EvaluationDetails object for this evaluation
1024
1093
  */
1025
- declare function useFeatureFlag<T extends FlagValue>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T>;
1094
+ declare function useObjectFlagDetails<T extends JsonValue = JsonValue>(flagKey: string, defaultValue: T, options?: ReactFlagEvaluationOptions): EvaluationDetails<T>;
1026
1095
 
1027
1096
  type ClientOrClientName = {
1028
1097
  /**
@@ -1051,4 +1120,4 @@ type ProviderProps = {
1051
1120
  declare const OpenFeatureProvider: ({ client, clientName, children }: ProviderProps) => React.JSX.Element;
1052
1121
  declare const useOpenFeatureClient: () => Client;
1053
1122
 
1054
- export { ClientProviderEvents as AllProviderEvents, AnyProviderEvent, BaseHook, BeforeHookContext, Client, ClientMetadata, ClientProviderEvents, CommonEventDetails, CommonProvider, ConfigChangeEvent, DefaultLogger, ErrorCode, ErrorEvent, EvaluationContext, EvaluationContextValue, EvaluationDetails, EvaluationLifeCycle, EventContext, EventDetails, EventHandler, EventMetadata, Eventing, Features, FlagEvaluationOptions, FlagMetadata, FlagNotFoundError, FlagValue, FlagValueType, GeneralError, GenericEventEmitter, Hook, HookContext, HookHints, InMemoryProvider, InvalidContextError, JsonArray, JsonObject, JsonValue, LOG_LEVELS, Logger, ManageContext, ManageLogger, Metadata, NOOP_PROVIDER, OpenFeature, OpenFeatureAPI, OpenFeatureClient, OpenFeatureCommonAPI, OpenFeatureError, OpenFeatureEventEmitter, OpenFeatureProvider, Paradigm, ParseError, PrimitiveValue, Provider, ProviderEmittableEvents, ClientProviderEvents as ProviderEvents, ProviderMetadata, ProviderNotReadyError, ProviderStatus, ReadyEvent, ResolutionDetails, ResolutionReason, SafeLogger, ServerProviderEvents, StaleEvent, StandardResolutionReasons, TargetingKeyMissingError, TypeMismatchError, isObject, isString, objectOrUndefined, statusMatchesEvent, stringOrUndefined, useFeatureFlag, useOpenFeatureClient };
1123
+ export { ClientProviderEvents as AllProviderEvents, AnyProviderEvent, BaseHook, BeforeHookContext, Client, ClientMetadata, ClientProviderEvents, CommonEventDetails, CommonProvider, ConfigChangeEvent, DefaultLogger, ErrorCode, ErrorEvent, EvaluationContext, EvaluationContextValue, EvaluationDetails, EvaluationLifeCycle, EventContext, EventDetails, EventHandler, EventMetadata, Eventing, Features, FlagEvaluationOptions, FlagMetadata, FlagNotFoundError, FlagValue, FlagValueType, GeneralError, GenericEventEmitter, Hook, HookContext, HookHints, InMemoryProvider, InvalidContextError, JsonArray, JsonObject, JsonValue, LOG_LEVELS, Logger, ManageContext, ManageLogger, Metadata, NOOP_PROVIDER, OpenFeature, OpenFeatureAPI, OpenFeatureClient, OpenFeatureCommonAPI, OpenFeatureError, OpenFeatureEventEmitter, OpenFeatureProvider, Paradigm, ParseError, PrimitiveValue, Provider, ProviderEmittableEvents, ClientProviderEvents as ProviderEvents, ProviderMetadata, ProviderNotReadyError, ProviderStatus, ReadyEvent, ResolutionDetails, ResolutionReason, SafeLogger, ServerProviderEvents, StaleEvent, StandardResolutionReasons, TargetingKeyMissingError, TypeMismatchError, isObject, isString, objectOrUndefined, statusMatchesEvent, stringOrUndefined, useBooleanFlagDetails, useBooleanFlagValue, useNumberFlagDetails, useNumberFlagValue, useObjectFlagDetails, useObjectFlagValue, useOpenFeatureClient, useStringFlagDetails, useStringFlagValue };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfeature/react-sdk",
3
- "version": "0.0.6-experimental",
3
+ "version": "0.1.0-experimental",
4
4
  "description": "OpenFeature React SDK",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "files": [