Skip to content

Commit

Permalink
refactor(files): moved everything out of src/index.js into separate f…
Browse files Browse the repository at this point in the history
…iles
  • Loading branch information
eudaimos committed Apr 14, 2021
1 parent 8b354fa commit 5f39728
Show file tree
Hide file tree
Showing 17 changed files with 419 additions and 347 deletions.
13 changes: 13 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const LEVEL_DEBUG = 'debug';
export const LEVEL_INFO = 'info';
export const LEVEL_WARN = 'warn';
export const LEVEL_ERROR = 'error';
export const LEVEL_CRITICAL = 'critical';

export default {
[LEVEL_DEBUG]: 1,
[LEVEL_INFO]: 2,
[LEVEL_WARN]: 3,
[LEVEL_ERROR]: 4,
[LEVEL_CRITICAL]: 5,
}
75 changes: 75 additions & 0 deletions src/error-boundary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React from 'react';
import PropTypes from 'prop-types';
import invariant from 'tiny-invariant';
import VALID_LEVELS, { LEVEL_ERROR } from './constants';
import { Context, getRollbarFromContext } from './provider';

const INITIAL_ERROR_STATE = { hasError: false, error: null };

export class ErrorBoundary extends Component {
static contextType = Context;

static propTypes = {
fallbackUI: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
errorMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
extra: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
level: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
callback: PropTypes.func,
}

static defaultProps = {
level: LEVEL_ERROR,
}

constructor(props) {
super(props);
invariant(VALID_LEVELS.includes(props.level), `${props.level} is not a valid level setting for Rollbar`);
this.state = { ...INITIAL_ERROR_STATE };
}

static getDerivedStateFromError(error) {
return { hasError: true, error };
}

componentDidCatch(error, info) {
const { errorMessage, extra, level: targetLevel, callback } = this.props;
const custom = utils.value(extra, {}, error, info);
const data = { ...info, ...custom };
const level = utils.value(targetLevel, LEVEL_ERROR, error, info);
const rollbar = getRollbarFromContext(this.context);
if (!errorMessage) {
rollbar[level](error, data, callback);
} else {
let logMessage = utils.value(errorMessage, '', error, info);
rollbar[level](logMessage, error, data, callback);
}
}

resetError = () => {
this.setState(INITIAL_ERROR_STATE);
}

render() {
const { hasError, error } = this.state;
const { fallbackUI, children } = this.props;

if (!hasError) {
return children;
}

if (!fallbackUI) {
return null;
}

if (React.isValidElement(fallbackUI)) {
return <fallbackUI error={error} resetError={this.resetError} />;
}

if (typeof fallbackUI === 'function') {
const fallbackComponent = fallbackUI(error, this.resetError);
return React.isValidElement(fallbackComponent) ? fallbackComponent : null;
}

return null;
}
}
24 changes: 24 additions & 0 deletions src/history-context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Rollbar from 'rollbar';
import invariant from 'tiny-invariant';

export function historyContext(rollbar, { formatter, filter }) {
invariant(rollbar instanceof Rollbar, 'historyContext must have an instance of Rollbar');
invariant(formatter == null || typeof formatter === 'function', `formatter option must be a function, received ${typeof formatter} instead`);
invariant(filter == null || typeof filter === 'function', `filter option must be a function, received ${typeof filter} instead`);
// v4 of history.listen callback signature is (location, action)
// v5 of history.listen callback signature is ({ location, action })
// this implementation translates it to work for both
return (v4location, v4action) => {
let { action, location } = v4location;
if (v4action) {
action = v4action;
location = v4location;
}
if (filter && !filter(location, action)) {
return;
}
const context = formatter ? formatter(location, action) : location.pathname;
invariant(typeof context === 'string', 'formatter must return a string value to set the context');
rollbar.configure({ payload: { context }});
}
}
5 changes: 5 additions & 0 deletions src/hooks/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export { useRollbar } from './use-rollbar';
export { useRollbarConfiguration } from './use-rollbar-config';
export { useRollbarContext } from './use-rollbar-context';
export { useRollbarPerson } from './use-rollbar-person';
export { useRollbarCaptureEvent } from './use-rollbar-capture-event';
12 changes: 12 additions & 0 deletions src/hooks/use-rollbar-capture-event.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import invariant from 'tiny-invariant';
import VALID_LEVELS, { LEVEL_DEBUG, LEVEL_INFO, LEVEL_CRITICAL } = '../constants';
import [ useRollbar } from './use-rollbar';

export function useRollbarCaptureEvent(metadata, level = LEVEL_INFO) {
invariant(VALID_LEVELS[level] <= LEVEL_CRITICAL && VALID_LEVELS[level] >= LEVEL_DEBUG, '')
const rollbar = useRollbar();
useEffect(() => {
rollbar.captureEvent(metadata, level);
}, [metadata]);
}

