├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── README.md ├── example ├── .babelrc ├── .eslintrc ├── index.html ├── index.js └── webpack.config.js ├── index.js ├── index.test.js └── package.json /.babelrc: -------------------------------------------------------------------------------- 1 | { "presets": ["es2015"] } 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | built/ 2 | coverage/ 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "hss", 4 | "hss/es6", 5 | "prettier" 6 | ], 7 | "plugins": [ 8 | "prettier" 9 | ], 10 | "rules": { 11 | "prettier/prettier": "error", 12 | "prefer-arrow-callback": "error" 13 | }, 14 | "parserOptions": { 15 | "ecmaVersion": 8, 16 | "sourceType": "script" 17 | }, 18 | "env": { 19 | "jest": true, 20 | "node": true, 21 | "es6": true 22 | } 23 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | built/ 3 | coverage/ 4 | .vscode/ 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | * 2 | !built/ 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | before_script: 2 | - 'if [ "$RAVEN_VERSION" ]; then npm install raven-js@$RAVEN_VERSION; fi' 3 | env: 4 | - RAVEN_VERSION="latest" 5 | - RAVEN_VERSION="^3.0.0" 6 | - RAVEN_VERSION="~3.9.0" 7 | language: node_js 8 | node_js: 9 | - "node" 10 | after_success: 11 | - bash <(curl -s https://codecov.io/bash) 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Travis](https://img.shields.io/travis/captbaritone/raven-for-redux.svg)]() [![Codecov](https://img.shields.io/codecov/c/github/captbaritone/raven-for-redux.svg)]() 2 | . 3 | 4 | # Deprecated 5 | 6 | Sentry now recommends using their new SDK `@sentry/browser` rather than Raven. Check out [redux-sentry-middleware](https://github.com/vidit-sh/redux-sentry-middleware) for an API compatible fork of this library that supports the new SDK! 7 | 8 | 9 | # Raven Middleware for Redux 10 | 11 | _Note:_ Requires Raven >= 3.9.0. Raven 3.14.0 has [a bug](https://github.com/getsentry/raven-js/issues/925) 12 | which this library triggers 13 | 14 | 15 | Logs the type of each dispatched action to Raven as "breadcrumbs" and attaches 16 | your last action and current Redux state as additional context. 17 | 18 | Inspired by [redux-raven-middleware] but with a slightly [different approach](#improvements). 19 | 20 | ## Installation 21 | 22 | npm install --save raven-for-redux 23 | 24 | ## Usage 25 | 26 | ### Browser 27 | 28 | ```JavaScript 29 | // store.js 30 | 31 | import Raven from "raven-js"; // Or, you might already have this as `window.Raven`. 32 | import { createStore, applyMiddleware } from "redux"; 33 | import createRavenMiddleware from "raven-for-redux"; 34 | 35 | import { reducer } from "./my_reducer"; 36 | 37 | Raven.config("").install(); 38 | 39 | export default createStore( 40 | reducer, 41 | applyMiddleware( 42 | // Middlewares, like `redux-thunk` that intercept or emit actions should 43 | // precede `raven-for-redux`. 44 | createRavenMiddleware(Raven, { 45 | // Optionally pass some options here. 46 | }) 47 | ) 48 | ); 49 | ``` 50 | 51 | For a working example, see the [example](./example/) directory. 52 | 53 | ### TypeScript 54 | `raven-for-redux` has TypeScript bindings available through [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b7ca35ab023ba1758de9e07004adde71e911c28e/types/raven-for-redux/index.d.ts). Please note the import style below, as it differs from the JavaScript example and is required for these typings. 55 | ```TypeScript 56 | import * as Raven from "raven-js"; 57 | import * as createRavenMiddleware from "raven-for-redux"; 58 | import { applyMiddleware, createStore } from "redux"; 59 | 60 | //... (same as JavaScript example, but now with proper typings) 61 | ``` 62 | 63 | ## Improvements 64 | 65 | This library makes, what I think are, a few improvements over 66 | `redux-raven-middlware`: 67 | 68 | 1. Raven is injected rather than being setup inside the middleware. This allows 69 | for more advanced configuration of Raven, as well as cases where Raven has 70 | already been initialized. For example, if you include Raven as its own 71 | ` 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import Raven from "raven-js"; 2 | import React from "react"; 3 | import { render } from "react-dom"; 4 | import { createStore, applyMiddleware } from "redux"; 5 | import createRavenMiddleware from "../"; // "raven-for-redux" 6 | 7 | const RAVEN_DSN = "https://5d5bf17b1bed4afc9103b5a09634775e@sentry.io/146969"; 8 | Raven.config(RAVEN_DSN).install(); 9 | 10 | // A very error-prone reducer. 11 | const reducer = (state = "Hello world!", action) => { 12 | switch (action.type) { 13 | case "CRASH_IN_THE_REDUCER": 14 | throw new Error("Whoops, we crashed in the reducer!"); 15 | case "UPDATE_MY_STRING": 16 | return action.str; 17 | default: 18 | return state; 19 | } 20 | }; 21 | 22 | const store = createStore( 23 | reducer, 24 | applyMiddleware( 25 | createRavenMiddleware(Raven, { 26 | breadcrumbDataFromAction: action => { 27 | return { STRING: action.str }; 28 | } 29 | }) 30 | ) 31 | ); 32 | 33 | document.getElementById("crash").addEventListener("click", () => { 34 | throw new Error("Whoops! My application crashed!"); 35 | }); 36 | document.getElementById("crash-in-reducer").addEventListener("click", () => { 37 | store.dispatch({ type: "CRASH_IN_THE_REDUCER" }); 38 | }); 39 | document.getElementById("set-state").addEventListener("click", () => { 40 | store.dispatch({ 41 | type: "UPDATE_MY_STRING", 42 | str: document.getElementById("state").value 43 | }); 44 | }); 45 | 46 | const Button = () => ( 47 | 54 | ); 55 | 56 | render(