UNPKG

11.8 kBJavaScriptView Raw
1import { combineReducers } from 'redux';
2import _createForOfIteratorHelper from '@babel/runtime/helpers/esm/createForOfIteratorHelper';
3import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
4import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
5import { isNil, selectAdapterConfigurationStatus, useAdapterContext, getIsFeatureEnabled, getFlagVariation, useAdapterSubscription, ConfigureAdapter, ToggleFeature as ToggleFeature$1, setDisplayName, wrapDisplayName, DEFAULT_FLAG_PROP_KEY, DEFAULT_FLAGS_PROP_KEY } from '@flopflip/react';
6export { ReconfigureAdapter as ReconfigureFlopFlip, useAdapterReconfiguration } from '@flopflip/react';
7import { AdapterSubscriptionStatus, AdapterConfigurationStatus } from '@flopflip/types';
8import React, { useDebugValue, useCallback } from 'react';
9import { useSelector, useDispatch } from 'react-redux';
10import _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray';
11import _slicedToArray from '@babel/runtime/helpers/esm/slicedToArray';
12
13var STATE_SLICE = '@flopflip';
14
15// Actions
16var UPDATE_FLAGS = '@flopflip/flags/update';
17var initialState$1 = {
18 memory: {}
19}; // Reducer
20
21var reducer$1 = function reducer() {
22 var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState$1;
23 var action = arguments.length > 1 ? arguments[1] : undefined;
24
25 switch (action.type) {
26 case UPDATE_FLAGS:
27 {
28 if (action.payload.id) {
29 return _objectSpread(_objectSpread({}, state), {}, _defineProperty({}, action.payload.id, _objectSpread(_objectSpread({}, state === null || state === void 0 ? void 0 : state[action.payload.id]), action.payload.flags)));
30 }
31
32 return _objectSpread(_objectSpread({}, state), Object.fromEntries(action.payload.adapterIdentifiers.map(function (adapterInterfaceIdentifier) {
33 return [adapterInterfaceIdentifier, _objectSpread(_objectSpread({}, state === null || state === void 0 ? void 0 : state[adapterInterfaceIdentifier]), action.payload.flags)];
34 })));
35 }
36
37 default:
38 return state;
39 }
40};
41var createReducer = function createReducer() {
42 var preloadedState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState$1;
43 return function () {
44 var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : preloadedState;
45 var action = arguments.length > 1 ? arguments[1] : undefined;
46 return reducer$1(state, action);
47 };
48}; // Action Creators
49
50var updateFlags = function updateFlags(flagsChange, adapterIdentifiers) {
51 return {
52 type: UPDATE_FLAGS,
53 payload: _objectSpread(_objectSpread({}, flagsChange), {}, {
54 adapterIdentifiers: adapterIdentifiers
55 })
56 };
57}; // Selectors
58
59var selectFlags = function selectFlags() {
60 return function (state) {
61 var _state$STATE_SLICE$fl;
62
63 return (_state$STATE_SLICE$fl = state[STATE_SLICE].flags) !== null && _state$STATE_SLICE$fl !== void 0 ? _state$STATE_SLICE$fl : {};
64 };
65};
66var selectFlag = function selectFlag(flagName, adapterIdentifiers) {
67 return function (state) {
68 var allFlags = selectFlags()(state);
69 var foundFlagVariation = false;
70
71 var _iterator = _createForOfIteratorHelper(adapterIdentifiers),
72 _step;
73
74 try {
75 for (_iterator.s(); !(_step = _iterator.n()).done;) {
76 var _allFlags$adapterInte;
77
78 var adapterInterfaceIdentifier = _step.value;
79 var flagValue = (_allFlags$adapterInte = allFlags[adapterInterfaceIdentifier]) === null || _allFlags$adapterInte === void 0 ? void 0 : _allFlags$adapterInte[flagName];
80
81 if (!isNil(flagValue)) {
82 foundFlagVariation = flagValue;
83 }
84 }
85 } catch (err) {
86 _iterator.e(err);
87 } finally {
88 _iterator.f();
89 }
90
91 return foundFlagVariation;
92 };
93};
94
95// Actions
96var UPDATE_STATUS = '@flopflip/status/update';
97var initialState = {
98 subscriptionStatus: AdapterSubscriptionStatus.Subscribed,
99 configurationStatus: AdapterConfigurationStatus.Unconfigured
100}; // Reducer
101
102var reducer = function reducer() {
103 var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : initialState;
104 var action = arguments.length > 1 ? arguments[1] : undefined;
105
106 switch (action.type) {
107 case UPDATE_STATUS:
108 return _objectSpread(_objectSpread({}, state), action.payload.status);
109
110 default:
111 return state;
112 }
113};
114
115var updateStatus = function updateStatus(statusChange) {
116 return {
117 type: UPDATE_STATUS,
118 payload: statusChange
119 };
120}; // Selectors
121
122var selectStatus = function selectStatus(state) {
123 var status = state[STATE_SLICE].status;
124 return selectAdapterConfigurationStatus(status === null || status === void 0 ? void 0 : status.configurationStatus);
125};
126
127var flopflipReducer = combineReducers({
128 flags: reducer$1,
129 status: reducer
130});
131var createFlopflipReducer = function createFlopflipReducer() {
132 var preloadedState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
133 memory: {}
134 };
135 return combineReducers({
136 flags: createReducer(preloadedState),
137 status: reducer
138 });
139};
140
141function createFlopFlipEnhancer(adapter, adapterArgs) {
142 return function (next) {
143 return function () {
144 var store = next.apply(void 0, arguments); // eslint-disable-next-line @typescript-eslint/no-floating-promises
145
146 adapter.configure(adapterArgs, {
147 // NOTE: This is like `bindActionCreators` but the bound action
148 // creators are renamed to fit the adapter API and conventions.
149 onFlagsStateChange: function onFlagsStateChange(flagsChange) {
150 store.dispatch(updateFlags(flagsChange, [adapter.id]));
151 },
152 onStatusStateChange: function onStatusStateChange(statusChange) {
153 store.dispatch(updateStatus(statusChange));
154 }
155 });
156 return store;
157 };
158 };
159}
160
161function useAdapterStatus() {
162 var adapterStatus = useSelector(selectStatus);
163 useDebugValue({
164 adapterStatus: adapterStatus
165 });
166 return adapterStatus;
167}
168
169function useFeatureToggle(flagName) {
170 var flagVariation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
171 var adapterContext = useAdapterContext();
172 var allFlags = useSelector(selectFlags());
173 var isFeatureEnabled = getIsFeatureEnabled(allFlags, adapterContext.adapterEffectIdentifiers, flagName, flagVariation);
174 useDebugValue({
175 flagName: flagName,
176 flagVariation: flagVariation,
177 isEnabled: isFeatureEnabled
178 });
179 return isFeatureEnabled;
180}
181
182function useFeatureToggles(flags) {
183 var allFlags = useSelector(selectFlags());
184 var adapterContext = useAdapterContext();
185 var requestedFlags = Object.entries(flags).reduce(function (previousFlags, _ref) {
186 var _ref2 = _slicedToArray(_ref, 2),
187 flagName = _ref2[0],
188 flagVariation = _ref2[1];
189
190 var isFeatureEnabled = getIsFeatureEnabled(allFlags, adapterContext.adapterEffectIdentifiers, flagName, flagVariation);
191 return [].concat(_toConsumableArray(previousFlags), [isFeatureEnabled]);
192 }, []);
193 return requestedFlags;
194}
195
196function useFlagVariations(flagNames) {
197 var adapterContext = useAdapterContext();
198 var allFlags = useSelector(selectFlags());
199 var flagVariations = flagNames.map(function (requestedVariation) {
200 return getFlagVariation(allFlags, adapterContext.adapterEffectIdentifiers, requestedVariation);
201 });
202 return flagVariations;
203}
204
205function useFlagVariation(flagName) {
206 var _useFlagVariations = useFlagVariations([flagName]),
207 _useFlagVariations2 = _slicedToArray(_useFlagVariations, 1),
208 flagVariation = _useFlagVariations2[0];
209
210 return flagVariation;
211}
212
213var useUpdateFlags = function useUpdateFlags(_ref) {
214 var adapterIdentifiers = _ref.adapterIdentifiers;
215 var dispatch = useDispatch();
216 return useCallback(function (flagsChange) {
217 return dispatch(updateFlags(flagsChange, adapterIdentifiers));
218 }, [dispatch, adapterIdentifiers]);
219};
220
221var useUpdateStatus = function useUpdateStatus() {
222 var dispatch = useDispatch();
223 return useCallback(function (statusChange) {
224 return dispatch(updateStatus(statusChange));
225 }, [dispatch]);
226};
227
228var defaultProps = {
229 defaultFlags: {},
230 shouldDeferAdapterConfiguration: false
231};
232
233var Configure = function Configure(props) {
234 var adapterIdentifiers = [props.adapter.id];
235 var handleUpdateFlags = useUpdateFlags({
236 adapterIdentifiers: adapterIdentifiers
237 });
238 var handleUpdateStatus = useUpdateStatus();
239 useAdapterSubscription(props.adapter);
240 return /*#__PURE__*/React.createElement(ConfigureAdapter, {
241 adapter: props.adapter,
242 adapterArgs: props.adapterArgs,
243 defaultFlags: props.defaultFlags,
244 shouldDeferAdapterConfiguration: props.shouldDeferAdapterConfiguration,
245 onFlagsStateChange: handleUpdateFlags,
246 onStatusStateChange: handleUpdateStatus
247 }, props.children);
248};
249
250Configure.displayName = 'ConfigureFlopflip';
251Configure.defaultProps = defaultProps;
252
253var ToggleFeature = function ToggleFeature(props) {
254 var isFeatureEnabled = useFeatureToggle(props.flag, props.variation);
255 return /*#__PURE__*/React.createElement(ToggleFeature$1, Object.assign({}, props, {
256 isFeatureEnabled: isFeatureEnabled
257 }));
258};
259
260ToggleFeature.displayName = 'ToggleFeature';
261
262function branchOnFeatureToggle(_ref, UntoggledComponent) {
263 var flagName = _ref.flag,
264 flagVariation = _ref.variation;
265 return function (ToggledComponent) {
266 var WrappedToggledComponent = function WrappedToggledComponent(ownProps) {
267 var isFeatureEnabled = useFeatureToggle(flagName, flagVariation);
268 if (isFeatureEnabled) return /*#__PURE__*/React.createElement(ToggledComponent, ownProps);
269 if (UntoggledComponent) return /*#__PURE__*/React.createElement(UntoggledComponent, ownProps);
270 return null;
271 };
272
273 return WrappedToggledComponent;
274 };
275}
276
277var injectFeatureToggle = (function (flagName) {
278 var propKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_FLAG_PROP_KEY;
279 return function (Component) {
280 var WrappedComponent = function WrappedComponent(ownProps) {
281 var _useFlagVariations = useFlagVariations([flagName]),
282 _useFlagVariations2 = _slicedToArray(_useFlagVariations, 1),
283 flagVariation = _useFlagVariations2[0];
284
285 var props = _objectSpread(_objectSpread({}, ownProps), {}, _defineProperty({}, propKey, flagVariation));
286
287 return /*#__PURE__*/React.createElement(Component, props);
288 };
289
290 setDisplayName(wrapDisplayName(WrappedComponent, 'injectFeatureToggle'));
291 return WrappedComponent;
292 };
293});
294
295var injectFeatureToggles = (function (flagNames) {
296 var propKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_FLAGS_PROP_KEY;
297 return function (Component) {
298 var WrappedComponent = function WrappedComponent(ownProps) {
299 var flagVariations = useFlagVariations(flagNames);
300 var flags = Object.fromEntries(flagNames.map(function (flagName, indexOfFlagName) {
301 return [flagName, flagVariations[indexOfFlagName]];
302 }));
303
304 var props = _objectSpread(_objectSpread({}, ownProps), {}, _defineProperty({}, propKey, flags));
305
306 return /*#__PURE__*/React.createElement(Component, props);
307 };
308
309 setDisplayName(wrapDisplayName(WrappedComponent, 'injectFeatureToggles'));
310 return WrappedComponent;
311 };
312});
313
314var version = '12.1.14';
315
316export { Configure as ConfigureFlopFlip, STATE_SLICE as FLOPFLIP_STATE_SLICE, ToggleFeature, UPDATE_FLAGS, UPDATE_STATUS, branchOnFeatureToggle, createFlopFlipEnhancer, createFlopflipReducer, flopflipReducer, injectFeatureToggle, injectFeatureToggles, selectFlag as selectFeatureFlag, selectFlags as selectFeatureFlags, useAdapterStatus, useFeatureToggle, useFeatureToggles, useFlagVariation, useFlagVariations, version };