@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 +23 -10
- package/dist/cjs/index.js +43 -15
- package/dist/cjs/index.js.map +2 -2
- package/dist/esm/index.js +43 -15
- package/dist/esm/index.js.map +2 -2
- package/dist/types.d.ts +73 -4
- package/package.json +1 -1
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,
|
|
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
|
|
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
|
-
{
|
|
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
|
|
119
|
+
You can disable this feature in the hook options:
|
|
107
120
|
|
|
108
121
|
```tsx
|
|
109
122
|
function Page() {
|
|
110
|
-
const
|
|
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
|
|
136
|
+
You can disable this feature in the hook options:
|
|
124
137
|
|
|
125
138
|
```tsx
|
|
126
139
|
function Page() {
|
|
127
|
-
const
|
|
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
|
|
167
|
+
const newMessage = useBooleanFlagValue('new-message', false);
|
|
155
168
|
|
|
156
169
|
return (
|
|
157
170
|
<>
|
|
158
|
-
{
|
|
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
|
-
|
|
50
|
-
|
|
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
|
|
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
|
|
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;
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -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": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,
|
|
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": "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",
|
|
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
|
|
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
|
|
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
|
-
|
|
136
|
-
|
|
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
|
package/dist/esm/index.js.map
CHANGED
|
@@ -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,
|
|
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
|
-
*
|
|
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
|
|
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,
|
|
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 };
|