UNPKG

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