{"id":13394372,"url":"https://github.com/dtschust/redux-bug-reporter","last_synced_at":"2025-03-13T20:31:29.443Z","repository":{"id":57350366,"uuid":"60634558","full_name":"dtschust/redux-bug-reporter","owner":"dtschust","description":":bug: A bug reporter and bug playback tool for redux. :bug:","archived":false,"fork":false,"pushed_at":"2018-01-19T01:43:45.000Z","size":1396,"stargazers_count":685,"open_issues_count":2,"forks_count":20,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-09-21T16:38:24.314Z","etag":null,"topics":["debug","devtools","playback","react","redux","replay"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dtschust.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-06-07T17:55:04.000Z","updated_at":"2024-08-01T20:52:30.000Z","dependencies_parsed_at":"2022-09-16T21:12:45.074Z","dependency_job_id":null,"html_url":"https://github.com/dtschust/redux-bug-reporter","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtschust%2Fredux-bug-reporter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtschust%2Fredux-bug-reporter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtschust%2Fredux-bug-reporter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dtschust%2Fredux-bug-reporter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dtschust","download_url":"https://codeload.github.com/dtschust/redux-bug-reporter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243478098,"owners_count":20297193,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["debug","devtools","playback","react","redux","replay"],"created_at":"2024-07-30T17:01:17.397Z","updated_at":"2025-03-13T20:31:28.724Z","avatar_url":"https://github.com/dtschust.png","language":"JavaScript","funding_links":[],"categories":["Utilities","JavaScript","📦 Legacy \u0026 Inactive Projects"],"sub_categories":[],"readme":"\u003cdiv align=\"center\" style=\"margin-bottom: 30px;\"\u003e\n\u003cimg src=\"https://raw.githubusercontent.com/dtschust/redux-bug-reporter/master/.github/Logo.png\" width=\"100\"/\u003e\n\u003c/div\u003e\n\n# Redux Bug Reporter\n\nAuthors: [Drew Schuster](https://github.com/dtschust) \u0026 [Greg Mathews](https://github.com/gregsqueeb)\n\n[![npm version](https://img.shields.io/npm/v/redux-bug-reporter.svg)](https://www.npmjs.com/package/redux-bug-reporter)\n[![npm downloads](https://img.shields.io/npm/dm/redux-bug-reporter.svg)](https://www.npmjs.com/package/redux-bug-reporter)\n[![build](https://travis-ci.org/dtschust/redux-bug-reporter.svg?branch=master)](https://travis-ci.org/dtschust/redux-bug-reporter)\n[![coverage](https://img.shields.io/codecov/c/github/dtschust/redux-bug-reporter.svg)](https://codecov.io/gh/dtschust/redux-bug-reporter)\n[![license](https://img.shields.io/github/license/dtschust/redux-bug-reporter.svg?maxAge=2592000)](/LICENSE.md)\n[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)\n\n## Demo\n\n[✨DEMO ✨](http://dtschust.github.io/redux-bug-reporter)\n\n[Prototype Demo Video](https://www.youtube.com/watch?v=n8vkg_RVIRo)\n\n## Features\n* **Easy Bug Filing** - Any user is able to easily file bugs right from your application\n* **Redux logging** - Any bug filed automatically passes along everything needed to recreate the bug. Initial redux state, all actions performed, and final redux state\n* **Redaction** - Customizable hooks allow for redaction of any sensitive information in redux state or in action payloads before bug submission\n* **Easy Playback of Bug** - A global function `window.bugReporterPlayback` is available to replay any bug\n* **Automatic Logging of browser errors** - Any calls to `console.error` or `window.onError` are filed with a bug automatically\n* **Automatic Browser Info logging** - All bugs filed automatically include window dimensions, window location, and user agent\n* **Extensible**\n    * Extra properties passed in as `meta` to the Redux Bug Reporter component are filed alongside the bug\n    * Submit property can either be a URL or a custom function that returns a promise. This should allow Redux Bug Reporter to work in any development environment\n* **Integration With Bug Trackers**\n    * Ships with integration for Jira, GitHub Issues, Asana, Taiga, and Google Sheets (via Sheetsu)\n    * Easy to write custom integration with other bug trackers\n    * [Integration Documentation](/docs/integrations.md)\n\n## Installation\n\nThe easiest way to use Redux Bug Reporter is to install it from npm and include it in your own build process (Webpack, Browserify, etc)\n```\n$ npm install --save redux-bug-reporter\n```\n\nA UMD build is also available:\n```html\n\u003clink rel=\"stylesheet\" href=\"redux-bug-reporter/dist/redux-bug-reporter.min.css\"\u003e\n\u003cscript src=\"redux-bug-reporter/dist/redux-bug-reporter.min.js\"\u003e\u003c/script\u003e\n```\n\n## Performance and Production Use\nRedux Bug Reporter puts minimal overhead on redux actions. However, it does keep copies of initial state, final state on bug submission, and full copies of all actions dispatched. For an application with heavy actions (such as network requests with large payloads) or very frequent actions, Redux Bug Reporter will gradually take up more and more memory. As such, it's probably a good idea to disable in production by default. The examples below demonstrate the expected common behavior of only enabling Redux Bug Reporter in non-production environments.\n### What about server-side rendering?\nRedux Bug Reporter disables itself by default if `window` is undefined, so it will not negatively impact server side renders.\n### But *can* it run in production?\nRedux Bug Reporter can run in production. It's assumed that an application usually wouldn't want the bug reporter to be displayed on the page and allow public users to file bugs, but if that is the desired behavior Redux Bug Reporter does work in production.\n\n## Usage\n### 1. Use with Redux\nUpdate your configure store:\n```javascript\nfunction configureStore(initialState) {\n  const store = createStore(reducer, initialState, compose(\n    applyMiddleware(...middleware)\n  ));\n  return store;\n}\n```\n*becomes*\n```javascript\n// ES6\nimport {storeEnhancer} from 'redux-bug-reporter'\n// ES5\nvar storeEnhancer = require('redux-bug-reporter').storeEnhancer\n\nfunction configureStore(initialState) {\n  const store = createStore(reducer, initialState, compose(\n    process.env.NODE_ENV !== 'production' ? storeEnhancer : f =\u003e f,\n    applyMiddleware(...middleware)\n  ));\n  return store;\n}\n```\nor if you don't have other store enhancers and middlewares\n```javascript\n// ES6\nimport {storeEnhancer} from 'redux-bug-reporter'\n// ES5\nvar storeEnhancer = require('redux-bug-reporter').storeEnhancer\n\nfunction configureStore(initialState) {\n  const store = createStore(reducer, initialState,\n    process.env.NODE_ENV !== 'production' ? storeEnhancer : f =\u003e f\n  );\n  return store;\n}\n```\n### 2. Render UI Component\n```js\n// ES6\nimport ReduxBugReporter from 'redux-bug-reporter'\nimport 'redux-bug-reporter/dist/redux-bug-reporter.css'\n// ES5\nvar ReduxBugReporter = require('redux-bug-reporter').default\nrequire('redux-bug-reporter/dist/redux-bug-reporter.css')\n\nconst ParentContainer = () =\u003e {\n    return (\n        \u003cdiv\u003e\n          This is your app, already wrapped in a Provider from react-redux\n          {process.env.NODE_ENV !== 'production' \u0026\u0026 \u003cReduxBugReporter submit='http://localhost/path/to/post/bug/to' projectName='Test'/\u003e}\n        \u003c/div\u003e\n    )\n}\n```\n\n### 3. Integrate With Backend Service\nRedux Bug Reporter needs to be able to submit bugs to some sort of backend. Redux Bug Reporter ships with integrations to many common bug trackers. See the [integration docs](/docs/integrations.md) to set one up. If a backend service doesn't exist, a temporary solution to try Redux Bug Reporter is to log bugs to the console instead of submitting them.\n\n```js\nimport submitFn from 'redux-bug-reporter/lib/integrations/console'\n\n// Later, in render\n\u003cReduxBugReporter submit={submitFn} projectName='example'/\u003e\n```\n\n### 4. Replay Filed Bugs\nTo replay a filed bug, call the global `bugReporterPlayback` function with the appropriate parameters:\n```js\nwindow.bugReporterPlayback(actions, initialState, state, delay)\n```\nThe delay parameter is the amount of time (in ms) between actions during playback. The default value is 100. **Note: Setting a delay value of -1 will skip playback and just set the redux store state to be equal to the final state of the bug. This is useful in situations where an application maintains critical state outside of redux and playback does not work.**\n\n\n\n## Prop Types\n| Property        | Type                       | Default | Description |\n|:---------       |:-----                      |:--------|:------------|\n|submit           |Function or String          |         |**Required** If a string, the URL to post a bug to. If a function, a function called that will submit the bug. **Note: function must return a promise**|\n|projectName      |String                      |         |**Required** Name of the project the bug should be filed against. This can be used to scope bugs between different initiatives|\n|redactStoreState |Function                    |         |*optional* A function that receives the state and returns a redacted state before bug submission. **Warning: Should not alter passed in state** See [Redacting Sensitive Data](#redacting-sensitive-data)|\n|name             |String                      |         |*optional* If the application knows the name of the user, this can be used to prepopulate the submission form|\n|meta             |Any                         |         |*optional* If `meta` exists, it will be passed along on bug submission|\n|customEncode     |Function                    |         | *optional* A function that receives the state and returns a new encoded state before bug submission (useful for [serializing immutable objects](#working-with-immutablejs-or-similar-libraries))|\n|customDecode     |Function                    |         | *optional* A function that receives the state and returns a new decoded state before bug playback (useful for [deserializing immutable objects](#working-with-immutablejs-or-similar-libraries))|\n\n## Redacting Sensitive Data\nSince Redux Bug Reporter logs all redux state and actions, there could easily be sensitive information in submitted bugs. There are two ways to redact information before submission.\n### Redacting Information from Store State\nPass in a redaction function as the `redactStoreState` prop to the `ReduxBugReporter` component. It will be applied to the initial store state and the final store state before bug submission.\n```js\nlet redactStoreState = function (state) {\n    // Deep Clone the state to prevent altering actual state\n    let newState = _.cloneDeep(state)\n    if (newState \u0026\u0026 newState.identity \u0026\u0026 newState.identity.name) {\n        newState.identity.name = 'REDACTED'\n    }\n    return newState\n}\n\n// Later, in render\n\u003cReduxBugReporter submit='http://localhost/path/to/post/bug/to' projectName='Test' redactStoreState={redactStoreState}/\u003e\n```\n### Redacting Information from Action Payloads\nIn order to redact information from a payload of an action, set `action.meta.redactFromBugReporter` to `true`. If that boolean exists and no custom redaction function is specified, all that will be logged for the action is its `type`. A custom redaction function can be specified by creating it at `action.meta.redactFromBugReporterFn`. If `redactFromBugReporterFn` exists, the action will be deep cloned and passed in to the redaction function, which will return the sanitized action and payload.\n```js\nlet action {\n    type: 'SIMPLE_ACTION',\n    sensitiveField: 'SECRETS',\n    meta: {\n        redactFromBugReporter: true,\n        unrelatedMeta: true\n    }\n}\n// Redacted action is { type: 'SIMPLE_ACTION', meta: { unrelatedMeta: true } }\n\nlet action {\n    type: 'CUSTOM_REDACTION_ACTION',\n    sensitiveField: 'SECRETS',\n    nonSensitiveField: 'Foo Bar'\n    meta: {\n        redactFromBugReporter: true,\n        redactFromBugReporterFn: function (action) {\n            delete action.sensitiveField\n            return action\n        },\n        unrelatedMeta: true\n    }\n}\n// Redacted action is { type: 'CUSTOM_REDACTION_ACTION', nonSensitiveField: 'Foo Bar', meta: { unrelatedMeta: true } }\n```\n\n## Working with ImmutableJS or similar libraries\nTo file and replay bugs, redux-bug-reporter needs to submit redux state as a JSON object and receive redux state as a JSON object. If all or part of your redux store is using a library such as [immutable](https://github.com/facebook/immutable-js), you will need to pass in the `customEncode` and `customDecode` properties to `\u003cReduxBugReporter\u003e`.\n```js\n/* Assume your redux state is of the form\n{\n    immutableState: IMMUTABLE_OBJECT,\n    normalMutableState: { foo: true }\n}\n*/\nimport { fromJS } from 'immutable'\nconst customEncode = (state) =\u003e {\n    return {\n        immutableState: state.immutableState.toJSON(),\n        mutableState: state.mutableState\n    }\n}\n\nconst customDecode = (state) =\u003e {\n    return {\n        immutableState: fromJS(state.immutableState),\n        mutableState: state.mutableState\n    }\n}\n\n// Later, when rendering Redux Bug Reporter\n\u003cReduxBugReporter submit='http://localhost/path/to/post/bug/to' projectName='Test' customEncode={customEncode} customDecode={customDecode}/\u003e\n```\n\n## Contributions\n- Fork the project\n- Make changes\n- Double check changes work by adding it to the examples\n- Confirm that tests still pass\n- Write new tests if applicable\n- Update README with appropriate docs\n- Commit and create a PR\n\n## License\n\nMIT\n\n[![Analytics](https://ga-beacon.appspot.com/UA-83674100-2/welcome-page?pixel)](https://github.com/igrigorik/ga-beacon)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdtschust%2Fredux-bug-reporter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdtschust%2Fredux-bug-reporter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdtschust%2Fredux-bug-reporter/lists"}