6 changes: 6 additions & 0 deletions src/hooks/use-rollbar-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import [ useRollbar } from './use-rollbar';

export function useRollbarConfiguration(config) {
const rollbar = useRollbar();
rollbar.configure(config);
}
21 changes: 21 additions & 0 deletions src/hooks/use-rollbar-context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import invariant from 'tiny-invariant';
import { useRollbar } from './use-rollbar';
import { useRollbarConfiguration } from './use-rollbar-config';

// Simple version does its job
// export function useRollbarContext(context) {
// useRollbarConfiguration({ payload: { context }});
// }

// Complex version will set the context when part of the tree and reset back to original context when removed
export function useRollbarContext(ctx = '', isLayout = false) {
invariant(typeof ctx === 'string', '`ctx` must be a string');
const rollbar = useRollbar();
(isLayout ? useLayoutEffect : useEffect)(() => {
const origCtx = rollbar.options.payload.context;
rollbar.configure({ payload: { context: ctx }});
return () => {
rollbar.configure({ payload: { context: origCtx }});
};
}, [ctx]);
}
42 changes: 42 additions & 0 deletions src/hooks/use-rollbar-logs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// EXPERIMENTAL
// NOT EXPORTED AS PART OF PUBLIC API YET
// NO TEST COVERAGE

import { useEffect, useLayoutEffect } from 'react';
import invariant from 'tiny-invariant';
import VALID_LEVELS, { LEVEL_DEBUG, LEVEL_INFO, LEVEL_WARN, LEVEL_ERROR, LEVEL_CRITICAL } from '../constants';
import { useRollbar } from './use-rollbar';

const LOG = 'log';

function useRollbarNotify(type, isLayout, ...args) {
invariant(type === LOG || VALID_LEVELS[type] >= LEVEL_DEBUG && VALID_LEVELS[type] <= LEVEL_CRITICAL, `cannot notify rollbar using method '${type}'`);
const rollbar = useRollbar();
(isLayout ? useLayoutEffect : useEffect)(() => {
rollbar[type](...args);
}, args)
}

export function useRollbarLog(isLayout, ...args) {
useRollbarNotify(LOG, isLayout, ...args);
}

export function useRollbarDebug(isLayout, ...args) {
useRollbarNotify(LEVEL_DEBUG, isLayout, ...args);
}

export function useRollbarInfo(isLayout, ...args) {
useRollbarNotify(LEVEL_INFO, isLayout, ...args);
}

export function useRollbarWarn(isLayout, ...args) {
useRollbarNotify(LEVEL_WARN, isLayout, ...args);
}

export function useRollbarError(isLayout, ...args) {
useRollbarNotify(LEVEL_ERROR, isLayout, ...args);
}

export function useRollbarCritical(isLayout, ...args) {
useRollbarNotify(LEVEL_ERROR, isLayout, ...args);
}
5 changes: 5 additions & 0 deletions src/hooks/use-rollbar-person.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { useRollbarConfiguration } from './use-rollbar-config';

export function useRollbarPerson(person) {
useRollbarConfiguration({ payload: { person }});
}
7 changes: 7 additions & 0 deletions src/hooks/use-rollbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { useContext } from 'react';
import { Context, getRollbarFromContext } from '../provider';

export function useRollbar() {
const context = useContext(Context);
return getRollbarFromContext(context);
}
15 changes: 15 additions & 0 deletions src/hooks/use-scoped-rollbar-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// EXPERIMENTAL
// NOT EXPORTED AS PART OF PUBLIC API YET
// NO TEST COVERAGE

import { useContext } from 'react';
import { Context, getRollbarFromContext, getRollbarConstructorFromContext } from '../provider';

export function useScopedConfiguration(config) {
const ctx = useContext(Context);
const rollbar = getRollbarFromContext(ctx);
const ctor = getRollbarConstructorFromContext(ctx);
const rollbar = new ctor(base.options);
rollbar.configure(config);
return rollbar;
}
15 changes: 15 additions & 0 deletions src/hooks/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useRef } from 'react';

// EXPERIMENTAL (NOT IN USE): wrap the instance of rollbar to prevent modification
export function wrapRollbarApi(rollbar) {
const rb = useRef(rollbar);
return {
log: (...args) => rb.current.log(...args),
debug: (...args) => rb.current.debug(...args),
info: (...args) => rb.current.info(...args),
warn: (...args) => rb.current.warn(...args),
error: (...args) => rb.current.error(...args),
critical: (...args) => rb.current.critical(...args),
captureEvent: (...args) => rb.current.captureEvent(...args),
}
}
Loading

0 comments on commit 5f39728

Please sign in to comment.