From 9b9d6aff7817784148d7360974bfefa87a55b2d1 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 8 Aug 2022 18:38:37 +0200 Subject: [PATCH] build: add env utils (#4304) * build: add env utils * test: env utils --- src/components/AmplitudeAnalytics/index.ts | 11 +++--- src/components/Menu/index.tsx | 3 +- src/serviceWorkerRegistration.ts | 4 +- src/state/index.ts | 3 +- src/utils/env.test.ts | 43 ++++++++++++++++++++++ src/utils/env.ts | 15 ++++++++ 6 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 src/utils/env.test.ts create mode 100644 src/utils/env.ts diff --git a/src/components/AmplitudeAnalytics/index.ts b/src/components/AmplitudeAnalytics/index.ts index 5cfef1ad96..d1a19a61de 100644 --- a/src/components/AmplitudeAnalytics/index.ts +++ b/src/components/AmplitudeAnalytics/index.ts @@ -1,4 +1,5 @@ import { Identify, identify, init, track } from '@amplitude/analytics-browser' +import { isDevelopmentEnv } from 'utils/env' /** * Initializes Amplitude with API key for project. @@ -6,8 +7,8 @@ import { Identify, identify, init, track } from '@amplitude/analytics-browser' * Uniswap has two Amplitude projects: test and production. You must be a * member of the organization on Amplitude to view details. */ -export function initializeAnalytics(isDevEnvironment = process.env.NODE_ENV === 'development') { - if (isDevEnvironment) return +export function initializeAnalytics() { + if (isDevelopmentEnv()) return const API_KEY = process.env.REACT_APP_AMPLITUDE_KEY if (typeof API_KEY === 'undefined') { @@ -36,7 +37,7 @@ export function initializeAnalytics(isDevEnvironment = process.env.NODE_ENV === /** Sends an event to Amplitude. */ export function sendAnalyticsEvent(eventName: string, eventProperties?: Record) { - if (process.env.NODE_ENV === 'development') { + if (isDevelopmentEnv()) { console.log(`[amplitude(${eventName})]: ${JSON.stringify(eventProperties)}`) return } @@ -54,14 +55,12 @@ type Value = string | number | boolean | string[] | number[] * for details. */ class UserModel { - constructor(private isDevEnvironment = process.env.NODE_ENV === 'development') {} - private log(method: string, ...parameters: unknown[]) { console.debug(`[amplitude(Identify)]: ${method}(${parameters})`) } private call(mutate: (event: Identify) => Identify) { - if (this.isDevEnvironment) { + if (isDevelopmentEnv()) { const log = (_: Identify, method: string) => this.log.bind(this, method) mutate(new Proxy(new Identify(), { get: log })) return diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx index bdf9138d50..d6f80254c0 100644 --- a/src/components/Menu/index.tsx +++ b/src/components/Menu/index.tsx @@ -24,6 +24,7 @@ import { import { Link } from 'react-router-dom' import { useDarkModeManager } from 'state/user/hooks' import styled, { css } from 'styled-components/macro' +import { isDevelopmentEnv, isStagingEnv } from 'utils/env' import { ReactComponent as MenuIcon } from '../../assets/images/menu.svg' import { useOnClickOutside } from '../../hooks/useOnClickOutside' @@ -301,7 +302,7 @@ export default function Menu() { Claim UNI )} - {['development', 'test'].includes(process.env.NODE_ENV) && ( + {(isDevelopmentEnv() || isStagingEnv()) && ( Feature Flags )} diff --git a/src/serviceWorkerRegistration.ts b/src/serviceWorkerRegistration.ts index 2fc1a43beb..148c172620 100644 --- a/src/serviceWorkerRegistration.ts +++ b/src/serviceWorkerRegistration.ts @@ -1,6 +1,8 @@ // This optional code is used to register a service worker. // register() is not called by default. +import { isProductionEnv, isStagingEnv } from 'utils/env' + // This lets the app load faster on subsequent visits in production, and gives // it offline capabilities. However, it also means that developers (and users) // will only see deployed updates on subsequent visits to a page, after all the @@ -93,7 +95,7 @@ function checkValidServiceWorker(swUrl: string, config?: Config) { } export function register(config?: Config) { - if (['production', 'staging'].includes(process.env.NODE_ENV) && 'serviceWorker' in navigator) { + if ((isProductionEnv() || isStagingEnv()) && 'serviceWorker' in navigator) { // The URL constructor is available in all browsers that support SW. const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href) if (publicUrl.origin !== window.location.origin) { diff --git a/src/state/index.ts b/src/state/index.ts index af3b5420da..76c4b7fed4 100644 --- a/src/state/index.ts +++ b/src/state/index.ts @@ -2,6 +2,7 @@ import { configureStore } from '@reduxjs/toolkit' import { setupListeners } from '@reduxjs/toolkit/query/react' import multicall from 'lib/state/multicall' import { load, save } from 'redux-localstorage-simple' +import { isTestEnv } from 'utils/env' import application from './application/reducer' import burn from './burn/reducer' @@ -44,7 +45,7 @@ const store = configureStore({ .concat(dataApi.middleware) .concat(routingApi.middleware) .concat(save({ states: PERSISTED_KEYS, debounce: 1000 })), - preloadedState: load({ states: PERSISTED_KEYS, disableWarnings: process.env.NODE_ENV === 'test' }), + preloadedState: load({ states: PERSISTED_KEYS, disableWarnings: isTestEnv() }), }) store.dispatch(updateVersion()) diff --git a/src/utils/env.test.ts b/src/utils/env.test.ts new file mode 100644 index 0000000000..2ce18110ba --- /dev/null +++ b/src/utils/env.test.ts @@ -0,0 +1,43 @@ +import { isDevelopmentEnv, isProductionEnv, isStagingEnv, isTestEnv } from './env' + +describe('env', () => { + const ENV = process.env + afterEach(() => { + process.env = ENV + }) + + function setEnv(env: Record) { + process.env = { + PUBLIC_URL: 'http://example.com', + NODE_ENV: 'development', + ...env, + } + } + + it('isDevelopmentEnv is true if NODE_ENV=development', () => { + setEnv({ NODE_ENV: 'development' }) + expect(isDevelopmentEnv()).toBe(true) + }) + + it('isTestEnv is true if NODE_ENV=test', () => { + setEnv({ NODE_ENV: 'test' }) + expect(isTestEnv()).toBe(true) + }) + + it('isStagingEnv is true REACT_APP_STAGING=1', () => { + setEnv({ REACT_APP_STAGING: 1 }) + expect(isStagingEnv()).toBe(true) + }) + + describe('isProductionEnv', () => { + it('is true if NODE_ENV=production', () => { + setEnv({ NODE_ENV: 'production' }) + expect(isProductionEnv()).toBe(true) + }) + + it('is false if NODE_ENV=production and REACT_APP_STAGING=1', () => { + setEnv({ NODE_ENV: 'production', REACT_APP_STAGING: 1 }) + expect(isProductionEnv()).toBe(false) + }) + }) +}) diff --git a/src/utils/env.ts b/src/utils/env.ts new file mode 100644 index 0000000000..d130b846dd --- /dev/null +++ b/src/utils/env.ts @@ -0,0 +1,15 @@ +export function isDevelopmentEnv(): boolean { + return process.env.NODE_ENV === 'development' +} + +export function isTestEnv(): boolean { + return process.env.NODE_ENV === 'test' +} + +export function isStagingEnv(): boolean { + return Boolean(process.env.REACT_APP_STAGING) +} + +export function isProductionEnv(): boolean { + return process.env.NODE_ENV === 'production' && !isStagingEnv() +}