diff options
| -rw-r--r-- | packages/instant/.dogfood.discharge.json | 4 | ||||
| -rw-r--r-- | packages/instant/.staging.discharge.json | 4 | ||||
| -rw-r--r-- | packages/instant/package.json | 3 | ||||
| -rw-r--r-- | packages/instant/src/components/zero_ex_instant_provider.tsx | 2 | ||||
| -rw-r--r-- | packages/instant/src/constants.ts | 17 | ||||
| -rw-r--r-- | packages/instant/src/redux/async_data.ts | 4 | ||||
| -rw-r--r-- | packages/instant/src/util/asset.ts | 17 | ||||
| -rw-r--r-- | packages/instant/src/util/buy_quote_updater.ts | 31 | ||||
| -rw-r--r-- | packages/instant/src/util/error_reporter.ts | 62 | ||||
| -rw-r--r-- | packages/instant/src/util/gas_price_estimator.ts | 5 | ||||
| -rw-r--r-- | packages/instant/src/util/heap.ts | 3 | ||||
| -rw-r--r-- | packages/instant/test/util/asset.test.ts | 33 | ||||
| -rw-r--r-- | packages/instant/webpack.config.js | 116 | ||||
| -rw-r--r-- | packages/monorepo-scripts/src/prepublish_checks.ts | 6 | ||||
| -rw-r--r-- | yarn.lock | 15 | 
15 files changed, 276 insertions, 46 deletions
diff --git a/packages/instant/.dogfood.discharge.json b/packages/instant/.dogfood.discharge.json index ca36b3861..cea579c27 100644 --- a/packages/instant/.dogfood.discharge.json +++ b/packages/instant/.dogfood.discharge.json @@ -1,12 +1,12 @@  {      "domain": "0x-instant-dogfood", -    "build_command": "WEBPACK_OUTPUT_PATH=public yarn build:umd:prod", +    "build_command": "WEBPACK_OUTPUT_PATH=public yarn build:umd:prod --env.dogfood",      "upload_directory": "public",      "index_key": "index.html",      "error_key": "index.html",      "trailing_slashes": true,      "cache": 3600, -    "aws_profile": "default", +    "aws_profile": "0xproject",      "aws_region": "us-east-1",      "cdn": false,      "dns_configured": true diff --git a/packages/instant/.staging.discharge.json b/packages/instant/.staging.discharge.json index c917a650b..9e63cb110 100644 --- a/packages/instant/.staging.discharge.json +++ b/packages/instant/.staging.discharge.json @@ -1,12 +1,12 @@  {      "domain": "0x-instant-staging", -    "build_command": "WEBPACK_OUTPUT_PATH=public yarn build:umd:prod", +    "build_command": "WEBPACK_OUTPUT_PATH=public yarn build:umd:prod --env.staging",      "upload_directory": "public",      "index_key": "index.html",      "error_key": "index.html",      "trailing_slashes": true,      "cache": 3600, -    "aws_profile": "default", +    "aws_profile": "0xproject",      "aws_region": "us-east-1",      "cdn": false,      "dns_configured": true diff --git a/packages/instant/package.json b/packages/instant/package.json index d3a85a646..fd2f12857 100644 --- a/packages/instant/package.json +++ b/packages/instant/package.json @@ -63,6 +63,7 @@          "react-redux": "^5.0.7",          "redux": "^4.0.0",          "redux-devtools-extension": "^2.13.5", +        "rollbar": "^2.5.0",          "styled-components": "^4.0.2",          "ts-optchain": "^0.1.1"      }, @@ -87,7 +88,9 @@          "make-promises-safe": "^1.1.0",          "npm-run-all": "^4.1.2",          "nyc": "^11.0.1", +        "rollbar-sourcemap-webpack-plugin": "^2.4.0",          "shx": "^0.2.2", +        "source-map-loader": "^0.2.4",          "svg-react-loader": "^0.4.6",          "ts-jest": "^23.10.3",          "tslint": "5.11.0", diff --git a/packages/instant/src/components/zero_ex_instant_provider.tsx b/packages/instant/src/components/zero_ex_instant_provider.tsx index 9814aabf8..1f53f2d96 100644 --- a/packages/instant/src/components/zero_ex_instant_provider.tsx +++ b/packages/instant/src/components/zero_ex_instant_provider.tsx @@ -15,6 +15,7 @@ import { AccountState, AffiliateInfo, AssetMetaData, Network, OrderSource } from  import { analytics, disableAnalytics } from '../util/analytics';  import { assetUtils } from '../util/asset';  import { errorFlasher } from '../util/error_flasher'; +import { setupRollbar } from '../util/error_reporter';  import { gasPriceEstimator } from '../util/gas_price_estimator';  import { Heartbeater } from '../util/heartbeater';  import { generateAccountHeartbeater, generateBuyQuoteHeartbeater } from '../util/heartbeater_factory'; @@ -86,6 +87,7 @@ export class ZeroExInstantProvider extends React.Component<ZeroExInstantProvider      }      constructor(props: ZeroExInstantProviderProps) {          super(props); +        setupRollbar();          fonts.include();          const initialAppState = ZeroExInstantProvider._mergeDefaultStateWithProps(this.props);          this._store = store.create(initialAppState); diff --git a/packages/instant/src/constants.ts b/packages/instant/src/constants.ts index be6077ca9..677510a8b 100644 --- a/packages/instant/src/constants.ts +++ b/packages/instant/src/constants.ts @@ -20,6 +20,23 @@ export const HEAP_ANALYTICS_ID = process.env.HEAP_ANALYTICS_ID;  export const COINBASE_API_BASE_URL = 'https://api.coinbase.com/v2';  export const PROGRESS_STALL_AT_WIDTH = '95%';  export const PROGRESS_FINISH_ANIMATION_TIME_MS = 200; +export const HOST_DOMAINS = [ +    '0x-instant-staging.s3-website-us-east-1.amazonaws.com', +    '0x-instant-dogfood.s3-website-us-east-1.amazonaws.com', +    'localhost', +    '127.0.0.1', +    '0.0.0.0', +    'unpkg.com', +    'jsdelivr.com', +]; +export const ROLLBAR_CLIENT_TOKEN = process.env.ROLLBAR_CLIENT_TOKEN; +export const INSTANT_ENVIRONMENT = process.env.INSTANT_ENVIRONMENT as +    | 'dogfood' +    | 'staging' +    | 'development' +    | 'production' +    | undefined; +export const ROLLBAR_ENABLED = process.env.ROLLBAR_ENABLED;  export const COINBASE_WALLET_IOS_APP_STORE_URL = 'https://itunes.apple.com/us/app/coinbase-wallet/id1278383455?mt=8';  export const COINBASE_WALLET_ANDROID_APP_STORE_URL = 'https://play.google.com/store/apps/details?id=org.toshi&hl=en';  export const COINBASE_WALLET_SITE_URL = 'https://wallet.coinbase.com/'; diff --git a/packages/instant/src/redux/async_data.ts b/packages/instant/src/redux/async_data.ts index 6feb760e7..5765a7ca4 100644 --- a/packages/instant/src/redux/async_data.ts +++ b/packages/instant/src/redux/async_data.ts @@ -10,6 +10,7 @@ import { assetUtils } from '../util/asset';  import { buyQuoteUpdater } from '../util/buy_quote_updater';  import { coinbaseApi } from '../util/coinbase_api';  import { errorFlasher } from '../util/error_flasher'; +import { errorReporter } from '../util/error_reporter';  import { actions } from './actions';  import { State } from './reducer'; @@ -23,6 +24,7 @@ export const asyncData = {              const errorMessage = 'Error fetching ETH/USD price';              errorFlasher.flashNewErrorMessage(dispatch, errorMessage);              dispatch(actions.updateEthUsdPrice(BIG_NUMBER_ZERO)); +            errorReporter.report(e);          }      },      fetchAvailableAssetDatasAndDispatchToStore: async (state: State, dispatch: Dispatch) => { @@ -37,6 +39,7 @@ export const asyncData = {              errorFlasher.flashNewErrorMessage(dispatch, errorMessage);              // On error, just specify that none are available              dispatch(actions.setAvailableAssets([])); +            errorReporter.report(e);          }      },      fetchAccountInfoAndDispatchToStore: async ( @@ -77,6 +80,7 @@ export const asyncData = {              const ethBalanceInWei = await web3Wrapper.getBalanceInWeiAsync(address);              dispatch(actions.updateAccountEthBalance({ address, ethBalanceInWei }));          } catch (e) { +            errorReporter.report(e);              // leave balance as is              return;          } diff --git a/packages/instant/src/util/asset.ts b/packages/instant/src/util/asset.ts index 40560d3eb..08f3642e3 100644 --- a/packages/instant/src/util/asset.ts +++ b/packages/instant/src/util/asset.ts @@ -1,3 +1,4 @@ +import { AssetBuyerError } from '@0x/asset-buyer';  import { AssetProxyId, ObjectMap } from '@0x/types';  import * as _ from 'lodash'; @@ -106,4 +107,20 @@ export const assetUtils = {          );          return _.compact(erc20sOrUndefined);      }, +    assetBuyerErrorMessage: (asset: ERC20Asset, error: Error): string | undefined => { +        if (error.message === AssetBuyerError.InsufficientAssetLiquidity) { +            const assetName = assetUtils.bestNameForAsset(asset, 'of this asset'); +            return `Not enough ${assetName} available`; +        } else if (error.message === AssetBuyerError.InsufficientZrxLiquidity) { +            return 'Not enough ZRX available'; +        } else if ( +            error.message === AssetBuyerError.StandardRelayerApiError || +            error.message.startsWith(AssetBuyerError.AssetUnavailable) +        ) { +            const assetName = assetUtils.bestNameForAsset(asset, 'This asset'); +            return `${assetName} is currently unavailable`; +        } + +        return undefined; +    },  }; diff --git a/packages/instant/src/util/buy_quote_updater.ts b/packages/instant/src/util/buy_quote_updater.ts index 2fd16d781..172b50d2a 100644 --- a/packages/instant/src/util/buy_quote_updater.ts +++ b/packages/instant/src/util/buy_quote_updater.ts @@ -1,4 +1,4 @@ -import { AssetBuyer, AssetBuyerError, BuyQuote } from '@0x/asset-buyer'; +import { AssetBuyer, BuyQuote } from '@0x/asset-buyer';  import { BigNumber } from '@0x/utils';  import { Web3Wrapper } from '@0x/web3-wrapper';  import * as _ from 'lodash'; @@ -9,6 +9,7 @@ import { Action, actions } from '../redux/actions';  import { AffiliateInfo, ERC20Asset } from '../types';  import { assetUtils } from '../util/asset';  import { errorFlasher } from '../util/error_flasher'; +import { errorReporter } from '../util/error_reporter';  export const buyQuoteUpdater = {      updateBuyQuoteAsync: async ( @@ -29,29 +30,17 @@ export const buyQuoteUpdater = {          try {              newBuyQuote = await assetBuyer.getBuyQuoteAsync(asset.assetData, baseUnitValue, { feePercentage });          } catch (error) { +            const errorMessage = assetUtils.assetBuyerErrorMessage(asset, error); + +            if (_.isUndefined(errorMessage)) { +                // This is an unknown error, report it to rollbar +                errorReporter.report(error); +            } +              if (options.dispatchErrors) {                  dispatch(actions.setQuoteRequestStateFailure()); -                let errorMessage; -                if (error.message === AssetBuyerError.InsufficientAssetLiquidity) { -                    const assetName = assetUtils.bestNameForAsset(asset, 'of this asset'); -                    errorMessage = `Not enough ${assetName} available`; -                } else if (error.message === AssetBuyerError.InsufficientZrxLiquidity) { -                    errorMessage = 'Not enough ZRX available'; -                } else if ( -                    error.message === AssetBuyerError.StandardRelayerApiError || -                    error.message.startsWith(AssetBuyerError.AssetUnavailable) -                ) { -                    const assetName = assetUtils.bestNameForAsset(asset, 'This asset'); -                    errorMessage = `${assetName} is currently unavailable`; -                } -                if (!_.isUndefined(errorMessage)) { -                    errorFlasher.flashNewErrorMessage(dispatch, errorMessage); -                } else { -                    throw error; -                } +                errorFlasher.flashNewErrorMessage(dispatch, errorMessage || 'Error fetching price, please try again');              } -            // TODO: report to error reporter on else -              return;          }          // We have a successful new buy quote diff --git a/packages/instant/src/util/error_reporter.ts b/packages/instant/src/util/error_reporter.ts new file mode 100644 index 000000000..8e21c8881 --- /dev/null +++ b/packages/instant/src/util/error_reporter.ts @@ -0,0 +1,62 @@ +import { logUtils } from '@0x/utils'; +import * as _ from 'lodash'; + +import { HOST_DOMAINS, INSTANT_ENVIRONMENT, ROLLBAR_CLIENT_TOKEN, ROLLBAR_ENABLED } from '../constants'; + +// Import version of Rollbar designed for embedded components +// See https://docs.rollbar.com/docs/using-rollbarjs-inside-an-embedded-component +// tslint:disable-next-line:no-var-requires +const Rollbar = require('rollbar/dist/rollbar.noconflict.umd'); + +let rollbar: any; +// Configures rollbar and sets up error catching +export const setupRollbar = (): any => { +    if (_.isUndefined(rollbar) && ROLLBAR_CLIENT_TOKEN && INSTANT_ENVIRONMENT && ROLLBAR_ENABLED) { +        rollbar = new Rollbar({ +            accessToken: ROLLBAR_CLIENT_TOKEN, +            captureUncaught: true, +            captureUnhandledRejections: true, +            enabled: true, +            itemsPerMinute: 10, +            maxItems: 500, +            payload: { +                environment: INSTANT_ENVIRONMENT, +                client: { +                    javascript: { +                        source_map_enabled: true, +                        code_version: process.env.GIT_SHA, +                        guess_uncaught_frames: true, +                    }, +                }, +            }, +            hostWhiteList: HOST_DOMAINS, +            uncaughtErrorLevel: 'error', +            ignoredMessages: [ +                // Errors from the third-party scripts +                'Script error', +                // Network errors or ad-blockers +                'TypeError: Failed to fetch', +                'Exchange has not been deployed to detected network (network/artifact mismatch)', +                // Source: https://groups.google.com/a/chromium.org/forum/#!topic/chromium-discuss/7VU0_VvC7mE +                "undefined is not an object (evaluating '__gCrWeb.autofill.extractForms')", +                // Source: http://stackoverflow.com/questions/43399818/securityerror-from-facebook-and-cross-domain-messaging +                'SecurityError (DOM Exception 18)', +            ], +        }); +    } +}; + +export const errorReporter = { +    report(err: Error): void { +        if (!rollbar) { +            logUtils.log('Not reporting to rollbar because not configured', err); +            return; +        } + +        rollbar.error(err, (rollbarErr: Error) => { +            if (rollbarErr) { +                logUtils.log(`Error reporting to rollbar, ignoring: ${rollbarErr}`); +            } +        }); +    }, +}; diff --git a/packages/instant/src/util/gas_price_estimator.ts b/packages/instant/src/util/gas_price_estimator.ts index 6b15809a3..332c8d00a 100644 --- a/packages/instant/src/util/gas_price_estimator.ts +++ b/packages/instant/src/util/gas_price_estimator.ts @@ -7,6 +7,8 @@ import {      GWEI_IN_WEI,  } from '../constants'; +import { errorReporter } from './error_reporter'; +  interface EthGasStationResult {      average: number;      fastestWait: number; @@ -42,8 +44,9 @@ export class GasPriceEstimator {          let fetchedAmount: GasInfo | undefined;          try {              fetchedAmount = await fetchFastAmountInWeiAsync(); -        } catch { +        } catch (e) {              fetchedAmount = undefined; +            errorReporter.report(e);          }          if (fetchedAmount) { diff --git a/packages/instant/src/util/heap.ts b/packages/instant/src/util/heap.ts index 7c53c9918..279ff3059 100644 --- a/packages/instant/src/util/heap.ts +++ b/packages/instant/src/util/heap.ts @@ -5,6 +5,7 @@ import * as _ from 'lodash';  import { HEAP_ANALYTICS_ID } from '../constants';  import { AnalyticsEventOptions, AnalyticsUserOptions } from './analytics'; +import { errorReporter } from './error_reporter';  export type EventProperties = ObjectMap<string | number>; @@ -107,8 +108,8 @@ export const heapUtil = {                  heapFunctionCall(curHeap);              } catch (e) {                  // We never want analytics to crash our React component -                // TODO(sk): error reporter here                  logUtils.log('Analytics error', e); +                errorReporter.report(e);              }          }      }, diff --git a/packages/instant/test/util/asset.test.ts b/packages/instant/test/util/asset.test.ts index 4229b24ed..fc4e4e2e4 100644 --- a/packages/instant/test/util/asset.test.ts +++ b/packages/instant/test/util/asset.test.ts @@ -1,6 +1,7 @@ +import { AssetBuyerError } from '@0x/asset-buyer';  import { AssetProxyId, ObjectMap } from '@0x/types'; -import { Asset, AssetMetaData, ERC20AssetMetaData, Network, ZeroExInstantError } from '../../src/types'; +import { Asset, AssetMetaData, ERC20Asset, ERC20AssetMetaData, Network, ZeroExInstantError } from '../../src/types';  import { assetUtils } from '../../src/util/asset';  const ZRX_ASSET_DATA = '0xf47261b0000000000000000000000000e41d2489571d322189246dafa5ebde1f4699f498'; @@ -11,7 +12,7 @@ const ZRX_META_DATA: ERC20AssetMetaData = {      decimals: 18,      name: '0x',  }; -const ZRX_ASSET: Asset = { +const ZRX_ASSET: ERC20Asset = {      assetData: ZRX_ASSET_DATA,      metaData: ZRX_META_DATA,  }; @@ -45,4 +46,32 @@ describe('assetDataUtil', () => {              ).toThrowError(ZeroExInstantError.AssetMetaDataNotAvailable);          });      }); +    describe('assetBuyerErrorMessage', () => { +        it('should return message for InsufficientAssetLiquidity', () => { +            const insufficientAssetError = new Error(AssetBuyerError.InsufficientAssetLiquidity); +            expect(assetUtils.assetBuyerErrorMessage(ZRX_ASSET, insufficientAssetError)).toEqual( +                'Not enough ZRX available', +            ); +        }); +        it('should return message for InsufficientAssetLiquidity', () => { +            const insufficientZrxError = new Error(AssetBuyerError.InsufficientZrxLiquidity); +            expect(assetUtils.assetBuyerErrorMessage(ZRX_ASSET, insufficientZrxError)).toEqual( +                'Not enough ZRX available', +            ); +        }); +        it('should message for StandardRelayerApiError', () => { +            const standardRelayerError = new Error(AssetBuyerError.StandardRelayerApiError); +            expect(assetUtils.assetBuyerErrorMessage(ZRX_ASSET, standardRelayerError)).toEqual( +                'ZRX is currently unavailable', +            ); +        }); +        it('should return error for AssetUnavailable error', () => { +            const assetUnavailableError = new Error( +                `${AssetBuyerError.AssetUnavailable}: For assetData ${ZRX_ASSET_DATA}`, +            ); +            expect(assetUtils.assetBuyerErrorMessage(ZRX_ASSET, assetUnavailableError)).toEqual( +                'ZRX is currently unavailable', +            ); +        }); +    });  }); diff --git a/packages/instant/webpack.config.js b/packages/instant/webpack.config.js index 41276809c..7149793c4 100644 --- a/packages/instant/webpack.config.js +++ b/packages/instant/webpack.config.js @@ -1,6 +1,7 @@  const childProcess = require('child_process');  const ip = require('ip');  const path = require('path'); +const RollbarSourceMapPlugin = require('rollbar-sourcemap-webpack-plugin');  const webpack = require('webpack');  // The common js bundle (not this one) is built using tsc. @@ -11,22 +12,104 @@ const GIT_SHA = childProcess      .toString()      .trim(); -const HEAP_PRODUCTION_ENV_VAR_NAME = 'INSTANT_HEAP_ANALYTICS_ID_PRODUCTION'; -const HEAP_DEVELOPMENT_ENV_VAR_NAME = 'INSTANT_HEAP_ANALYTICS_ID_DEVELOPMENT'; -const getHeapAnalyticsId = modeName => { -    if (modeName === 'production') { -        return process.env[HEAP_PRODUCTION_ENV_VAR_NAME]; +const getEnvironmentName = (env, argv) => { +    if (env && env.dogfood) { +        return 'dogfood'; +    } else if (env && env.staging) { +        return 'staging';      } -    if (modeName === 'development') { -        return process.env[HEAP_DEVELOPMENT_ENV_VAR_NAME]; +    // argv.mode should be 'development' or 'production' +    return argv.mode; +}; + +const getHeapAnalyticsId = environmentName => { +    if (environmentName === 'production') { +        return process.env['INSTANT_HEAP_ANALYTICS_ID_PRODUCTION']; +    } + +    if (environmentName === 'development' || environmentName === 'dogfood' || environmentName === 'staging') { +        return process.env['INSTANT_HEAP_ANALYTICS_ID_DEVELOPMENT'];      }      return undefined;  }; +const ROLLBAR_PUBLISH_TOKEN_ENV_NAME = 'INSTANT_ROLLBAR_PUBLISH_TOKEN'; +const ROLLBAR_CLIENT_TOKEN_ENV_NAME = 'INSTANT_ROLLBAR_CLIENT_TOKEN'; +const getRollbarSourceMapPlugin = environmentName => { +    if (!environmentName) { +        return undefined; +    } + +    const publishToken = process.env[ROLLBAR_PUBLISH_TOKEN_ENV_NAME]; +    if (!publishToken) { +        return undefined; +    } + +    let rollbarPublicPath; +    if (environmentName === 'dogfood') { +        rollbarPublicPath = 'http://0x-instant-dogfood.s3-website-us-east-1.amazonaws.com'; +    } else if (environmentName === 'staging') { +        rollbarPublicPath = 'http://0x-instant-staging.s3-website-us-east-1.amazonaws.com'; +    } // TODO(sk): When we decide on JS cdn, add public path here + +    if (!rollbarPublicPath) { +        console.log('No rollbar public path'); +        return undefined; +    } + +    const rollbarPluginOptions = { +        accessToken: publishToken, +        version: GIT_SHA, +        publicPath: rollbarPublicPath, +    }; +    return new RollbarSourceMapPlugin(rollbarPluginOptions); +}; +const validateRollbarPresence = (environmentName, rollbarEnabled, rollbarSourceMapPlugin) => { +    const requiresRollbar = environmentName === 'dogfood' || environmentName === 'staging'; +    if (!requiresRollbar) { +        return; +    } +    if (!rollbarEnabled || !rollbarSourceMapPlugin) { +        throw new Error( +            `Rollbar env vars must be set to build for ${environmentName}. Please set ${ROLLBAR_CLIENT_TOKEN_ENV_NAME} to a rollbar access token with post_client_item permissions, and ${ROLLBAR_PUBLISH_TOKEN_ENV_NAME} to a rollbar access token with post_server_item permissions.`, +        ); +    } +}; +  module.exports = (env, argv) => { +    const environmentName = getEnvironmentName(env, argv);      const outputPath = process.env.WEBPACK_OUTPUT_PATH || 'umd'; + +    const envVars = { +        GIT_SHA: JSON.stringify(GIT_SHA), +        NPM_PACKAGE_VERSION: JSON.stringify(process.env.npm_package_version), +        HEAP_ANALYTICS_ID: getHeapAnalyticsId(environmentName), +        INSTANT_ENVIRONMENT: JSON.stringify(environmentName), +        ROLLBAR_CLIENT_TOKEN: JSON.stringify(process.env[ROLLBAR_CLIENT_TOKEN_ENV_NAME]), +    }; + +    const canRollbarBeEnabled = +        environmentName === 'development' ? process.env.INSTANT_ROLLBAR_FORCE_DEVELOPMENT_REPORT : true; +    if (envVars.INSTANT_ENVIRONMENT && envVars.ROLLBAR_CLIENT_TOKEN && canRollbarBeEnabled) { +        envVars['ROLLBAR_ENABLED'] = JSON.stringify(true); +    } + +    let plugins = [ +        new webpack.DefinePlugin({ +            'process.env': envVars, +        }), +    ]; +    const rollbarSourceMapPlugin = getRollbarSourceMapPlugin(environmentName); +    if (rollbarSourceMapPlugin) { +        console.log('Using rollbar source map plugin'); +        plugins = plugins.concat(rollbarSourceMapPlugin); +    } else { +        console.log('Not using rollbar source map plugin'); +    } +    validateRollbarPresence(environmentName, envVars['ROLLBAR_ENABLED'], rollbarSourceMapPlugin); +      const config = {          entry: {              instant: './src/index.umd.ts', @@ -37,15 +120,7 @@ module.exports = (env, argv) => {              library: 'zeroExInstant',              libraryTarget: 'umd',          }, -        plugins: [ -            new webpack.DefinePlugin({ -                'process.env': { -                    GIT_SHA: JSON.stringify(GIT_SHA), -                    HEAP_ANALYTICS_ID: getHeapAnalyticsId(argv.mode), -                    NPM_PACKAGE_VERSION: JSON.stringify(process.env.npm_package_version), -                }, -            }), -        ], +        plugins,          devtool: 'source-map',          resolve: {              extensions: ['.js', '.json', '.ts', '.tsx'], @@ -60,6 +135,15 @@ module.exports = (env, argv) => {                      test: /\.svg$/,                      loader: 'svg-react-loader',                  }, +                { +                    test: /\.js$/, +                    loader: 'source-map-loader', +                    exclude: [ +                        // instead of /\/node_modules\// +                        path.join(process.cwd(), 'node_modules'), +                        path.join(process.cwd(), '../..', 'node_modules'), +                    ], +                },              ],          },          devServer: { diff --git a/packages/monorepo-scripts/src/prepublish_checks.ts b/packages/monorepo-scripts/src/prepublish_checks.ts index 60cdccf1d..5fe1aacf2 100644 --- a/packages/monorepo-scripts/src/prepublish_checks.ts +++ b/packages/monorepo-scripts/src/prepublish_checks.ts @@ -186,7 +186,11 @@ async function checkPublishRequiredSetupAsync(): Promise<void> {  const checkRequiredEnvVariables = () => {      utils.log('Checking required environment variables...'); -    const requiredEnvVars = ['INSTANT_HEAP_ANALYTICS_ID_PRODUCTION']; +    const requiredEnvVars = [ +        'INSTANT_HEAP_ANALYTICS_ID_PRODUCTION', +        'INSTANT_ROLLBAR_CLIENT_TOKEN', +        'INSTANT_ROLLBAR_PUBLISH_TOKEN', +    ];      requiredEnvVars.forEach(requiredEnvVarName => {          if (_.isUndefined(process.env[requiredEnvVarName])) {              throw new Error(`Must have ${requiredEnvVarName} set`); @@ -13367,6 +13367,21 @@ rollbar@^2.4.7:    optionalDependencies:      decache "^3.0.5" +rollbar@^2.5.0: +  version "2.5.0" +  resolved "https://registry.yarnpkg.com/rollbar/-/rollbar-2.5.0.tgz#dbb513eea34f1e3bae57611810c3e6df0ef50a12" +  dependencies: +    async "~1.2.1" +    console-polyfill "0.3.0" +    debug "2.6.9" +    error-stack-parser "1.3.3" +    json-stringify-safe "~5.0.0" +    lru-cache "~2.2.1" +    request-ip "~2.0.1" +    uuid "3.0.x" +  optionalDependencies: +    decache "^3.0.5" +  rst-selector-parser@^2.2.3:    version "2.2.3"    resolved "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91"  | 
