{"_id":"@compozed/redux-delux","_rev":"3-35c3e49c0f09fd7f423d7c4d1b0f693e","name":"@compozed/redux-delux","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@compozed/redux-delux","version":"0.1.0","description":"Manage RESTful API transactions without the boilerplate","main":"lib/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/compozed/redux-delux.git"},"scripts":{"test":"jest","compile":"npx babel-cli src -d lib","prepublish":"npm run compile"},"peerDependencies":{"axios":"^0.18.0","react":"^16.2.0","react-redux":"^5.0.6","redux":"^3.7.2"},"devDependencies":{"axios-mock-adapter":"^1.15.0","babel-cli":"^6.26.0","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-plugin-transform-runtime":"^6.23.0","jest":"^22.4.3","sinon":"^5.0.7","axios":"^0.18.0","react":"^16.2.0","react-redux":"^5.0.6","redux":"^3.7.2"},"dependencies":{"babel-core":"^6.26.3","babel-jest":"^22.4.3","babel-preset-env":"^1.7.0","regenerator-runtime":"^0.11.1"},"gitHead":"875a027d29f4e31e92ee1082c173dae14569d3e1","bugs":{"url":"https://github.com/compozed/redux-delux/issues"},"homepage":"https://github.com/compozed/redux-delux#readme","_id":"@compozed/redux-delux@0.1.0","_npmVersion":"6.1.0","_nodeVersion":"10.5.0","_npmUser":{"name":"joshmcguigan","email":"joshmcg88@gmail.com"},"dist":{"integrity":"sha512-ARIcMltrlAhEU/Bw+VXZIJd742kJiN8F4mQ8CqUCba666E1XRan2zi4H3mdUGeoeVFoZPt6q/8hMgWmRi0TS/Q==","shasum":"58b17f9d46bc7a4449544b2be31614097e0ed7ef","tarball":"https://registry.npmjs.org/@compozed/redux-delux/-/redux-delux-0.1.0.tgz","fileCount":22,"unpackedSize":58183,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbm+oXCRA9TVsSAnZWagAAJ5QP/iSmZdZMnRPTBrJLqrXi\nj8xc6Cel++rY7MaVN5W0KUfEJ9bhNljsrmmPqAOxKuqJ8GNckmArw939eXSt\nXPy3h9tBaJBJlCgpOXLZY6niGsjC9c6247jleP8N63iIepwI+65sM/fqsa1q\nuUfz8sE7QAtIWoAEeqIda8BHppCtNZi/mHKRaaZNQfxKCVocUQb+hnVuAyex\n/BL5V1qEO2R+f4IzPVlWUWZBNFhud8DzjFuBxYKJmCw2wLZD1osF7PwelgTr\nKIKPycyYmki2ndFrnwscnkaFZqczKeaAlXjBSaJFfsXJe9rPZgyDRHpt1wKa\nQPw1bwQKmcZTIK4xXrSi6k8IngLHy76M/ltALPCN+N5RjVavnHVA+OIGGS9O\noygifZbRDWr4RgL4kBRGjqGCxqV8bJlO78AYxvJcWAKUZ4QRj741FRM/G3TU\nN5UZp4VusNDaWmdvnbdRWn5CYOdDvY6z2KsxD2/fLwCMoPrHHDKqDe2XDg+C\nOp6xE3jqp11vZ9pVG2IAc0vH0dAt/Mrn4KAwRYT02WI+kt68iQ9tfCtieX1A\nYCudt1jAVMAZlehHSCXc26g7ANL7jPsNtKJkeHHPGP5fFEAhn9vAnyaVcjDH\n4O7v/BBJmqRkGlpvg+r0J5qHazUJjh7oIPfctzpK2Abu5oKsJn4aHEZUObyo\nT46q\r\n=UudQ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFKZSw31ckgAcxw8VqGEwVFB/CfRUTgbleYPtl+xiJE6AiEAy7qQ9SAgjimmKYSnfgF1DTUx3/a1VlLuGHrKVq212Ss="}]},"maintainers":[{"name":"joshmcguigan","email":"joshmcg88@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/redux-delux_0.1.0_1536944662909_0.6193740290904006"},"_hasShrinkwrap":false},"0.2.0":{"name":"@compozed/redux-delux","version":"0.2.0","description":"Manage RESTful API transactions without the boilerplate","main":"lib/index.js","license":"MIT","repository":{"type":"git","url":"git+https://github.com/compozed/redux-delux.git"},"scripts":{"test":"jest","compile":"npx babel-cli src -d lib","prepublish":"npm run compile"},"peerDependencies":{"axios":"^0.18.0","react":"^16.2.0","react-redux":"^5.0.6","redux":"^3.7.2"},"devDependencies":{"axios-mock-adapter":"^1.15.0","babel-cli":"^6.26.0","babel-plugin-transform-object-rest-spread":"^6.26.0","babel-plugin-transform-runtime":"^6.23.0","jest":"^22.4.3","sinon":"^5.0.7","axios":"^0.18.0","react":"^16.2.0","react-redux":"^5.0.6","redux":"^3.7.2"},"dependencies":{"babel-core":"^6.26.3","babel-jest":"^22.4.3","babel-preset-env":"^1.7.0","regenerator-runtime":"^0.11.1"},"gitHead":"8efecbc24fe47735b525eb9c60273333c4175847","bugs":{"url":"https://github.com/compozed/redux-delux/issues"},"homepage":"https://github.com/compozed/redux-delux#readme","_id":"@compozed/redux-delux@0.2.0","_npmVersion":"6.1.0","_nodeVersion":"10.5.0","_npmUser":{"name":"joshmcguigan","email":"joshmcg88@gmail.com"},"dist":{"integrity":"sha512-BwLyUoIbpt1nJNQ8LjWlNhvVFW4eR46hfPlggOX+xKyaQ08fhcxzDXaKL2C3N8qw/myvsrNUv7IAR2L/dfwIaw==","shasum":"83414d37237b78825c61cf579dcae2f4d0cd1578","tarball":"https://registry.npmjs.org/@compozed/redux-delux/-/redux-delux-0.2.0.tgz","fileCount":23,"unpackedSize":63480,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcP3EcCRA9TVsSAnZWagAAeIAP/3TqUO2nPirRmpHcf4Nv\nVTfUnZ6i5t1f2JQ+Ca6UT6OkygAkPXoZI/dGfJLk9ZFyQibs3M0F7F7KYKyx\nBg1t9EN0h/i+J8jyz+l6R6TyLpKjtYi6j2jWIXPG1AR0CsAm3gY9iQy2ADst\n416rkeW4qsoAARZGaaz4NjmihgwH/7Mg7TNXf9YqI3dpTGIf0YDp6GlMRzbI\nevgfRY4OckkAbL3nSBKLK1tJr74fibAFc01QAZC3Ob4+mYni7jQAtaYeOsOG\nXkPhgBFwRMxXfLwIpRUI6JSvcZFSqhoUDczZVu3QF07ZXe4IA5J8w6YCWfZm\nwf0m7r2cXDs1dPRp4oW9at7+Leb+AA9bNfda9lU8hHwu5hAaH9+0uj5yAwdc\n2WA5J71lHUw+r5RGrIRokJFSHnz0SaJvR2jLmkjQ1wyMTbxtCNLXDgxWdg6R\nCsDG4jPoBlvkIOAHWdpwWGLr5fClygNCi6VqAT8CU9GtdsgIFNe4qC/TVAh1\nGGb03b4NPmr/PobMsoIQG1sL2PIfQiQPkNPMlEixzOcyHtgvsE/FtjyjW6ww\nIu95ef5XQLcAbLbMt7arr2amX+89+JqLU3YIhw9dW9TquSp153B3s5K0ch3y\nYvmHuS7nQg9OdKYAyWyWZAdl69okxotNKZWVMZao12lwY1ENP6Am7WraeC7O\nM2m0\r\n=J3CU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFSdpxi2nylJErcsOhjDBN+cWpXbzXT6ZKLwScoT6ZEgAiAc7YU1s6yMuL4FsdQI2+iSriEeWmbKE148c3MbF1AudA=="}]},"maintainers":[{"email":"joshmcg88@gmail.com","name":"joshmcguigan"},{"email":"trayoda@gmail.com","name":"trayo"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/redux-delux_0.2.0_1547661596089_0.8563225988424314"},"_hasShrinkwrap":false}},"time":{"created":"2018-09-14T17:04:22.748Z","0.1.0":"2018-09-14T17:04:22.998Z","modified":"2022-04-05T00:42:32.797Z","0.2.0":"2019-01-16T17:59:56.233Z"},"maintainers":[{"email":"joshmcg88@gmail.com","name":"joshmcguigan"},{"email":"trayoda@gmail.com","name":"trayo"}],"description":"Manage RESTful API transactions without the boilerplate","homepage":"https://github.com/compozed/redux-delux#readme","repository":{"type":"git","url":"git+https://github.com/compozed/redux-delux.git"},"bugs":{"url":"https://github.com/compozed/redux-delux/issues"},"license":"MIT","readme":"# redux-delux\n\nredux-delux eliminates the boilerplate typically required to manage RESTful API transactions within a React/Redux application. Using redux-delux, you get Redux-like access to the data recieved from your API (along with metadata like loading and error status), all without writing a single reducer or action creator.\n\n### Redux store setup\n\nIf you don't need to setup any of your own reducers, you can setup the redux store with rr.reducers.\n\n```js\n   import rd from 'redux-delux';\n   \n   export default(initialState) => {\n     return createStore(\n       rr.reducers,\n       initialState,\n       applyMiddleware(...middleware)\n     );\n   }\n   \n```\n\nIf you want to setup your own reducers, you can use rr.combineReducers.\n\n```js\n   import rd from 'redux-delux';\n   \n   export default(initialState) => {\n     return createStore(\n       rr.combineReducers({myData: myReducer}),\n       initialState,\n       applyMiddleware(...middleware)\n     );\n   }\n   \n```\n\n### API setup\n\nThe redux-delux API for a project is defined as an object with request and task keys.\n\n```js\n    export default {\n        request: {\n          getItems,\n          getItemsForUser\n        },\n        task: {\n          createItem,\n          deleteItem\n        }\n    };\n``` \n\n#### Request\n\nRequests are used get data from an API. Requests store the status (loading, error, response data) of the most recent call (in the requestStatus object in the store).\n\nAPI requests can be defined either by a URL (string)\n\n```js\n    import rd from 'redux-delux';\n    \n    export default rr.apiRequest('/items');\n```\n\nor by a function that returns a URL (string)\n\n```js\n    import rd from 'redux-delux';\n    \n    const getItemsForUser = (userId) => {\n        return `/items/user/${userId}`;\n    };\n    \n    export default rr.apiRequest(getItems);\n```\n\n#### Task\n\nTasks are used to take an action (typically via an API). The status (loading, error, success) is saved for every task, but tasks do not automatically manage response data.\n\nAPI tasks are defined by a function which returns an array of sub-tasks (functions). The example below will create a new item for a user, and then re-request the item list for that same user.\n\n```js\n    import rd from 'redux-delux';\n    import getItemsForUser from \"../getItemsForUser\";\n    import axios from 'axios';\n    \n    export const createItem = (userId, itemId, itemName, dispatch) => {\n        const url = `/items`;\n        const subTask1 = () => axios.post(url, {id: itemId, name: itemName, userId});\n        const subTask2 = () => getItemsForUser.request(userId)(dispatch);\n        return [subTask1, subTask2];\n    };\n    \n    export default rr.apiTask(createItem);\n\n```\n\nEach sub-task receives an array containing the results of all previous sub-tasks as an argument. This makes it possible to update existing data in the store with the response of this task (such as a POST's response).\n\n```js\n    import rd from 'redux-delux';\n    import getItems from \"../getItems\";\n    import axios from 'axios';\n    \n    export const createItem = (itemName, dispatch) => {\n        const url = `/apps`;\n        const subTask1 = () => axios.post(url, {name: itemName});\n        const subTask2 = (previousSubTaskResults) => getItems.patch(dispatch,\n            (existingData)=> {\n                const items = existingData;\n                const newItem = previousSubTaskResults[0].data;\n                const updatedItems = [...items, newItem];\n                return updatedItems;\n            }\n        );        \n        \n        return [subTask1, subTask2];\n    };\n    \n    export default rr.apiTask(createItem);\n\n```\n\nAs of version `0.2.0`, it is possible to pass an optional second argument to `rr.apiTask` in order to enable storing the reponse data. The second argument should be a function which takes an array and returns the data you want to store as associated with that task. The array contains the results of each sub-task. \n\n### redux-delux within React components\n\n#### connect\n\nThe redux-delux api can be injected into React components using connect. As with react-redux, 'mapStateToProps' and 'mapDispatchToProps' are optional arguments. \n\n```js\n    import rd from 'redux-delux';\n    import api from './api'; // as defined above\n    \n    rr.connect(api, mapStateToProps, mapDispatchToProps)(Component)\n```\n\n#### usage\n\nA connected component will be injected by react-redux with the following props (based on the API definition shown above).\n\n```js\n    this.props = {\n        request:{\n            getItems,\n            getItemsForUser\n        },\n        requestStatus: {\n            getItems,\n            getItemsForUser\n        },\n        task: {\n            createItem,\n            deleteItem\n        },\n        taskStatus: function taskStatus(taskId){}\n    }\n```\n\n##### request\n\nrequest object is used to make a network request for data.\n\n```js\n    import rd from 'redux-delux';\n    \n    class App extends Component {\n    \n      componentDidMount(){\n          this.props.request.getItemsForUser('userId-123')\n      }\n    \n      render() {\n          return (\n              <p>My React App</p>\n          );\n      }\n    }\n    \n    rr.connect(api)(App)\n```\n\n##### requestStatus\n\nrequestStatus object is used to get the results of a request network call.\n\n```js\n    import rd from 'redux-delux';\n    \n    class App extends Component {\n    \n      componentDidMount(){\n          this.props.request.getItemsForUser('userId-123')\n      }\n    \n      render() {\n      \n          const userItems = this.props.requestStatus.getItemsForUser('userId-123');\n      \n          return (\n            {\n                userItems.isLoading &&\n                <p>Loading user data..</p>\n            }\n            {\n                userItems.data &&\n                <p>User data loading complete</p>\n            }      \n            <p>My React App</p>\n          );\n      }\n    }\n    \n    rr.connect(api)(App)\n```\n\n##### task\n\ntask object is used to execute a redux-delux task.\n\n```js\n    import rd from 'redux-delux';\n    \n    class App extends Component {\n    \n      componentDidMount(){\n          this.props.request.getItemsForUser('userId-123')\n      }\n    \n      render() {\n      \n          const userItems = this.props.requestStatus.getItemsForUser('userId-123');\n      \n          return (\n            {\n                userItems.isLoading &&\n                <p>Loading user data..</p>\n            }\n            {\n                userItems.data &&\n                <p>User data loading complete</p>\n            }      \n            <p>My React App</p>\n            <button onClick={()=>{this.props.task.createItem('New Item Title')}}/>\n          );\n      }\n    }\n    \n    rr.connect(api)(App)\n```\n\n##### taskStatus\n\ntaskStatus object is used to review the status of a task.\n\n```js\n    import rd from 'redux-delux';\n    \n    class App extends Component {\n    \n      constructor(){\n        super();\n        this.state = {taskId: ''}\n      }\n    \n      componentDidMount(){\n          this.props.request.getItemsForUser('userId-123')\n      }\n      \n      createItem = async () => {\n        const id = await this.props.task.createItem('New Item Title');\n        this.setState({taskId: id});\n      }\n    \n      render() {\n      \n          const userItems = this.props.requestStatus.getItemsForUser('userId-123');\n          const taskStatus = this.props.taskStatus(this.state.taskId);\n      \n          return (\n            {\n                userItems.isLoading &&\n                <p>Loading user data..</p>\n            }\n            {\n                userItems.data &&\n                <p>User data loading complete</p>\n            }      \n            <p>My React App</p>\n            <button onClick={this.createItem}/>\n            {\n                taskStatus.isLoading &&\n                <p>Adding item...</p>\n            }\n            {\n                taskStatus.success &&\n                <p>Item Added</p>\n            }\n          );\n      }\n    }\n    \n    rr.connect(api)(App)\n```\n\n##### Using redux-delux outside of React components\n\nStatus can be used to get the results of a network call. You must first pass the root state into the status function, and then call it with the arguments that are specified when the api request was setup.\n\n```js\n    // selectors.js\n\n    export const selectorCoolItems = (state) => {\n    \n        const userId = state.uiState.userId;\n        const itemsForUser = api.request.getItemsForUser.status(state)(userId);    \n        \n        // derive new data\n        return itemsForUser.data.filter(item => (item.coolness > 10) );\n    }\n```\n\n\n### watch out\n\n- redux-delux uses _rr key in the root of the redux store\n- redux-delux uses request, requestStatus, task, and taskStatus in this.props for connected components\n- redux-delux uses redux actions with types starting with _rr \n\n\n","readmeFilename":"README.md"}