Last active
March 28, 2020 15:15
-
-
Save reecelucas/a71b0cc0ebeee6da620cffc352eee1dc to your computer and use it in GitHub Desktop.
Revisions
-
reecelucas revised this gist
Mar 28, 2020 . 1 changed file with 18 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,17 +6,30 @@ const app = express(); const { isFeatureEnabled, getFeatureConfig } = getFeatureUtils({ environment: "development", cookieName: "featureOverrides", }); const ensureFeatureUtils = (req, _res, next) => { if (!req.cookies) { throw new Error( "Server configuration error: ensureFeatureUtils middleware requires cookie-parser middleware upstream" ); } const { featureOverrides } = req.cookies; req.isFeatureEnabled = (featureName) => isFeatureEnabled(featureName, featureOverrides); req.getFeatureConfig = () => getFeatureConfig(featureOverrides); next(); }; app.use(cookieParser()); app.use(ensureFeatureUtils); app.get("/", (req, res) => { console.log(req.getFeatureConfig()); // { FEATURE_A: true, FEATURE_B: false } if (req.isFeatureEnabled("FEATURE_A")) { res.send("FEATURE_A is enabled"); } else { res.send("FEATURE_A is NOT enabled"); -
reecelucas revised this gist
Mar 27, 2020 . 2 changed files with 3 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -42,7 +42,7 @@ export const getFeatureUtils = ({ environment, cookieName }) => { const config = getConfig(environment, cookieValue); const value = config[featureName]; if (value === undefined) { throw new Error( `${featureName} is not defined for the ${environment} environment` ); @@ -51,8 +51,7 @@ export const getFeatureUtils = ({ environment, cookieName }) => { return value; }; // `values` should be an object. E.g. setFeatureOverrides({ FEATURE_A: false }) const setFeatureOverrides = values => { Cookies.set(cookieName, values); }; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -12,7 +12,7 @@ const { console.log(isFeatureEnabled("FEATURE_B")); // false console.log(getFeatureConfig()); // { FEATURE_A: true, FEATURE_B: false } setFeatureOverrides({ FEATURE_B: true }); // After refreshing page... console.log(isFeatureEnabled("FEATURE_B")); // true -
reecelucas revised this gist
Mar 27, 2020 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -59,7 +59,7 @@ export const getFeatureUtils = ({ environment, cookieName }) => { const getFeatureConfig = cookieString => { const cookieValue = cookieString || cookieValueFromDocument; return getConfig(environment, cookieValue); }; return { isFeatureEnabled, setFeatureOverrides, getFeatureConfig }; -
reecelucas revised this gist
Mar 26, 2020 . 1 changed file with 6 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -10,19 +10,19 @@ const getDefaultConfigForEnv = environment => {} ); const getConfigOverridesFromCookie = cookieString => { try { return cookieString ? JSON.parse(cookieString) : {}; } catch (error) { throw new Error( "Could not determine feature config overrides: error parsing cookie value" ); } }; const getConfig = (environment, cookieString) => { const defaultConfig = getDefaultConfigForEnv(environment); const overrides = getConfigOverridesFromCookie(cookieString); return { ...defaultConfig, @@ -39,7 +39,7 @@ export const getFeatureUtils = ({ environment, cookieName }) => { // be accessed on the `request` object. On the client we retrieve the cookie value from // the document. const cookieValue = cookieString || cookieValueFromDocument; const config = getConfig(environment, cookieValue); const value = config[featureName]; if (!value) { @@ -62,5 +62,5 @@ export const getFeatureUtils = ({ environment, cookieName }) => { return getConfig(environment, cookieString); }; return { isFeatureEnabled, setFeatureOverrides, getFeatureConfig }; }; -
reecelucas created this gist
Mar 26, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,19 @@ export default { FEATURE_A: { name: 'FEATURE_A', description: 'Human readable description of feature A', enabled: { development: true, production: false } }, FEATURE_B: { name: 'FEATURE_B', description: 'Human readable description of feature B', enabled: { development: false, production: true } } }; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,66 @@ import config from "./featureConfig"; import Cookies from "js-cookie"; const getDefaultConfigForEnv = environment => Object.entries(config).reduce( (obj, [key, value]) => ({ ...obj, [key]: value.enabled[environment] }), {} ); const getConfigOverridesFromCookie = cookieValue => { try { return cookieValue ? JSON.parse(cookieValue) : {}; } catch (error) { throw new Error( "Could not determine feature config overrides: error parsing cookie value" ); } }; const getConfig = (environment, cookieValue) => { const defaultConfig = getDefaultConfigForEnv(environment); const overrides = getConfigOverridesFromCookie(cookieValue); return { ...defaultConfig, ...overrides }; }; export const getFeatureUtils = ({ environment, cookieName }) => { const cookieValueFromDocument = Cookies.get(cookieName); const isFeatureEnabled = (featureName, cookieString) => { // If `cookieString` is provided we use this to determine feature overrides. // This is useful when using `isFeatureEnabled` on the server, where `cookieName` can // be accessed on the `request` object. On the client we retrieve the cookie value from // the document. const cookieValue = cookieString || cookieValueFromDocument; const config = getConfig(environment, cookieString); const value = config[featureName]; if (!value) { throw new Error( `${featureName} is not defined for the ${environment} environment` ); } return value; }; // `values` should be an object, E.g. { FEATURE_A: false }. // This function could be called on a feature-flipper UI to set features for local development. const setFeatureOverrides = values => { Cookies.set(cookieName, values); }; const getFeatureConfig = cookieString => { const cookieValue = cookieString || cookieValueFromDocument; return getConfig(environment, cookieString); }; return { isFeatureEnabled, getFeatureConfig, setFeatureOverrides }; }; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,19 @@ import { getFeatureUtils } from "./featureFlags"; const { isFeatureEnabled, getFeatureConfig, setFeatureOverrides } = getFeatureUtils({ environment: "development", cookieName: "featureOverrides" }); console.log(isFeatureEnabled("FEATURE_B")); // false console.log(getFeatureConfig()); // { FEATURE_A: true, FEATURE_B: false } setFeatureOverrides("featureOverrides", { FEATURE_B: true }); // After refreshing page... console.log(isFeatureEnabled("FEATURE_B")); // true console.log(getFeatureConfig()); // { FEATURE_A: true, FEATURE_B: true } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,24 @@ import express from "express"; import cookieParser from "cookie-parser"; import { getFeatureUtils } from "./featureFlags"; const app = express(); const { isFeatureEnabled, getFeatureConfig } = getFeatureUtils({ environment: "development", cookieName: "featureOverrides" }); app.use(cookieParser()); app.get("/", (req, res) => { const featureOverrides = req.cookies.featureOverrides; console.log(getFeatureConfig(featureOverrides)); // { FEATURE_A: true, FEATURE_B: false } if (isFeatureEnabled("FEATURE_A", featureOverrides)) { res.send("FEATURE_A is enabled"); } else { res.send("FEATURE_A is NOT enabled"); } });