@flopflip/react-redux
Version:
A feature toggle wrapper to use LaunchDarkly with React Redux
427 lines (336 loc) • 12.9 kB
JavaScript
;Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
// src/branch-on-feature-toggle.tsx
var _react = require('react'); var _react2 = _interopRequireDefault(_react);
// src/use-feature-toggle.ts
var _react3 = require('@flopflip/react');
var _reactredux = require('react-redux');
// src/ducks/flags.ts
var _toolkit = require('@reduxjs/toolkit');
// src/constants.ts
var STATE_SLICE = "@flopflip";
// src/ducks/flags.ts
var initialState = { memory: {} };
var flagsSlice = _toolkit.createSlice.call(void 0, {
name: "flags",
initialState,
reducers: {
updateFlags: {
reducer(state, action) {
if (action.payload.id) {
state[action.payload.id] = __spreadValues(__spreadValues({}, state[action.payload.id]), action.payload.flags);
return;
}
for (const adapterId of action.payload.adapterIdentifiers) {
state[adapterId] = __spreadValues(__spreadValues({}, state[adapterId]), action.payload.flags);
}
},
prepare(flagsChange, adapterIdentifiers) {
return {
payload: __spreadProps(__spreadValues({}, flagsChange), { adapterIdentifiers })
};
}
}
}
});
var { updateFlags } = flagsSlice.actions;
var reducer = flagsSlice.reducer;
var createReducer = (preloadedState = initialState) => {
return (state = preloadedState, action) => reducer(state, action);
};
var selectFlags = () => (state) => {
var _a;
return (_a = state[STATE_SLICE].flags) != null ? _a : {};
};
var selectFlag = (flagName, adapterIdentifiers) => (state) => {
var _a;
const allFlags = selectFlags()(state);
let foundFlagVariation = false;
for (const adapterId of adapterIdentifiers) {
const flagValue = (_a = allFlags[adapterId]) == null ? void 0 : _a[flagName];
if (!_react3.isNil.call(void 0, flagValue)) {
foundFlagVariation = flagValue;
}
}
return foundFlagVariation;
};
// src/use-feature-toggle.ts
function useFeatureToggle(flagName, flagVariation = true) {
const adapterContext = _react3.useAdapterContext.call(void 0, );
const allFlags = _reactredux.useSelector.call(void 0, selectFlags());
const isFeatureEnabled = _react3.getIsFeatureEnabled.call(void 0,
allFlags,
adapterContext.adapterEffectIdentifiers,
flagName,
flagVariation
);
_react.useDebugValue.call(void 0, {
flagName,
flagVariation,
isEnabled: isFeatureEnabled
});
return isFeatureEnabled;
}
// src/branch-on-feature-toggle.tsx
function branchOnFeatureToggle({ flag: flagName, variation: flagVariation }, UntoggledComponent) {
return (ToggledComponent) => {
function WrappedToggledComponent(ownProps) {
const isFeatureEnabled = useFeatureToggle(flagName, flagVariation);
if (isFeatureEnabled) {
return /* @__PURE__ */ _react2.default.createElement(ToggledComponent, __spreadValues({}, ownProps));
}
if (UntoggledComponent) {
return /* @__PURE__ */ _react2.default.createElement(UntoggledComponent, __spreadValues({}, ownProps));
}
return null;
}
return WrappedToggledComponent;
};
}
// src/configure.tsx
// src/use-update-flags.ts
var useUpdateFlags = ({
adapterIdentifiers
}) => {
const dispatch = _reactredux.useDispatch.call(void 0, );
return _react.useCallback.call(void 0,
(flagsChange) => dispatch(updateFlags(flagsChange, adapterIdentifiers)),
[dispatch, adapterIdentifiers]
);
};
// src/use-update-status.ts
var _types = require('@flopflip/types');
// src/ducks/status.ts
var initialState2 = {};
var statusSlice = _toolkit.createSlice.call(void 0, {
name: "status",
initialState: initialState2,
reducers: {
updateStatus: {
reducer(state, action) {
if (action.payload.id) {
state[action.payload.id] = __spreadValues(__spreadValues({}, state[action.payload.id]), action.payload.status);
return;
}
for (const adapterInterfaceIdentifier of action.payload.adapterIdentifiers) {
state[adapterInterfaceIdentifier] = __spreadValues(__spreadValues({}, state[adapterInterfaceIdentifier]), action.payload.status);
}
},
prepare(statusChange, adapterIdentifiers) {
return {
payload: __spreadProps(__spreadValues({}, statusChange), { adapterIdentifiers })
};
}
}
}
});
var { updateStatus } = statusSlice.actions;
var reducer2 = statusSlice.reducer;
var selectStatus = ({ adapterIdentifiers } = {}) => (state) => {
const { status } = state[STATE_SLICE];
return _react3.selectAdapterConfigurationStatus.call(void 0, status, adapterIdentifiers);
};
// src/use-update-status.ts
var useUpdateStatus = () => {
const dispatch = _reactredux.useDispatch.call(void 0, );
return _react.useCallback.call(void 0,
(statusChange) => dispatch(updateStatus(statusChange, Object.keys(_types.adapterIdentifiers))),
[dispatch]
);
};
// src/configure.tsx
function Configure({
adapter,
adapterArgs,
children,
defaultFlags = {},
shouldDeferAdapterConfiguration = false
}) {
const adapterIdentifiers = [adapter.id];
const handleUpdateFlags = useUpdateFlags({ adapterIdentifiers });
const handleUpdateStatus = useUpdateStatus();
_react3.useAdapterSubscription.call(void 0, adapter);
return /* @__PURE__ */ _react2.default.createElement(
_react3.ConfigureAdapter,
{
adapter,
adapterArgs,
defaultFlags,
shouldDeferAdapterConfiguration,
onFlagsStateChange: handleUpdateFlags,
onStatusStateChange: handleUpdateStatus
},
children
);
}
Configure.displayName = "ConfigureFlopflip";
// src/ducks/index.ts
var flopflipReducer = _toolkit.combineReducers.call(void 0, {
flags: reducer,
status: reducer2
});
var createFlopflipReducer = (preloadedState = { memory: {} }) => _toolkit.combineReducers.call(void 0, {
flags: createReducer(preloadedState),
status: reducer2
});
// src/enhancer.ts
var configureAdapter = _toolkit.createAction.call(void 0, "flopflip/configureAdapter");
function createFlopFlipEnhancer(adapter, adapterArgs) {
return (next) => (...args) => {
const store = next(...args);
store.dispatch(configureAdapter({ adapter, adapterArgs }));
adapter.configure(adapterArgs, {
onFlagsStateChange: (flagsChange) => {
store.dispatch(updateFlags(flagsChange, [adapter.id]));
},
onStatusStateChange: (statusChange) => {
store.dispatch(
updateStatus(statusChange, Object.keys(_types.adapterIdentifiers))
);
}
});
return store;
};
}
// src/inject-feature-toggle.tsx
// src/use-flag-variations.ts
function useFlagVariations(flagNames) {
const adapterContext = _react3.useAdapterContext.call(void 0, );
const allFlags = _reactredux.useSelector.call(void 0, selectFlags());
const flagVariations = flagNames.map(
(requestedVariation) => _react3.getFlagVariation.call(void 0,
allFlags,
adapterContext.adapterEffectIdentifiers,
requestedVariation
)
);
return flagVariations;
}
// src/inject-feature-toggle.tsx
var injectFeatureToggle = (flagName, propKey = _react3.DEFAULT_FLAG_PROP_KEY) => (Component) => {
function WrappedComponent(ownProps) {
const [flagVariation] = useFlagVariations([flagName]);
const props = __spreadProps(__spreadValues({}, ownProps), {
[propKey]: flagVariation
});
return /* @__PURE__ */ _react2.default.createElement(Component, __spreadValues({}, props));
}
_react3.setDisplayName.call(void 0, _react3.wrapDisplayName.call(void 0, WrappedComponent, "injectFeatureToggle"));
return WrappedComponent;
};
// src/inject-feature-toggles.tsx
var injectFeatureToggles = (flagNames, propKey = _react3.DEFAULT_FLAGS_PROP_KEY) => (Component) => {
function WrappedComponent(ownProps) {
const flagVariations = useFlagVariations(flagNames);
const flags = Object.fromEntries(
flagNames.map((flagName, indexOfFlagName) => [
flagName,
flagVariations[indexOfFlagName]
])
);
const props = __spreadProps(__spreadValues({}, ownProps), {
[propKey]: flags
});
return /* @__PURE__ */ _react2.default.createElement(Component, __spreadValues({}, props));
}
_react3.setDisplayName.call(void 0, _react3.wrapDisplayName.call(void 0, WrappedComponent, "injectFeatureToggles"));
return WrappedComponent;
};
// src/reconfigure.ts
// src/toggle-feature.tsx
function ToggleFeature(_a) {
var _b = _a, {
flag,
variation
} = _b, remainingProps = __objRest(_b, [
"flag",
"variation"
]);
const isFeatureEnabled = useFeatureToggle(flag, variation);
return /* @__PURE__ */ _react2.default.createElement(
_react3.ToggleFeature,
__spreadProps(__spreadValues({
flag,
variation
}, remainingProps), {
isFeatureEnabled
})
);
}
ToggleFeature.displayName = "ToggleFeature";
// src/use-adapter-reconfiguration.ts
// src/use-adapter-status.ts
function useAdapterStatus({ adapterIdentifiers } = {}) {
const adapterStatus = _reactredux.useSelector.call(void 0, selectStatus({ adapterIdentifiers }));
_react.useDebugValue.call(void 0, { adapterStatus });
return adapterStatus;
}
// src/use-all-feature-toggles.ts
function useAllFeatureToggles() {
const adapterContext = _react3.useAdapterContext.call(void 0, );
const allFlags = _reactredux.useSelector.call(void 0, selectFlags());
const reversedAdapterEffectIdentifiers = [
...adapterContext.adapterEffectIdentifiers
].reverse();
return reversedAdapterEffectIdentifiers.reduce(
(_allFlags, adapterIdentifier) => __spreadValues(__spreadValues({}, _allFlags), allFlags[adapterIdentifier]),
{}
);
}
// src/use-feature-toggles.ts
function useFeatureToggles(flags) {
const allFlags = _reactredux.useSelector.call(void 0, selectFlags());
const adapterContext = _react3.useAdapterContext.call(void 0, );
const requestedFlags = Object.entries(flags).reduce(
(previousFlags, [flagName, flagVariation]) => {
const isFeatureEnabled = _react3.getIsFeatureEnabled.call(void 0,
allFlags,
adapterContext.adapterEffectIdentifiers,
flagName,
flagVariation
);
previousFlags.push(isFeatureEnabled);
return previousFlags;
},
[]
);
return requestedFlags;
}
// src/use-flag-variation.ts
function useFlagVariation(flagName) {
const [flagVariation] = useFlagVariations([flagName]);
return flagVariation;
}
// src/index.ts
var version = "__@FLOPFLIP/VERSION_OF_RELEASE__";
exports.ConfigureFlopFlip = Configure; exports.FLOPFLIP_STATE_SLICE = STATE_SLICE; exports.ReconfigureFlopFlip = _react3.ReconfigureAdapter; exports.ToggleFeature = ToggleFeature; exports.branchOnFeatureToggle = branchOnFeatureToggle; exports.createFlopFlipEnhancer = createFlopFlipEnhancer; exports.createFlopflipReducer = createFlopflipReducer; exports.flopflipReducer = flopflipReducer; exports.injectFeatureToggle = injectFeatureToggle; exports.injectFeatureToggles = injectFeatureToggles; exports.selectFeatureFlag = selectFlag; exports.selectFeatureFlags = selectFlags; exports.useAdapterReconfiguration = _react3.useAdapterReconfiguration; exports.useAdapterStatus = useAdapterStatus; exports.useAllFeatureToggles = useAllFeatureToggles; exports.useFeatureToggle = useFeatureToggle; exports.useFeatureToggles = useFeatureToggles; exports.useFlagVariation = useFlagVariation; exports.useFlagVariations = useFlagVariations; exports.version = version;
//# sourceMappingURL=index.cjs.map