{"_id":"studiokit-net-js","_rev":"110-e771a426a61e331a3a2bac428b68ca65","name":"studiokit-net-js","time":{"modified":"2023-02-16T19:13:56.905Z","created":"2017-05-23T14:43:30.153Z","0.0.9":"2017-05-23T14:43:30.153Z","0.0.8":"2017-05-23T14:53:19.705Z","0.0.10":"2017-05-23T14:54:16.712Z","0.0.11":"2017-05-23T14:55:47.527Z","0.0.12":"2017-05-23T15:08:13.027Z","0.0.13":"2017-05-23T22:56:09.269Z","0.0.14":"2017-06-07T20:56:05.814Z","0.0.15":"2017-06-08T16:21:03.866Z","0.0.16":"2017-06-10T03:46:54.251Z","1.0.0":"2017-06-13T19:24:47.311Z","1.0.1":"2017-06-15T19:08:22.579Z","1.0.2":"2017-06-15T20:27:22.470Z","1.0.3":"2017-06-15T20:39:45.891Z","1.0.4":"2017-06-15T21:06:01.902Z","1.0.5":"2017-06-15T22:16:53.189Z","1.0.6":"2017-06-27T17:41:22.584Z","1.0.7":"2017-07-07T13:49:21.970Z","1.0.9":"2017-09-05T15:15:26.314Z","1.1.0":"2017-09-26T20:56:38.996Z","1.1.1":"2017-09-27T14:06:20.746Z","1.1.2":"2017-09-27T14:41:46.007Z","1.1.3":"2017-09-27T14:53:55.156Z","1.2.0":"2017-10-11T17:27:03.541Z","1.2.1":"2017-10-19T14:58:22.028Z","1.3.0":"2017-10-24T21:09:15.198Z","1.3.1":"2017-10-25T15:38:22.481Z","1.4.0":"2017-10-31T13:45:05.441Z","1.4.1":"2017-10-31T14:58:17.595Z","1.4.2":"2017-10-31T19:04:18.156Z","1.4.3":"2017-11-02T15:19:53.481Z","1.4.4":"2017-11-02T19:55:31.115Z","1.4.5":"2017-11-08T22:11:48.651Z","1.4.6":"2017-11-14T20:54:28.680Z","1.4.7":"2017-11-17T20:39:21.923Z","1.4.8":"2017-11-30T20:52:29.992Z","1.4.9":"2017-11-30T21:00:36.326Z","1.4.10":"2017-12-12T21:57:08.101Z","1.4.11":"2018-01-11T20:02:12.929Z","1.4.12":"2018-01-24T20:47:25.764Z","1.4.13":"2018-01-25T20:21:42.570Z","1.4.14":"2018-01-26T16:25:41.085Z","1.4.15":"2018-01-31T15:51:02.254Z","1.4.16":"2018-01-31T23:09:58.742Z","1.4.17":"2018-02-02T16:24:32.383Z","1.4.18":"2018-02-28T16:22:59.711Z","1.4.19":"2018-03-08T19:12:32.373Z","1.4.20":"2018-04-04T20:58:34.716Z","1.4.21":"2018-06-06T19:59:14.000Z","1.4.22":"2018-06-15T14:33:54.676Z","1.5.0":"2018-07-19T16:07:50.487Z","1.5.1":"2018-08-14T21:50:02.080Z","1.5.2":"2018-09-27T17:26:58.523Z","1.5.3":"2018-11-09T18:00:39.344Z","2.0.0":"2019-02-12T18:30:03.027Z","3.0.0":"2019-03-12T13:41:09.838Z","3.0.1":"2019-03-13T13:22:20.999Z","3.0.2":"2019-03-21T15:11:48.191Z","3.0.3":"2019-03-21T20:06:53.275Z","3.0.4":"2019-03-26T19:05:13.182Z","3.0.5":"2019-05-29T15:39:09.178Z","2.0.1":"2019-10-01T17:56:48.315Z","3.0.6":"2019-10-01T17:58:24.082Z","3.0.7":"2019-10-16T20:25:04.262Z","3.0.8":"2020-10-22T20:50:16.605Z","3.0.9-alpha.1":"2020-10-29T13:53:30.287Z","3.0.9-alpha.2":"2020-10-29T17:47:26.601Z","3.0.9-alpha.3":"2020-10-29T20:32:52.864Z","3.0.9-alpha.4":"2020-10-29T21:28:14.514Z","3.0.9":"2020-11-02T14:24:05.515Z","3.0.10-alpha.1":"2020-11-04T18:13:18.235Z","3.0.10-alpha.2":"2020-11-04T18:22:56.328Z","3.0.10":"2020-11-05T19:45:02.972Z","4.0.0-alpha.1":"2021-01-21T21:21:56.812Z","4.0.0":"2021-01-27T13:51:11.676Z","4.0.1":"2021-01-28T22:31:09.436Z","4.0.2-alpha.1":"2021-06-23T12:27:35.930Z","4.0.2":"2021-06-23T17:59:57.174Z","4.0.2-next.1":"2021-12-15T20:39:13.923Z","4.0.2-next.2":"2021-12-15T20:44:06.816Z","4.0.2-next.1.3":"2021-12-15T22:17:44.633Z","4.1.0":"2021-12-16T19:04:33.991Z","4.1.1":"2021-12-20T19:52:20.219Z","4.1.1-next.1.1":"2022-01-06T14:12:57.656Z","4.1.1-next.1.2":"2022-01-06T14:33:04.118Z","4.1.2":"2022-01-11T17:15:40.844Z","4.1.3":"2022-06-17T20:54:56.561Z","4.1.4-alpha.1":"2023-02-16T15:19:22.415Z","4.1.4-alpha.2":"2023-02-16T17:56:48.095Z","4.1.4-alpha.3":"2023-02-16T18:25:04.399Z","4.1.4":"2023-02-16T19:13:56.755Z"},"maintainers":[{"name":"lane174","email":"lane174@purdue.edu"},{"name":"wgrauvog","email":"wgrauvog@purdue.edu"},{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"dist-tags":{"latest":"4.1.4","next":"4.1.4-alpha.3"},"description":"Network/API functions for Studio apps at Purdue","readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","versions":{"0.0.10":{"name":"studiokit-net-js","version":"0.0.10","scripts":{"build":"babel src -d lib","build:watch":"babel src --watch -d lib","test":"mocha --require babel-polyfill --require isomorphic-fetch --compilers js:babel-core/register 'src/**/__tests__/*'","test:watch":"mocha -w --require babel-polyfill --require isomorphic-fetch --compilers js:babel-core/register 'src/**/__tests__/*'","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-transform-flow-strip-types":"^6.22.0","chai":"^3.5.0","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","immutable":"^3.8.1","isomorphic-fetch":"^2.2.1","mocha":"^3.3.0","pre-git":"^3.14.0","rewire":"^2.5.2"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"_id":"studiokit-net-js@0.0.10","dist":{"shasum":"66f65839dd922d60b428823b9e1ad44ef254c41b","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-0.0.10.tgz","integrity":"sha512-+n42ZOeLMQiFAOQRO4QVyTa+22kKxpK0OTByxZCvM42XoNn6+5U3k6eyTELXHW0yCcWw/wLefUzp8oA37yP7cA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHp/44laP5BDdeWf5imNfyAUkPw23gkT4ZHdgf8dMpIgAiAxcYSwSp9tET6UmJi7y6C7XytRNb4CFRJUN5jOyN8ShQ=="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-0.0.10.tgz_1495551255736_0.07108825072646141"},"directories":{}},"0.0.11":{"name":"studiokit-net-js","version":"0.0.11","scripts":{"build":"babel src -d lib","build:watch":"babel src --watch -d lib","test":"mocha --require babel-polyfill --require isomorphic-fetch --compilers js:babel-core/register 'src/**/__tests__/*'","test:watch":"mocha -w --require babel-polyfill --require isomorphic-fetch --compilers js:babel-core/register 'src/**/__tests__/*'","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-transform-flow-strip-types":"^6.22.0","chai":"^3.5.0","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","immutable":"^3.8.1","isomorphic-fetch":"^2.2.1","mocha":"^3.3.0","pre-git":"^3.14.0","rewire":"^2.5.2"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"_id":"studiokit-net-js@0.0.11","dist":{"shasum":"e02a87c50d2442c275ecc161f3d6cde032edbf9a","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-0.0.11.tgz","integrity":"sha512-Hg/86lmqV3WTy5s8eyREZrp7PD7IT921dEPn2tL8t0bGtGRp7DqetY22f7n0eUGxFZJIhqSws2dDWLJdTbxuqA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCWC8z4xuozftOyJsBNIZu6fI4+dpAY5CMkOsAu47gEfwIgOPoLabWmrVWl5Q77UgdGRgtXfSDhGeuI5a3MNCCkpY4="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-0.0.11.tgz_1495551346565_0.09546618419699371"},"directories":{}},"0.0.12":{"name":"studiokit-net-js","version":"0.0.12","scripts":{"build":"babel src -d lib","build:watch":"babel src --watch -d lib","test":"mocha --require babel-polyfill --require isomorphic-fetch --compilers js:babel-core/register 'src/**/__tests__/*'","test:watch":"mocha -w --require babel-polyfill --require isomorphic-fetch --compilers js:babel-core/register 'src/**/__tests__/*'","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-transform-flow-strip-types":"^6.22.0","chai":"^3.5.0","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","immutable":"^3.8.1","isomorphic-fetch":"^2.2.1","mocha":"^3.3.0","pre-git":"^3.14.0","rewire":"^2.5.2"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"_id":"studiokit-net-js@0.0.12","dist":{"shasum":"40819286926879a6476ea1f49a3b10151dca819c","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-0.0.12.tgz","integrity":"sha512-lm9eM4h3CglFWuvROURkCZDcYTo9ikH/ujT8S385B5e6JreOEjLq8uUno+gRUEpzHwaYQgRL1UifTKaK4QS33A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDMYwXLgk77nr8UAzk80GOl3+5kfGAEgahkhGBaqlnuzAIgMAp8z+ErVjcdW/xwMksLiLqHPd8N4T8N34ot50I7WYo="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-0.0.12.tgz_1495552092071_0.7852561324834824"},"directories":{}},"0.0.13":{"name":"studiokit-net-js","version":"0.0.13","scripts":{"build":"babel src -d lib","build:watch":"babel src --watch -d lib","test":"mocha --require babel-polyfill --require isomorphic-fetch --compilers js:babel-core/register 'src/**/__tests__/*'","test:watch":"mocha -w --require babel-polyfill --require isomorphic-fetch --compilers js:babel-core/register 'src/**/__tests__/*'","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-transform-flow-strip-types":"^6.22.0","chai":"^3.5.0","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","immutable":"^3.8.1","isomorphic-fetch":"^2.2.1","mocha":"^3.3.0","pre-git":"^3.14.0","rewire":"^2.5.2"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"_id":"studiokit-net-js@0.0.13","dist":{"shasum":"22036c3c4067c11c7ae6e4165f45d98ba71f73de","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-0.0.13.tgz","integrity":"sha512-/KwybHb6f7r6UprmaxgSrpanNokfkE1KhrIC0KETk5GrKa/m+e6HZRQZjFkLpVY2hxDiolyAcnNRDpzAE0GRxQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFYJ8thCbUurJUu25w8eFcJOhMjJmCSmhXj5CekrXp3xAiA9c/VLbh29vR9CWMtDEJnCJLNuGHLpj2kMl/RZByey0g=="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-0.0.13.tgz_1495580168123_0.9102932098321617"},"directories":{}},"0.0.14":{"name":"studiokit-net-js","version":"0.0.14","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"jest","test:watch":"jest --watch","coverage":"jest --coverage","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"4bbcea21b709f306d0316f342751a2f41891e294","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@0.0.14","_shasum":"7512341b6fa36ccc28b381c3090c99e99fc832fb","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.10.3","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"7512341b6fa36ccc28b381c3090c99e99fc832fb","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-0.0.14.tgz","integrity":"sha512-4qlmYozhpD3bCZkF3RiK5aqK4lPAqVg7jn7BsxgOzHWo+hO6WCdOVQXUhk44ycttWJzv9oP7tpsbMrOv1kJTLw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC0pqYfE6taQoLBIw1BxQVFdx1FnK7MC/qVop6zlsNu4wIhAMTaHAoY9mzUs+NWwesVCOCLjcEPLzcjRfCBdiIMscTD"}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-0.0.14.tgz_1496868964571_0.7703259938862175"},"directories":{}},"0.0.15":{"name":"studiokit-net-js","version":"0.0.15","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"139ce9e5b54529b4b669d4a2a9534829778d86ac","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@0.0.15","_shasum":"00fafa0e8382d2a26c72b19c1a53c37997b624e6","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.10.3","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"00fafa0e8382d2a26c72b19c1a53c37997b624e6","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-0.0.15.tgz","integrity":"sha512-pbUverBkk4O2BCTbvy60oWMAYCjhVe/DjEwJbw+X6zmV76cdeotTBPROoXNTXV6ZxLwwLKDb3Oqc+JC7zvC3bQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD38OZrePOViegnAhbTt9x4Iy8P2/pnG+i/ueOn8If7EQIgI8i2IAN9ayLWwE56vtwlV+6yYps7k9+mCvmxci/+LEE="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-0.0.15.tgz_1496938862590_0.7883981342893094"},"directories":{}},"0.0.16":{"name":"studiokit-net-js","version":"0.0.16","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"78d673905d4135ca91791d6dbf628244f95764f5","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@0.0.16","_shasum":"8d1b8abe4fe9ac534e2331562c8ffb77ac23f9fa","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.10.3","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"8d1b8abe4fe9ac534e2331562c8ffb77ac23f9fa","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-0.0.16.tgz","integrity":"sha512-uA0mepXdRDWU9oQmvTBta1hG3kIeRouOZCl6d5La/mNVQZBgDcISNhDvMbPZxM4eFH4EgvcyPlwUJ8hgyhPlRw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICmriF9gJ5J0xztDvyk+7X1ID3SCK0i9xz/uDZh1mhKGAiEAk+jaG3gECISZDN+LlphWDpOYMzlhUrV/C1nOXJ6zJ8s="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-0.0.16.tgz_1497066413058_0.737799588823691"},"directories":{}},"1.0.0":{"name":"studiokit-net-js","version":"1.0.0","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"62ec9e5b19834e366634bdadf516bd24af535d6c","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.0.0","_shasum":"cf136a51195864a028d1a690526d0e90ed27f840","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.10.3","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"cf136a51195864a028d1a690526d0e90ed27f840","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.0.0.tgz","integrity":"sha512-OTUNBb6GJuIpzAU9t1iZFTUCuIaEG/dmO7C5D+89NeU2TUWnFJqPHo5w2JhJSkSELDcenbub8/ZZMnQpZjib5w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQJse1w9Qn+TNnRNKMa8Z/Qu6olmH9INzGVh2Ws64RCQIgGlhFgj3/p/Bi/7LKEsumAWAVs9/vdZUd8pAUy197G70="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.0.0.tgz_1497381886101_0.4576445419806987"},"directories":{}},"1.0.1":{"name":"studiokit-net-js","version":"1.0.1","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"BABEL_ENV=test jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","coveralls":"^2.13.1","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"345facf4f159f36d942f09d8061004ca38cae604","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.0.1","_shasum":"409529afec904da468fb189146d535d9cdd8cfa8","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.10.3","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"409529afec904da468fb189146d535d9cdd8cfa8","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.0.1.tgz","integrity":"sha512-7ou3S0ZhLnYpmbo+0OBJ58ozxUzzim1KsVeU6EMKr2HV/H3K7WXfpkUFaLQizDEpgBDixI7MOka2j/jWtTwxJw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDPu6ia1Om9V0Gy9Gtilr64qjwcx+XdQocdcOeUpB6GVQIgHtqsCg91MRmlrRdNG3OrsW0PCqCWaflkumcdMh/8ejk="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.0.1.tgz_1497553701124_0.8401781374122947"},"directories":{}},"1.0.2":{"name":"studiokit-net-js","version":"1.0.2","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"BABEL_ENV=test jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","coveralls":"^2.13.1","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"b97f4d17d9cb91a22ce9de3495b17cc64466d9fa","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.0.2","_shasum":"4419e0deff92e0aff3dfe3c7e39b705e2dfbddd9","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.10.3","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"4419e0deff92e0aff3dfe3c7e39b705e2dfbddd9","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.0.2.tgz","integrity":"sha512-xjWAlwGQMcGQT67sjk/cKq4pvUsoT4AmlDNEDNfRyhuE1FFj36SlO3taEumfpWzzDgm1UWNurqIMcp1PpAGohQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBiNaUEvZz2wuq5503v/gYkFpY65P/ZpXHFJNhdWNkSKAiEA9pgkTBQxwASG8N09OVwon9ugnHAqmz9yLWdwG9p6ADA="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.0.2.tgz_1497558441254_0.344699130859226"},"directories":{}},"1.0.3":{"name":"studiokit-net-js","version":"1.0.3","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"BABEL_ENV=test jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","coveralls":"^2.13.1","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"c463f4897f2b5edf6a5f28c17d538f539f582dce","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.0.3","_shasum":"2f26d40256621070c4ac0458c74b3273bd49ed30","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.10.3","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"2f26d40256621070c4ac0458c74b3273bd49ed30","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.0.3.tgz","integrity":"sha512-EgMsvODhCVoAlB6A82PQD9skxfKPbkGB43JM/TUnxDWJ46irrhStJ5sb9t0y6ooBVs12ymtrdO633gBbAoziMA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFlhSs4few7FB0lbKGC++a0G2tAjQQbt+VU5GbJTFMcjAiAWcgZ1k0eA8aJkgUDJ7Jat7SOVfZ7jSeY9a5FM21rr6A=="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.0.3.tgz_1497559184700_0.44961888808757067"},"directories":{}},"1.0.4":{"name":"studiokit-net-js","version":"1.0.4","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"BABEL_ENV=test jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","coveralls":"^2.13.1","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"ad15c94792ea7d7fbc4fec91400e936d7cd6bac9","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.0.4","_shasum":"ebc15b96d1c36e04bcb4aafcc9feecc7b5c0a011","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.10.3","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"ebc15b96d1c36e04bcb4aafcc9feecc7b5c0a011","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.0.4.tgz","integrity":"sha512-JI4r0it/k9A6wTyxYbseRj/PYJm061rRHvTFl+7mmEMhdAk3pWEG4P/4g9gEQM0/mYlSmI5ShXXO60JXb2GF8w==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDbPLhL3BMV/i7RFnCW3eBWj1SDkMu8nItx05zTpBCiCwIgaeZUIQHGkiivVr6tXxE+PSmbGM95a0c4ja4LsN5mARs="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.0.4.tgz_1497560760637_0.7023346002679318"},"directories":{}},"1.0.5":{"name":"studiokit-net-js","version":"1.0.5","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"BABEL_ENV=test jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","coveralls":"^2.13.1","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"a491eb108a64e5bb8321ee56bae45be54465d010","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.0.5","_shasum":"1131ec38df05e2a7eeae718ea9a2a3af3bb07771","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.10.3","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"1131ec38df05e2a7eeae718ea9a2a3af3bb07771","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.0.5.tgz","integrity":"sha512-b33WQ4juov2D7mmEyAJbKjb5ThS8jtKtkIDWhmXg4u8knzZfQvs+WibRlhhOEFslwbztRp3Xu4bQ2Ej718ALpQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCJFpE7ZGzr32f+8Xnjm6pgycIwXQYkfajH3S6Fkcl0+AIhANRnPtZSZtbh+kXTXtyJGIyHTBg7n9CDMPjPXFGe2+M1"}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.0.5.tgz_1497565011825_0.40533673320896924"},"directories":{}},"1.0.6":{"name":"studiokit-net-js","version":"1.0.6","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"BABEL_ENV=test jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","coveralls":"^2.13.1","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"da0be12cf9748bde2e1eb9dac941d6efd7ce9472","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.0.6","_shasum":"ec2b19c0f45340a6f105a4361d44169a18206db0","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.10.3","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"ec2b19c0f45340a6f105a4361d44169a18206db0","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.0.6.tgz","integrity":"sha512-+UlcF/n0xqhowzzQ9IHqLe+WcZJ3jnEzyLwLsPfysluXa1tq4mcSL8N+uXIM8p12WOBtj/y8ETGExTg0LWzmOg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD0BAHE3Cr9qfao+REgOh03juT/cIHCvUJTlDZd4GwMwQIgNOofEwOstQrjLVpZSHclMbbpgTTvbnAHOsK0tmVyqqg="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.0.6.tgz_1498585281320_0.8895188227761537"},"directories":{}},"1.0.7":{"name":"studiokit-net-js","version":"1.0.7","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"BABEL_ENV=test jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","coveralls":"^2.13.1","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"4a70e02e57e66b6adccd27c4efaed77c44b6d8c5","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.0.7","_shasum":"3a22c1312c2d54a7c8b08a3edbb06214cf5de48c","_from":".","_npmVersion":"4.6.1","_nodeVersion":"6.11.0","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"shasum":"3a22c1312c2d54a7c8b08a3edbb06214cf5de48c","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.0.7.tgz","integrity":"sha512-jFGK7ObKjmPC573TsQ+y1D/TILgZ01YXlhNwzmFtzq21vXvFzVwEaNqR+YUJhpcCAcsMDEY1rJAORoWDSv6pdw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDqxWr82Iy2p9RNRgDHRCAfZo+nzO3C/P5zRbfOpx+VmAIge77vPaLzoxvFO5o0NvlzKUn/WW5rTBp80rL8VDg1Cio="}]},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.0.7.tgz_1499435360515_0.16946198558434844"},"directories":{}},"1.0.9":{"name":"studiokit-net-js","version":"1.0.9","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"BABEL_ENV=test jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","coveralls":"^2.13.1","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"953b5adb67fcd0ead47a1236d8a008bd1fbfa43e","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.0.9","_npmVersion":"5.3.0","_nodeVersion":"8.1.2","_npmUser":{"name":"tragessere","email":"tragessere@gmail.com"},"dist":{"integrity":"sha512-N8cYrIZv0VDgdfGsuFwT+pySe1/u12OJjGKQmAIMMsJ51erQdKy+qrGiQYdNcFKerBwkXoI2boLrCJR8iUvUAw==","shasum":"33320e33d3bc362e1c861e8bbd46aee1f02169bd","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.0.9.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCmeIOFrM12DzDYv8lXK5U6W0+/IXEOMqCKxpkz5EUa5AIhAOO5N7O58XgbQWE3N6oWTmJNnSyduvC9CW0smrH+qaZ2"}]},"maintainers":[{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.0.9.tgz_1504624525183_0.6778354097623378"},"directories":{}},"1.1.0":{"name":"studiokit-net-js","version":"1.1.0","scripts":{"build":"babel src -d lib --ignore '**/*.spec.js'","build:watch":"babel src --watch -d lib --ignore '**/*.spec.js'","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"BABEL_ENV=test jest --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js","commit":"commit-wizard"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"author":{"name":"Jason Dufair","email":"jase@purdue.edu"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","coveralls":"^2.13.1","eslint":"^3.19.0","eslint-plugin-redux-saga":"^0.3.0","fetch-mock":"^5.10.0","flow-bin":"^0.46.0","isomorphic-fetch":"^2.2.1","jest":"^20.0.4","pre-git":"^3.14.0"},"dependencies":{"babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"config":{"pre-git":{"commit-msg":"simple","pre-commit":["yarn babel -- src -d lib"],"pre-push":[],"post-commit":[],"post-checkout":[],"post-merge":[]}},"jest":{"testPathIgnorePatterns":["/node_modules/","<rootDir>/lib/"]},"gitHead":"8d42ec44ce3950ff1056f9f142e680c8033b73c1","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.1.0","_shasum":"35934dbb5a4f1c3f256638d0ca0cd992ec8f8899","_from":".","_npmVersion":"4.1.2","_nodeVersion":"7.2.0","_npmUser":{"name":"acamliu","email":"alexcamliu@gmail.com"},"dist":{"shasum":"35934dbb5a4f1c3f256638d0ca0cd992ec8f8899","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.1.0.tgz","integrity":"sha512-Jxecd0trXx54uhSAcSAn0GOWNUT7lZ8jW/qamLYADjik4xo/Chi+IFLMnsjoypEfGvStvGOYCdLrReGPjBhVAA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHa8dwfnbE99HmLTO3jmBnuHKXRbiz9fWowStILlpGzkAiEAx+I6xli7W00Cg0hCVQHekhHqoVuKfQlWNz7OmFkZvFY="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.1.0.tgz_1506459397819_0.43859576783142984"},"directories":{}},"1.1.1":{"name":"studiokit-net-js","version":"1.1.1","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","pretest":"npm run build","prepush":"npm run test","prepublish":"npm run test"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","coveralls":"^2.13.1","eslint":"^4.7.2","eslint-config-prettier":"^2.5.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.10.0","flow-bin":"^0.55.0","husky":"^0.14.3","isomorphic-fetch":"^2.2.1","jest":"^21.1.0","lint-staged":"^4.2.2","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"9193e9380c52fed1fdc1f705b69c02c967aab11b","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.1.1","_shasum":"27b0754d8e6ea16e552fe16e2454d0dd1c43b0d3","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.1.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"shasum":"27b0754d8e6ea16e552fe16e2454d0dd1c43b0d3","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.1.1.tgz","integrity":"sha512-Lzzp0YDhgGsWLf6C/CfMEgBbTxxlZYd9GAwWJc8V73XawwxINNS2gvoAzdu6MH4XRdsutpFZUS8XpLJdQk8bLQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDBJMu+1xDFP/B43sdLYkWxT4UXa0niE7YG4gm/6ShIFQIgR73+HV2svHLwPwZmmn/HJU6W2//DLPX0JKck/b2YNlo="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.1.1.tgz_1506521179564_0.13301640679128468"},"directories":{}},"1.1.2":{"name":"studiokit-net-js","version":"1.1.2","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","pretest":"npm run build","prepush":"npm run test","prepublish":"npm run test"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"babel-cli":"^6.24.1","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","coveralls":"^2.13.1","eslint":"^4.7.2","eslint-config-prettier":"^2.5.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.10.0","flow-bin":"^0.55.0","husky":"^0.14.3","isomorphic-fetch":"^2.2.1","jest":"^21.1.0","lint-staged":"^4.2.2","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"65e059a09bb10dc0999a0b4230c4747689775049","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.1.2","_shasum":"77b44c9ff83f66cdec1cf34485c5893b60cb30f5","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.1.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"shasum":"77b44c9ff83f66cdec1cf34485c5893b60cb30f5","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.1.2.tgz","integrity":"sha512-Q5sifMtvOiODva8Y1QNxxbTSM3fmMxmuGfH4uTw3K/4xiAwJ0h7sCUWL2JO8TdQLhaS/n1KT+pA1zn+7ELj31g==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD/f8hgpH3Yf6n7Yuv3HcxoxagEmkZaCZfhYo77zkadGwIhAJM6sdQywvJE8EMO9fDV7+ADOp75ePAO3Cy15uGu2Dsi"}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.1.2.tgz_1506523304798_0.7483712993562222"},"directories":{}},"1.1.3":{"name":"studiokit-net-js","version":"1.1.3","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"BABEL_ENV=test jest","test:watch":"BABEL_ENV=test jest --watch","coverage":"BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","pretest":"npm run build","prepush":"npm run test","prepublish":"npm run test"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","coveralls":"^2.13.1","eslint":"^4.7.2","eslint-config-prettier":"^2.5.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.10.0","flow-bin":"^0.55.0","husky":"^0.14.3","isomorphic-fetch":"^2.2.1","jest":"^21.1.0","lint-staged":"^4.2.2","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"f8af8e1a8ec8762f7784eba75fade3bb97c216b3","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.1.3","_shasum":"3a3e7f179a8124fedcc12231a0c9483a12e4b1e7","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.1.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"shasum":"3a3e7f179a8124fedcc12231a0c9483a12e4b1e7","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.1.3.tgz","integrity":"sha512-4S5z6BsWcY6cxyAJW/vvs2ewMgMx/wKU+1vp/v3hsZdgaFgsViLl4hqPevjKst5acCyEq+NCHf+etbsbBrW/2A==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIG6KRDpeZecbWNwwqHTJxlOISB5yk6O4Gaf/KisNdA0YAiBdpdRpqJh7bA4yMMA8ePqhQo5eoFGoCBhZ6PiRj1QKyg=="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.1.3.tgz_1506524034215_0.9480859364848584"},"directories":{}},"1.2.0":{"name":"studiokit-net-js","version":"1.2.0","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","pretest":"npm run build","prepush":"npm run test","prepublish":"npm run test"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.4.0","babel-runtime":"^6.23.0","coveralls":"^2.13.1","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.5.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.10.0","flow-bin":"^0.55.0","husky":"^0.14.3","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.2.2","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.1","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"4ef3320206896dee50a4c290898ae8c3a51d0c49","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.2.0","_shasum":"a7233f5dc68eb2afd58724f44fd1e52d90888121","_from":".","_npmVersion":"3.10.9","_nodeVersion":"7.1.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"shasum":"a7233f5dc68eb2afd58724f44fd1e52d90888121","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.2.0.tgz","integrity":"sha512-911sj5czjhwgPcPGhQ1tFk47Zw+XDT2XDCfVvSFLSRYbiWxuyVOd5g4D7x1fLaT54E6xEPQODWFUV0r1vmi4Bw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIF27nFoD9MKQd0bmgMFdUGbN2520R/gf9C0fQumqv5yzAiEAtTlg+CfvdHsZbZihuHXi5kpvZQyHvRM9xsx8Mm0NIEM="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.2.0.tgz_1507742822457_0.028194031678140163"},"directories":{}},"1.2.1":{"name":"studiokit-net-js","version":"1.2.1","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"cc94a685be2de91a857048d9958a8112a0245f5a","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.2.1","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-AulDm1rbP5fzuAJETtpLKJsstQ5hWvlnTq/dM8++F35Ds6sA3HfSveQ1rx4/1Z6fXyH3YK4dznVwXvEhu9eplg==","shasum":"6731409b5e10368c8b3175995852d8e4e16a4987","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.2.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNVWaQ6HtHbr4lb6KAJDhVKscawb6gYIY5arm481vq+QIhAJWc49t5rfK+wYr72lLlofW/agmWMY3XW0ByjBmqhpNn"}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.2.1.tgz_1508425101024_0.7591688290704042"},"directories":{}},"1.3.0":{"name":"studiokit-net-js","version":"1.3.0","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"6f26bc43f256ab18d8db0e00f3edfe0668516d3d","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.3.0","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-I+z4GflJBRWhWwUislSdrwlxxboLWuUpYEMdGTJsH1dmxk5CEHUiz1v5r4hg3R+13+Sta1j1HZ8+tmyheCLLIQ==","shasum":"04b83b50fbc0b90fa97c4f12486d02a556ffad45","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.3.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHNY+t4jiVUE99crKW83I9R+q/jmcX4igWwFxJRq8zQSAiEA/ZXMFrh4MFXXHFI9f1uV0cf76GaHFwtDVrorAG/E/GY="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.3.0.tgz_1508879354213_0.32492605806328356"},"directories":{}},"1.3.1":{"name":"studiokit-net-js","version":"1.3.1","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"0ba94b5e5f30cab46aba833cd50168341840907a","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.3.1","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-Sa/7rL1/N1/xj3kMQwyS1rxBY7vmHkm4uL+fgj+S0dRrA3e/RdrHzZBIZrWhtfsSkRXOQMaft4LYprXTLjyLtg==","shasum":"a7b69758d2589b709bf78cc4f60ff89bdbacf40b","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.3.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDF+GkHYtgQSs6LKfgm1UFZU/Yf//tq6aypLXr1z42R/AiEAw91kDHKigkPBGmNbd8A3OaGSQTAKsEe7aFYgVm9RljE="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.3.1.tgz_1508945901377_0.559014801401645"},"directories":{}},"1.4.0":{"name":"studiokit-net-js","version":"1.4.0","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"cce235fd8cf786f3ea604ae67a6a7e47f820cdc4","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.0","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-E4QNmXC/9Q8UNjti6mkf7V1LWcr54YX9mwmPtbxW7W41zUTIbn7LlSfo05Tlha8gOeMCruXXNj4r81wD4fol9w==","shasum":"eb064cb8d6821881cd0c299f5e5d179c82d692f2","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.0.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCAlBRIaQ2qkLhdoPUG7i/5G0Dgq7RNyOdl1a38lXsE+QIhAL+2bbSH04gsgBv3P0ER332G95vm0/jMquTo8A6/bcxZ"}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.0.tgz_1509457504388_0.7792669769842178"},"directories":{}},"1.4.1":{"name":"studiokit-net-js","version":"1.4.1","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"91f6171b47c6729b7d7e7eea0c2ffb30e16579e8","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.1","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-0WrOljw7Yt7TrbYCuNsca+adDTkQATXMF3OUpbSutMLPS+u8aO3tg/yB1SSVwEbidkHNDrIQZ/vqSm7ix6HVEg==","shasum":"c25c3d85dec4256c03282a76a22370c9ed828659","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.1.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDPFcEgg8cxw2yDk0a4zdnyJq+tCwKbv6NIPH3YWUPd6wIgTtpvfsjawgiZXScTbXYCCAB5qjBBRd10/7xGsdJCVOI="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.1.tgz_1509461896612_0.7749400124885142"},"directories":{}},"1.4.2":{"name":"studiokit-net-js","version":"1.4.2","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"e8163865c9167d559710bf941b1d04e3841529af","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.2","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-G/0biibpqCu7QuSSLWVHKC5LiVDAr1FlVLoudG2WmTJYRqUfmmabdx0IH3y/A3kDGkoJswYgf3mylzPE1DUHww==","shasum":"a387cc97c8a2f0a714bfef189e1f0a1dd5a6df06","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.2.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDeibilAOWDjg90cz2S4DK2hknueSzulO2GyFOMyV68PwIgFk+Vpi1PtXTzD9XmFTcQNtQBtY8x/7Ybq5JImw79WJ0="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.2.tgz_1509476657140_0.055010347394272685"},"directories":{}},"1.4.3":{"name":"studiokit-net-js","version":"1.4.3","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"8c41f2933b920aa1c7eeb26895a3dc3f03e847a1","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.3","_npmVersion":"5.5.1","_nodeVersion":"8.7.0","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"integrity":"sha512-HMi0nwL7Qiszd4krhvo+ZKrTGbO+Ltq9B9XVIz6uD7qxXPJZmxRtKP+LQ9sIdb4KnzwHVf+yh1r5VFWuEquU+Q==","shasum":"1c79ad0ee33c4214697a438e4d6fc49129cc978d","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.3.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID7gqRUzrTfO9ox6HEzsfSpY2CqJZoUheD9QtS1Y3X7TAiEAwb5LwaYjupUVMEs6NS6VeONPoy9bT+rb6ApWdsTVRlg="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.3.tgz_1509635992329_0.1131001973990351"},"directories":{}},"1.4.4":{"name":"studiokit-net-js","version":"1.4.4","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"48db1cc6851b2c34d1ad5a657b9ac3a88a3ac8b2","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.4","_npmVersion":"5.5.1","_nodeVersion":"8.7.0","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"integrity":"sha512-gIbvl3giqVPSVmsMaZ/DoltzcBIkeUq20Yoru9PoAQODBBF0nRWIAHEJLceq5cmwDRx+u7aolilrR/R8/YuwXQ==","shasum":"c67194e5bde371e3475ee6a6206862f192317960","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.4.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAQRAi5A9qmDjeg5ZQ4xKUXCE9pu7ktF1Qxp0QE3zPfSAiEArXr3C6r+qmcdVv8SFvmhonOuiudLN//x5DF6p2EM/kk="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.4.tgz_1509652530126_0.1038584066554904"},"directories":{}},"1.4.5":{"name":"studiokit-net-js","version":"1.4.5","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"_id":"studiokit-net-js@1.4.5","dist":{"shasum":"d0be6fcf3f4a9e194ae48f2c4be2ec09e1a871ab","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.5.tgz","integrity":"sha512-mUmot8+gRZ1F0Qrq+KsgY/FVk6AYoeeaSRfjm/EZHEwYXkp1IYtxJPM/eKnFQD4QLebwcT1rIXxFj8CeBzi0cA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFXoJJ48mDuNuJiLlSZ0L6Uo2hjoFsQdM5CQxsCN6pjjAiAfGpyo6cYavaKc01YD5n3SblwPysiG1lcfBsJTxu3NTA=="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmUser":{"name":"acamliu","email":"alexcamliu@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.5.tgz_1510179107483_0.3608550347853452"},"directories":{}},"1.4.6":{"name":"studiokit-net-js","version":"1.4.6","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"_id":"studiokit-net-js@1.4.6","dist":{"shasum":"43aee53d3eebab530eadf3801524e4da5b0a2230","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.6.tgz","integrity":"sha512-6OhCIHY7tTLsgsOpZ9zynvWPI/I0+dIV5nTAWmpmBVJa+TXs4R1+rMsnY7l9gAl24QH93qA2FhmGxYOPAGqkQQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCZ97UP5Rd1NnuwIyYmeu0j6jX4SoCKLEXnnwPko2Mn3wIgRww1Rlc+2Z9xvmiQggBCVqpbimNiuNHsyzo6JoGDIkY="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmUser":{"name":"acamliu","email":"alexcamliu@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.6.tgz_1510692867702_0.42707048170268536"},"directories":{}},"1.4.7":{"name":"studiokit-net-js","version":"1.4.7","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"_id":"studiokit-net-js@1.4.7","dist":{"shasum":"9d96bc77f310581577222cb231c220a45702de1e","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.7.tgz","integrity":"sha512-WAARnlwtEY0ALtXpwy5Odq9YWrEUoHAv71wMZGOoFIQgQVk4PE9D5DrrvESru/D1kAQTnjhIEXgJ03pkatiHew==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDG4b9JKrZwwK9AN4cZ9LeIuhAS9Fl4phOgCV8K+s8EBAiEAl5msCue2W3YWv2J0dlzSwFIPbGajI64P9Xn0hNH6Siw="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmUser":{"name":"acamliu","email":"alexcamliu@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.7.tgz_1510951160785_0.12303371564485133"},"directories":{}},"1.4.8":{"name":"studiokit-net-js","version":"1.4.8","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"_id":"studiokit-net-js@1.4.8","dist":{"shasum":"be1766bf1bc8751879bad69bb0ed9a8bd68b8ce2","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.8.tgz","integrity":"sha512-IyTYCEM0zmYg+jfdHNzwMVSTMXuFcuB9ZVgPXd+w4q6hXYTJE/hQxJTAUk6W/gHM5xvcfj6SdDuRT0/wGancHQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKbbCw6tNpXWv/KTngrfVM+wBvPTsTk+mAHbDd8u7kTwIhAOCPQXgEFfCIBohKN3AXmNbh5lWiVroP+PDcsOHpPK0m"}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmUser":{"name":"acamliu","email":"alexcamliu@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.8.tgz_1512075148151_0.19545039138756692"},"directories":{}},"1.4.9":{"name":"studiokit-net-js","version":"1.4.9","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"_id":"studiokit-net-js@1.4.9","dist":{"shasum":"864ae18f8e30fd4c3650ff2189235c97a3620a30","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.9.tgz","integrity":"sha512-TOb7LH3oYJdI7z0BzvXbWqwK85AKHKfyfaEv9dgNlJ6i8CD7afmabHml7JkTyu/+oEFQMTMlRYhZ2dY1xk0DMg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHaS0TqCbcCaa2NvRSz0t15VleyUzgGXI1oODEKSqZIRAiEAy0pR4FQGkWesYRnpydfu++0MFs1d3RTSQMP7N77t3PQ="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmUser":{"name":"acamliu","email":"alexcamliu@gmail.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.9.tgz_1512075634769_0.6913307181093842"},"directories":{}},"1.4.10":{"name":"studiokit-net-js","version":"1.4.10","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"_id":"studiokit-net-js@1.4.10","dist":{"shasum":"b9c76442be17dac719abe1226928d138ae876404","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.10.tgz","integrity":"sha512-RHJ0s9Vg/gL9YJCnOh1jKqX4yl94YS1S/dUYQZe9E4z0hIuCAl6EldoA+YXwz6zXv2uOiY0+DiRzGDirlwwezA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICCIGGasM1zimi+ksxcbUsVc9mhnYaad6w6R1PDSesbZAiAQYfds91MutBBr90zy0VG2MM1HN/TMe3DXv5G2OdtQrg=="}]},"maintainers":[{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmUser":{"name":"darrellshi","email":"shi180@purdue.edu"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.10.tgz_1513115827080_0.7225534354802221"},"directories":{}},"1.4.11":{"name":"studiokit-net-js","version":"1.4.11","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"_id":"studiokit-net-js@1.4.11","dist":{"shasum":"9010f2658d9bbd69fbfff7fdd0d24148179d277b","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.11.tgz","integrity":"sha512-vTfrxEdGwSpAQ0+Vp0uh+uKfx/qxggynSW6vMtXwoZGy/8wp7BW64UcjdcEYg5C0BmrwnIAa+JyV7BA6gY47iQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDI7Xfx1adaCQy5V693zVDG/IG0VseuUuIhwrFRXATv7AiEA0+cYn6ZdxBQpBxZ9qV5rwcD3q5pQvSsH3liEM0Wmgag="}]},"maintainers":[{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.11.tgz_1515700931836_0.13746121572330594"},"directories":{}},"1.4.12":{"name":"studiokit-net-js","version":"1.4.12","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"12f92495383956a53ab3875ec678f856382179a3","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.12","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-XcMkRKn9A9cti4OaC+PMpxjGkP5FEYVCJjmtCU7v4yIm93GeLCsADr1A6KRO3zZyoiPkdUKHc1PsOwjflecpmg==","shasum":"4ffa21fd9d4cf0a6efeee5b82d59791834f3cb53","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.12.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFnHS83laq6MPJwxzgcaAwFGH+vSfNSJ3v9n1S/Ari+LAiEAiapZcVN0ktXa0PVsmkfN+y1xXpcKBvQva78IET691VU="}]},"maintainers":[{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.12.tgz_1516826844457_0.1776250775437802"},"directories":{}},"1.4.13":{"name":"studiokit-net-js","version":"1.4.13","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"6bfc803dab7e6cccf3412b66f8150fec1d80baf2","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.13","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-ypaEICcMFXg7o/6qTK3c5diywO5l8x2GpozfBhACqeDSOEJP5u7sJEEJb1eMsPJqg+KfNK3kfpbhfiS1j/sebQ==","shasum":"e4c7ea0def09b3b3d2a2e8046011f0d51764d7a3","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.13.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAtWNj2lbpTKVQ4Szr0aLoxwU75w0QsC2OuAdOg0wo8nAiBsNFJpfaLA+Ui7q+AqzX7KHnTGQdq7kyvlznuME844Mg=="}]},"maintainers":[{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.13.tgz_1516911701287_0.7662209775298834"},"directories":{}},"1.4.14":{"name":"studiokit-net-js","version":"1.4.14","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"9ea7ef2133ad9be2f40bc4c8e9953d48a495f6bf","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.14","_npmVersion":"5.6.0","_nodeVersion":"8.9.4","_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"dist":{"integrity":"sha512-0bD5jAO79w2g5qM/0ypnq9T6ejREmql0QbI8K0EdilD7NTOrqZLT2erCEYl00jbNsp6quFjBcCutvOGAggc/0g==","shasum":"ec8ae80a67948f6c89982b4cce94ddc8af9bf340","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.14.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBuVn8Gc++PJF5iVUrnxLBFV6xtYzmHRNB+Pc6NtN1QcAiBpdm8u3Es/8x4CG1/F1QTta1smc9IYpKUAt7ZUhPeIZg=="}]},"maintainers":[{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.14.tgz_1516983940997_0.9359766910783947"},"directories":{}},"1.4.15":{"name":"studiokit-net-js","version":"1.4.15","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"cbee09eedd8fff92f60c0fb803bb18e8317033c6","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.15","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-sDv2z132t4tAnZS7jdVeooXn8e2Z+NYP4b/j/wKQuOZ2SZbAOlHGdbIolG/1zsq6iHaC6GN4jrMB1O0UOMAeVQ==","shasum":"e0e80a47bc7c66c19f4ddf5ede87307bd5ffb722","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.15.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFFQZKBsXf5aBIJHrm10+n7ZF19pFtcu9AfdeIOp/JKSAiEA9pz7rPByt5bkZxDLIKofcJYZHYRtO4D0C6668NPWE/c="}]},"maintainers":[{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.15.tgz_1517413861189_0.629227006342262"},"directories":{}},"1.4.16":{"name":"studiokit-net-js","version":"1.4.16","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"78cb45e9c5e8eca3acec89fa16e89e60055d46c5","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.16","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-79SuYUOdZZvxVBZD09LlCW+72sw8JwZVhm/ssk9IVIoWlHxbPcb8v664Ic5bbRJUm+4ErE5UtD7Eh2bwEjEHgA==","shasum":"fdccb5660a908b702182ace786deaff38ddb92ea","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.16.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIF/hAHwHE0qepG8PAxjNIL+RHcByKCbmHYYHlWR5p727AiBWcCXXu1i6LPDt7Hke1+Uxt2eu41Ba+HxaeHRooMVr6g=="}]},"maintainers":[{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.16.tgz_1517440197757_0.11670231516472995"},"directories":{}},"1.4.17":{"name":"studiokit-net-js","version":"1.4.17","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"8f54516bbb8c9ff3c8e17e45bf201c9435e6191f","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.17","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-fQnGCuSQI41ku0VD/bJRrfVjQMIhHK4dD260ktA1TzfP7YA/Ntu0+bfj9Q9btd3bANfgMXtfNrGZtzbyFnWM4g==","shasum":"1dce6402feb8e1f740d22fb6fd2ce3c1f229be36","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.17.tgz","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH+bA7ofAVstpBf/Ons6EcpcGlcGqt2Dem0FSwNDOmJoAiBPK3kTMr6gmizajzWIWMN1yKv8UPdwe6nRHddUNBSGkg=="}]},"maintainers":[{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"tragessere@gmail.com","name":"tragessere"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js-1.4.17.tgz_1517588671160_0.3397443061694503"},"directories":{}},"1.4.18":{"name":"studiokit-net-js","version":"1.4.18","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"1f7fc28950d82f4c4f672678510c59b340fdb2de","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.18","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-mU9+G0i5xSSwKhmsm2YgiPO5nfpd2XiAgalhnRXhxAwdEvD+nXzGD9yJBKym258EOPmF2Cxo/tWXJYAUwM7JNw==","shasum":"ff57f3b1d0376a51935a68b6d3883c10340dbb54","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.18.tgz","fileCount":7,"unpackedSize":54597,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDNt9XVBeLHHsz1Lsie/J+cfC6+GO7IUdK/Zy+P5qcSGAIhAN3P3dUHWIeDaisc844b0A6fIw2PqgumwHyMP31KK41P"}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_1.4.18_1519834979644_0.4799536747824713"},"_hasShrinkwrap":false},"1.4.19":{"name":"studiokit-net-js","version":"1.4.19","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"48570b1bfd4668971d8592e7ec5770da4c3eed03","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.19","_npmVersion":"5.3.0","_nodeVersion":"8.6.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-Mv/X31mkDo6t8ZLDj8Dvwx6qHPAg52e8tXy/pAwJLBFMgToIvSltk6ZshWp+gw0eFLrk+RG7Po4U8noKGErFDw==","shasum":"0661f64aa62acca992536771537d665cfd3ee3ce","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.19.tgz","fileCount":7,"unpackedSize":55125,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC4pBhWPI9eaMzf4u2keEY3gNPwARN01K/aKb24pZgYjwIgTD5AABbwvygua3jr5Zx6d1zmK59r+AlQI6Eh/JF9zcw="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_1.4.19_1520536352197_0.15252594040292178"},"_hasShrinkwrap":false},"1.4.20":{"name":"studiokit-net-js","version":"1.4.20","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"_id":"studiokit-net-js@1.4.20","dist":{"shasum":"7f1d411ea3d796043eb1c65b1908eccd1575c430","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.20.tgz","fileCount":10,"unpackedSize":55161,"integrity":"sha512-D/bmsE5lEb7Jl46BFVQbp/f5xbhnmbRbS6sbLBqwoDeR4b0OSomqqIRtqP3kq52o6ECpre85sI1XvogSssmgmg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCMk0qLXGrymLjm8wHcLJXJBwoSZ5xxC+7FMPy2Y3l1uwIgRiQBpbJUtHwBOyyu0ciKMSk0H92USHHBIZO1R3ZTIj0="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"_npmUser":{"name":"acamliu","email":"alexcamliu@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_1.4.20_1522875514640_0.2385875534549755"},"_hasShrinkwrap":false},"1.4.21":{"name":"studiokit-net-js","version":"1.4.21","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^5.13.1","flow-bin":"^0.57.3","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^21.2.1","lint-staged":"^4.3.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.1.0"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"6e75b5d478b434d82734082bd6c68db601d33d8e","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.21","_npmVersion":"5.6.0","_nodeVersion":"8.11.1","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-aGRTyUdoOBmsbNd/planJYg5EaJtRUt/zGQgJXODX/ToiMQbqLtj+ugW3MoPTgVpe6ktxPBeSXCj8/jv+jyXEg==","shasum":"ba0c8dd8cd4e0e68a2ffff1b95dceb4a265af0f9","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.21.tgz","fileCount":7,"unpackedSize":55613,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbGD0TCRA9TVsSAnZWagAAMt4QAJoRlP0dPZp7WfG4nBiG\n0WyrqtZOgRY5S1Uq/d8CmcJI//uPP+NrjM56GjcJXvNiYOJOJVh3ninNQI3k\nmYsp93Pku/9xVI2hcw4MVZkpR5cIYmiC4zXn/E84qCQEHqTzyGzriQOpDN2Y\nfGQg9sTpbEK33dhdMB1c27rjOZU0G0Xq30go20tlmXEa56h5kEksqhnq68gH\nNlLJVLh4uQKoxzW5NMnI2Kg8rCJ3O2PCeTrX0gceCfkSj+aZKwcpl4OLYDsP\n8BqxRuHtRlCjnJUUf4jTaKWkrcKkN/YWGKLLSO7HzgMP7db61b7CcSIvAPfS\ny1HkRuY36Uz3amNhqDHgf6FMkhYNRR50Ql/FbraBqYsCdinPWArZwRKFdfp4\nuzvZEQ9Qjmt0vJL6gHo5anxgoggS2e9rzge/eTGM14iGwUk/xXRUS/Cr89As\nX/J8aJ6tjbUOln4HO2t07RJRFaW5c2jkfYhdYY2mp/sw5nvGPjDZHZQCXT9y\nX1kyQP9MZOt0R0FuUmWAy9PxsCIx1KOXT8P0ydqe4K8sB565QlSqgT4UWndG\nmYghtvqoNVBezMBM32/BwTqUBA6ZiyJyeaFQ7VuOo0KmKeL6zmD+QTktghes\nzJ/jJ7gs9Y5eTowHMiaVS/+FQmKRNXFEARo2He0GaDwRbvhs3t0CUBXQ7eAW\nn45L\r\n=8w9w\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDJrKJtHwrygZmE5d6knBvZ8/2Rkeg36nW1tzxOdOpFrgIgIE0S7ZUN96tPXpZnP2ILCZsahXoKi0wg8dku6U1lUaM="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_1.4.21_1528315153896_0.8926710089192049"},"_hasShrinkwrap":false},"1.4.22":{"name":"studiokit-net-js","version":"1.4.22","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^6.4.4","flow-bin":"^0.74.0","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^23.1.0","lint-staged":"^7.2.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.2.1"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"b48a23505a40096e715046ea46198860219d586d","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.4.22","_npmVersion":"5.6.0","_nodeVersion":"8.11.1","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-CUqWzcHpOChBTZMzTOWgAumyicNK3GwBWZ1W0VNc9fUFa9Hr969On6tPBC8OnCKSWqszC2EWNrz2DGHqIOxDeA==","shasum":"752b3cabd28be4894b2e5284e586ba537f368f4d","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.4.22.tgz","fileCount":7,"unpackedSize":55850,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbI85UCRA9TVsSAnZWagAAEmcP/iYPdZu17HDtxTyAobcB\nLlOlJsF4CBcT/dRct+eoCvvw9KvCA9fDkp37C86Ppy/6cWLGARN8Sn7zpMV8\nPVfxhhD0XqTSUHIGaX6+vucOt2wN1Xbde85DUUliO5C0Jb1UG43BC1aNNJAe\nFi5mbZX1D3XgWfG33zQlWvH9zWRdfvYsDmmFZ7KH6olwtnh558U0kH3f1UXc\njmXh3CXZmN96WDeHfQtr3tR6JYbfbR1Q7o7ADDEXeAoP9qUGQ8z7t3zpPC10\nrNbqnYdvY2BNW5cI4gslNBSZwSERBRrwpjp3+DhMREk67sypQik9v6p4baog\nm46Vsh1v22O1vCeQ7TQtw6ml3BkATUh/fktOgVxN1bkZwsDujR1vY6Q1r7QO\n6qp8Nk2zPxHVVUbjp03Tp5aUkenFA+etHErILsHYhyTKIRpgETcZIsWyGh6l\nwh/UPqt6IsIu1ORzYqq9cjKoBwl+xDnAwlK9r9fWuAhtheyY+oClp1shdttE\n8TLrAwAhSObdvrylbN8kv/tXRuL/tdC+wpRozM9NCdUSfSedTViacDf/OP4N\n+6icre2VGGFH+Yn6Jzoa/rfM9HPWct3PdrCybDNjsn6q3lG64XVGrZokWL9V\nDGbjwwHw8V6LESdl6PbnmDQT7VJqdvMy10MHhwcxExg6+3bMrMaq5PI6a9bo\nQAoh\r\n=OV/Q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCn81lqGSjxM/BsSPgoB5mqCRZX40jXPN/ESpCbgqhWTQIhANsLNdO8bL83GJxjZB3CMGSMiwcnDXo0QncsYn2syIHD"}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_1.4.22_1529073234623_0.8562563472049682"},"_hasShrinkwrap":false},"1.5.0":{"name":"studiokit-net-js","version":"1.5.0","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^6.4.4","flow-bin":"^0.74.0","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^23.1.0","lint-staged":"^7.2.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.2.1"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"3b8592ddcf918cc2a7fb7b02af1266a01a88cc6b","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.5.0","_npmVersion":"5.6.0","_nodeVersion":"8.11.1","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-MtUwORzcEgvR7UJbAhTcZZRs+93gYyp+LTHExdG9Tj+pcxBbSnf5R+lTLIp9GkP708XpZfbDuaffMRc0siTkBQ==","shasum":"0ef3e44c32f97771e82716660cfeb73e5cf308a9","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.5.0.tgz","fileCount":9,"unpackedSize":58725,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbULdWCRA9TVsSAnZWagAAOroP/1Fpyn5PUw4ofH2d0xzX\nyiNxic1dgqZyRSsNUq5T2+kZNo7D0gH6TuxN3YQW9cxJJq/tkraFgTkUt9u8\nZUPeFJwmaGUh44U/dK2u19zZuyfvKxirietrX5fkxBua8Z4nWpU3Kwkxbiet\nFMk73QVqplqDeD0+mmn/XBBI76gnpTOxz3qs10/fM8SSh9v2PxUXGz3HFxsO\nkPfK/4kuDVztFza+eSn8kOzk1xKxa78njLK3t84cWGhzGx7RyMqdk/gw/rdS\noWyK5mP9l/dFKRxw9Ind2EMV6F7zC0m0Y9PuB7OgV5O63hgfjvtOn5IChmts\niK9jFgSnzLEYfGA9BWSqSV/MkD6nt8Rf/rGnQHqY9Igf1qQ0avyMazc12pkj\np//fpAZOqX7/wMXsXd4OReadOuyKLvejZz6p1oLi74Nm9CjA2qWMt3YfPeMN\nu8SNYZCUo5up5b77lWGlaLdYV7cbZs7PeHYwfAmbTGwtUViwPy/4eZwY1kGm\nsbX5vftrkFs21wmzE3JFKLh+CYHr5Z/PTiOXhCEvC82kaFuuD2ojrBa8DvB9\noVWUaCJtQd0b+Bu1dCYjWy7ttcmYkqF80Urr6puE3TklvcU7941133rZxYHd\nUAFglOudHiUh6mlX7YlhX3Bmsdz9+uZeYl3My03BIKjAi/UHtr9INLjnDZB8\nS12b\r\n=cOmr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCx7TF051liSkOFJER/FH6cUSwc2oTNTr/ZuWRdBbGkiQIgJYKQ+fEARnC14GDudAx1oKNJu0jKiNeUd04rxEAEyes="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_1.5.0_1532016470356_0.9727144990935919"},"_hasShrinkwrap":false},"1.5.1":{"name":"studiokit-net-js","version":"1.5.1","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","precommit":"lint-staged","prepush":"npm run test","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","files":["lib"],"devDependencies":{"babel-cli":"^6.24.1","babel-core":"^6.0.0","babel-eslint":"^8.0.0","babel-plugin-rewire":"^1.1.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.6.0","babel-runtime":"^6.26.0","babel-template":"^6.2.0","babel-types":"^6.2.0","coveralls":"^3.0.0","cross-env":"^5.0.5","eslint":"^4.7.2","eslint-config-prettier":"^2.6.0","eslint-config-studiokit":"^0.1.0","eslint-plugin-prettier":"^2.3.1","eslint-plugin-redux-saga":"^0.5.0","fetch-mock":"^6.4.4","flow-bin":"^0.74.0","husky":"^0.14.3","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^23.1.0","lint-staged":"^7.2.0","prettier":"^1.7.0"},"dependencies":{"lodash":"^4.17.4","redux":"^3.6.0","redux-saga":"^0.15.6","uuid":"^3.2.1"},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"fc7a2220eac7aad6d7a2024511309da696b2ecc3","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.5.1","_npmVersion":"5.6.0","_nodeVersion":"8.11.1","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-UzinzSbcCKX3dMhiR9LDt07ZpqBGbRvsAB2nCNNu/FhfRthvnA11KEkbFodVCItRoS6cezfc8hMvJ0pSnoy4TQ==","shasum":"325f9bb30d8e9223baf0e23f19cd258a2a48b66f","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.5.1.tgz","fileCount":9,"unpackedSize":58732,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbc06KCRA9TVsSAnZWagAAjksQAJlsa0ZDVhqscAfHhFbH\nkEd5s6E/i1uI0arrKT9T5df06YlECvvYtgM4tja/7+jBsJJ4Gg5ePPpyJPP0\ntNypSUKMdh7CiiZ2zpZviBcNOsE5XH8pptVzCI2WbnddmR4+jIp4rpHvQgGa\n/u48OXFDzrqOza9BZVQ/NUbZj/5Kw6g/aukJy6Nd6E6pxUpY1qPU5PNoQ4RH\nYYXGI7eJTxmM2U2Kmd6fu5zR6JAcw0Lt6RUOUkHoZMwIyTUJaaeunIXWOtua\nKid57l+9UPng9Jl53/DzCMVYRtdivFtoYiLY49mGH78EPqadg7QKLhPQ551A\n6ZXgaL0cv5BZ9Vt5/LKoLXR3T4L3geOXhCg8Momuc1/ez3U/TxInY45Xzr64\nvivRo9UJGsnJH1DKAjM4btIZ4QMKxHMdRP62qO7y8YN66TparADlVKG4ecRs\n4v7Rs86gm1/ebRg3CzfO2GYSDWhfjcZjH+1cYTA9hzukCPURWLJVzoY5Sj8/\nyu2jmOojXZPehhKC2qY8y1JZKENdHAawZw9OcHw82qtgnfqf7u/94yV9yu47\nuFhYenh5MbjUIGZVF4yo9jbE79g/gu6yl2eURlWV28XPcTn7Y5QZWXvL5UIw\nDpUWh6kHoWo+16vMwttjahaGc1ydhJ2a+W+m2B4cebn9r+z8b9fCfTgpdfzL\nnUFN\r\n=PTs7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCWU52d6uB6h3Ar8A4bVuWnXuTv+XrTpGFESVuEJ/hxIQIhAI8o51+GCIa4+sxdnhSV3Qtznl+KFtmjRYpluk1aridl"}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_1.5.1_1534283401950_0.1029450825818854"},"_hasShrinkwrap":false},"1.5.2":{"name":"studiokit-net-js","version":"1.5.2","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"babel-cli":"^6.26.0","babel-core":"^6.26.3","babel-eslint":"7.2.3","babel-plugin-rewire":"^1.2.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.7.0","babel-runtime":"^6.26.0","babel-template":"^6.26.0","babel-types":"^6.26.0","coveralls":"^3.0.2","cross-env":"^5.2.0","eslint":"4.10.0","eslint-config-prettier":"^3.1.0","eslint-config-studiokit":"^0.2.1","eslint-plugin-prettier":"^2.7.0","eslint-plugin-redux-saga":"^0.9.0","fetch-mock":"^7.0.5","flow-bin":"^0.81.0","husky":"^1.0.1","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^23.6.0","lint-staged":"^7.3.0","prettier":"^1.14.3"},"dependencies":{"lodash":"^4.17.11","redux":"^3.7.2","redux-saga":"^0.16.0","uuid":"^3.3.2"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"5137386102c4a8e7959d07fe4466d3aab7f311c9","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.5.2","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-/76f3vtB0UzxqMbjBOEmj6rjRmmcRwYKIfGm5/huBX35DcPtADqbMqFKApN+cFfMVVL3r1hnoYWr8x7i61YVTg==","shasum":"5f3d616b64f5ff6948ff155da8f8d6a9fb20928e","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.5.2.tgz","fileCount":9,"unpackedSize":58129,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbrRLjCRA9TVsSAnZWagAAA9kP/3VgwwaElQ6nY8drZmGd\n8tOliT2qI1Lkvhs7XjhYpK0qiizyyBBtjPpsAQWmmHftiTaut3AXOyLehrs3\n/ozfbSMdtpJrmi7dQ8nwdtlDQO3omqQuZRb7cv3SbbfH0BITdfvWZmrlxENJ\nzudwv7piRwsw0c2GXmOO6Gezjo+6fgvzNDTgap3a00j6yZ2TmhfXUKUweI8T\n0RUtOIqufwqHjy1rfaoYdXLDV5aQGz2uzIaMY+2R9vM+16g592ZLDnAO+8qk\nGh6al/Kk7lLsFYbOd2wNzqb9bP/RWSOXJWonn/0Fq0cJUzOxnTCrdb3fd8Y1\nys7QammO06IrBrBF7yFtVq4yGGJ+capTrxUqAJ1rh+5MQTtYLtX37Oo61w8J\ntYcL+5OWEa94xabhlvzHdlnNe1aordXsoRaJplvngsUveLLdvAvuk390UhgO\nDOusqJy4hT+iBTvskd8zEmpmGBNAqsIMe12SQz0NNIuawlG+fUm2v34F4z6B\nZz5l2U9vyNfCGfseJPZ1C2Mtl/4OxIMR7+MGnSA7VBFmDrdk4KJpV9cebso8\nfOWymxQWVMtpnL34VWAHDDNJGkvh0tGOQ3XAbCD7HUaKWmVCjycIPlD/C0k0\nEjFUBECkRGRT2AlMa9yjNWWykn7iV9lim1e3XHaQUuKOo4+h9kMyBddHR4E2\nXsMY\r\n=utW3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDahpaB9nN67nEWgXWyCM+FXD8o45j5eCZLprbDwTDwcAiEArGvTVGvAYBpRc2vZUVdQqjRtWm2P21QorqIgFO7jyCQ="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_1.5.2_1538069218288_0.8268430884573292"},"_hasShrinkwrap":false},"1.5.3":{"name":"studiokit-net-js","version":"1.5.3","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js ./*.js src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"babel-cli":"^6.26.0","babel-core":"^6.26.3","babel-eslint":"7.2.3","babel-plugin-rewire":"^1.2.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.7.0","babel-runtime":"^6.26.0","babel-template":"^6.26.0","babel-types":"^6.26.0","coveralls":"^3.0.2","cross-env":"^5.2.0","eslint":"4.10.0","eslint-config-prettier":"^3.1.0","eslint-config-studiokit":"^0.2.1","eslint-plugin-prettier":"^2.7.0","eslint-plugin-redux-saga":"^0.9.0","fetch-mock":"^7.0.5","flow-bin":"^0.81.0","husky":"^1.0.1","immutable":"^3.8.2","isomorphic-fetch":"^2.2.1","jest":"^23.6.0","lint-staged":"^7.3.0","prettier":"^1.14.3"},"dependencies":{"lodash":"^4.17.11","redux":"^3.7.2","redux-saga":"^0.16.0","uuid":"^3.3.2"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"40e8fd001bb313eea5b7f88037f97994d3fea42a","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@1.5.3","_npmVersion":"6.4.1","_nodeVersion":"8.12.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-YOtLt5xnsFSapllklxSW5kqHGSxxRmmKQ/CI9N3fczQKshaSr3CgJx2k3AEnVd4EQTHXSQH37PYr+qGWW69zbw==","shasum":"6fe42dabd072031b597784ef8c1615535372c7f7","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-1.5.3.tgz","fileCount":9,"unpackedSize":59024,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb5ctICRA9TVsSAnZWagAA8WEQAKPw8JrpNm3rt3YuUIiL\nt1t1QR13XY/FN7vTMW3qwgXrMRNlnQkwk0S1l8jRxCH6BcatYWvY08qPD8V7\nJ7l+BeCddU/ttVj0coNTxchgNHbzupEnRgymlfUyuiSPQ/x3Sqq/6z58uJxg\nGRYX6TYs/1MMG+w+u6ZK09jdOrDoEYna7dR5vlgVi1/t3U6qtaWZvlA0n/Yt\nFLuDSL8lUmAKZYOiF8w81jDP9iPLkxYhXnin3v/Q2Ts/ss4aVo9Li7erzCLL\nUbMLAl1nbRQsFhu3nYiutTiXbTpnbZfNvbBtfKFc4glVEews3dWqTINduUCu\nX60mR/x8pjO3laaFLcuIAETKwmk3oYc6oGUoqz4aBX8nqhl5R21oeUnmorv/\njRoW2cDwq8SpQ5oqAny1TUZQphRxGNJDeKEBPmuzNTwPTr9hx9/6Y2dHwJOa\n66f4AIKpL9w+Zs6O/pe20vETwAlhK3a1MWAQMJwPVgo68iZB5x/H/AJZs1Ib\ndjpQCReFl1zDWs01a+5N38fAUduOjW7kSi0SpNOziejWulw5VO8krXx8zs3v\nQa6adywe0tJjhraPEQxHpjIlBG6uXZFW+gYJ7+TMtcQcbABgLuQ9vS0Xmn0P\nUGb9mRc2T6IcChyr7HPC8clcCtSfD3Wwl5YFBYStpICupImmgM0hXkJMl5KU\nipdQ\r\n=Rccf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIB3QQoWYie+TcU2twGADK2TqYy4kcE51XslHLnzAVyMGAiAKo2Z8CHnULRkiVq2X0rv/p3iTcCb+DDe095SNp3+zEQ=="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_1.5.3_1541786439168_0.04300934957169944"},"_hasShrinkwrap":false},"2.0.0":{"name":"studiokit-net-js","version":"2.0.0","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js --ignore-pattern '!.eslintrc.js' src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"@redux-saga/testing-utils":"^1.0.1","babel-cli":"^6.26.0","babel-core":"^6.26.3","babel-eslint":"9.0.0","babel-plugin-rewire":"^1.2.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.7.0","babel-runtime":"^6.26.0","babel-template":"^6.26.0","babel-types":"^6.26.0","coveralls":"^3.0.2","cross-env":"^5.2.0","eslint":"5.12.0","eslint-config-prettier":"^4.0.0","eslint-config-studiokit":"^1.0.0","eslint-plugin-prettier":"^3.0.1","eslint-plugin-redux-saga":"^1.0.0","flow-bin":"^0.92.1","husky":"^1.3.1","jest":"23.6.0","lint-staged":"^8.1.3","prettier":"^1.16.4"},"dependencies":{"lodash":"^4.17.11","redux":"^4.0.1","redux-saga":"^1.0.1","uuid":"^3.3.2"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"1e3444d0ebb9239480763c8fb608b974e78a4cd8","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@2.0.0","_npmVersion":"6.4.1","_nodeVersion":"10.15.0","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-9XouUxKbOiCuewv4S+u+TW8jf/uc2Oj3yzcrkefzL7Ov5ZKfQGhtumpp9uC1+1kp8k+B94xrJ/VQJkVjSWl3xg==","shasum":"728ea0095ccedfb01fe3fd05d40fe1d6231295e0","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-2.0.0.tgz","fileCount":9,"unpackedSize":58931,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcYxCrCRA9TVsSAnZWagAA/wUP/iE1MUspaPUKVkPiO68X\nLaXU62OP8JrJAWj+TH7jdHQIkFg1S6JL1JLQ6vIDWYTXi/w4whsayZFKaDxe\nybiOs5An3jcUqGjNc/eQUVkTYWA+c+E/58OqPfj/cSy6A+jVZOQBhk7Ob0Oi\nRxGy4I5VKujTLSOiueYxfS35A56UqYenAdBKW1+oHfled1bXc6j2xKdQF+te\nfeSb8XvCmmfau44IoDPpI9Uin52aAxHrkbp970uShJgOYMtYmb3hPrTRS8w8\nRi0q0Ves7P27NAq+iSvojD0C+CMNWqSyVXyWqZaKGG5km+cOgjoU7VGHgEHO\n3ugIOLkA+oU+csEJezH9dIeLYcIAi7QXnaj4OOIo/DnifPtPmZXBz67qkLla\n5I+ZfVlpI0PPKEXMV0llzt6BAAs2K04gFN50fdO0YyrZ1fUS1oAzp9E0NZHi\nCfLWYGCm6jYKDAHje4yw0PLwG/REK/0iwXo+q0Bpc6QgdOqpSmdXuGXv8IU4\niJ8OH3qGLs/0iHpk7Ry9ojlbiw9yXRTCwcQg96QyHLp426FeIM4vztZplGN8\n+tY/GfgH4FzmzRewgn8h59wKYNitdl3jwaS1LmOfUTKiO0DcWlQLg/SOj0ET\nFTkHzwVtrWRZCZKjq7bZxzZm1v4Q5sThUYyB6yZE1yUBP9PjsdKE9PGE0Lhl\nWsOK\r\n=NuHE\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDHoK9NVvtB8/g6HYApqU0LemXfuJ9clHXMpfp+HUnIaAIgdIiR3h+ClU7f6Y2gj3aeMjBUgqYYn3YX+omJY3CaD8Q="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_2.0.0_1549996202868_0.5897308684587301"},"_hasShrinkwrap":false},"3.0.0":{"name":"studiokit-net-js","version":"3.0.0","scripts":{"tslint-check":"tslint-config-prettier-check ./tslint.json","lint:core":"tslint -c tslint.json -p tsconfig.json","lint":"yarn lint:core 'src/**/*.{ts,tsx}'","fix":"yarn lint --fix","test":"jest","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","clean":"rimraf ./lib","build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","prepublishOnly":"yarn build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","types":"lib/index.d.ts","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"@redux-saga/testing-utils":"^1.0.2","@types/jest":"^24.0.9","@types/mockdate":"^2.0.0","coveralls":"^3.0.3","cross-env":"^5.2.0","husky":"^1.3.1","jest":"^24.3.0","jest-fetch-mock":"^2.1.1","lint-staged":"^8.1.5","mockdate":"^2.0.2","prettier":"^1.16.4","rimraf":"^2.6.3","ts-jest":"^24.0.0","tslint":"^5.13.1","tslint-config-prettier":"^1.18.0","tslint-plugin-prettier":"^2.0.1","typescript":"^3.3.3333"},"dependencies":{"@redux-saga/types":"^1.0.2","@types/lodash":"^4.14.122","@types/node":"^11.10.5","@types/uuid":"^3.4.4","lodash":"^4.17.11","redux":"^4.0.1","redux-saga":"^1.0.2","uuid":"^3.3.2"},"prettier":{"parser":"typescript","trailingComma":"none","useTabs":true,"tabWidth":4,"semi":false,"singleQuote":true,"printWidth":120,"jsxBracketSameLine":true},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.ts":["yarn lint:core --fix","git add"]},"jest":{"transform":{"^.+\\.tsx?$":"ts-jest"},"automock":false,"setupFiles":["./setupJest.ts"]},"gitHead":"c2397dbc6053dc0cdc2861d29714f28c9866b5ce","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.0","_npmVersion":"6.4.1","_nodeVersion":"10.15.1","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-h2gRaJnR3JdgEM/GvIGrx+ckP93yBTtKkkXmOwHsQrNO3EysOvKJUF4pOD2xaFztNJU3uCS3GVbcWbH3k5Aojw==","shasum":"92b95a126a7df00dc846dbcc868c415e1ee00fb9","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.0.tgz","fileCount":16,"unpackedSize":83230,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJch7b2CRA9TVsSAnZWagAAgUYQAJsBoOUawUSwCvCTGU9N\nVdRGDVRkP73i5tQBOoZWAudR5BO1OEX9hW4wbBfZRaUANbHZ+BGqvMpKI4RD\nwlXuTojDmWBJ3eNkmUzA0ewlgS52mzZZkm4h0kHGDMJLxZH0IQeTQlmYnbgb\nIdpap9BOXxDtpjlHmjcmHDUVcohK7xgUrSLddDkc020Ny53q64DoncBmKi64\nNraYykZc2XxLj4h7RysCPrl1K35tuuqYEqS/Yv2RsvBVag29YIrCNAWc3sRC\ntXh1KZC2CtYyst59D/I1X0YwsZQ2G+IftaxsDbYAP6YVGlhnN6ZMDTxfwu3Y\nIaQgcHQQnKp0w4dTVcwaIipoN6s6s3NsoYpIGnO6nMHXny+whjDbP9eec+Xj\ncfBUzkdlIOuVBkvI08lNVKn1Xsm3CaQ1p61h0h2RyjKmPJIH16jkYQyILEaU\nepmi0LCFl7vQ1GpWLRPJRA+lYrmLhDdCcLMk2kIOSvU9ly5RGYMiLRXTUY6i\nBvRmpHUi6uv4l60qo5CpUFfF/bg0tlpeSOb0KZ6Ka6mU4Db9iaYs0i1NnrFg\n+DYBQ7uZFPBw6MTmcev3h0HkQuANkzW2crVggiL3MWNE1opJALldN0a2VHUK\nyhkWNTnv20ly3fVF3izsiuDQgrrWlCpIlGcQ86ngo85rAVGpeNfSGPQKAUgf\nnFYU\r\n=4Djf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHbBJLcxYRVCI9Ayr62z39GaSJOD++uCosN5zg0dtgd5AiA6EurFsDvXXUf1rorI9pi4zOVFPP6b3G1yw2iKf2DCyA=="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.0_1552398069694_0.17455481463008748"},"_hasShrinkwrap":false},"3.0.1":{"name":"studiokit-net-js","version":"3.0.1","scripts":{"tslint-check":"tslint-config-prettier-check ./tslint.json","lint:core":"tslint -c tslint.json -p tsconfig.json","lint":"yarn lint:core 'src/**/*.{ts,tsx}'","fix":"yarn lint --fix","test":"jest","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","clean":"rimraf ./lib","build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","prepublishOnly":"yarn build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","types":"lib/index.d.ts","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"@redux-saga/testing-utils":"^1.0.2","@types/jest":"^24.0.11","@types/mockdate":"^2.0.0","coveralls":"^3.0.3","cross-env":"^5.2.0","husky":"^1.3.1","jest":"^24.5.0","jest-fetch-mock":"^2.1.1","lint-staged":"^8.1.5","mockdate":"^2.0.2","prettier":"^1.16.4","rimraf":"^2.6.3","ts-jest":"^24.0.0","tslint":"^5.14.0","tslint-config-prettier":"^1.18.0","tslint-plugin-prettier":"^2.0.1","typescript":"^3.3.3333"},"dependencies":{"@redux-saga/types":"^1.0.2","@types/lodash":"^4.14.123","@types/node":"^11.11.3","@types/uuid":"^3.4.4","lodash":"^4.17.11","redux":"^4.0.1","redux-saga":"^1.0.2","uuid":"^3.3.2"},"prettier":{"parser":"typescript","trailingComma":"none","useTabs":true,"tabWidth":4,"semi":false,"singleQuote":true,"printWidth":120,"jsxBracketSameLine":true},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.ts":["yarn lint:core --fix","git add"]},"jest":{"transform":{"^.+\\.tsx?$":"ts-jest"},"automock":false,"setupFiles":["./setupJest.ts"]},"gitHead":"d4e569bacccc098c4e292dad7a57632597afdafe","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.1","_npmVersion":"6.4.1","_nodeVersion":"10.15.1","_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"dist":{"integrity":"sha512-N7HB7S6TKIiB0cgAomNUl/SFjjRythtYEfBJdUr4VVgSfeM1LO1xbK4nY0M/bE0qWraIp8oUk/2nBu1JGRunLQ==","shasum":"ebb9d5bb9e28e1554a7e4f0ff3625ca766a406e7","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.1.tgz","fileCount":16,"unpackedSize":83231,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJciQQNCRA9TVsSAnZWagAARKsP/jsEJyYLKK39jJFy8UVG\nnLHmB5fcXuDVeHJkDI+GlYwNq9xwtqOvs6A4rg2oHsbIeENvh4zhjFBuGVL4\ngrO4LwoeKebIIqbO9HCaZAmFh4Sh7kWH2/s4bhfI5t6EhJxli7Zuzm234/RY\nHfL8Z1hs6tU8bwa07xvt+3VXvKm2vX7JGQf+B5hCdvPMg5UmR5cIALITX/8x\nqMo+58WfRUbI2qzKNmg8auyaaPaXsHf2whQU55729Tt0r9z8JrVFr9OXv67R\nYYJlZoatOe6SloZ5ud6hgVWNzulSqYjnLxjZpryslo7M85Iqev63GKiWuMUV\nB/RK91Ls2bohVRHbPDt1KFCNUfkbPOsLVMbg6uIzGt6JlWGzyZC7bc3Y2e8j\nc100mx2s1POqoIwDCpjbr9+BHKR9twkHEmM4PEFeXx2s1fQF8OnFBOn+Ps12\n54lVcQP20JY40t05cYQfL6zMf6U5Uj7DVy/8S6/07Ibz+2dddLzBsyj5maYb\nWc4PuG7iEGCuc0CGBYKFLojH+8N8WqSrq16WPJD3fKxMTAHSouezyanokrsJ\nunGik4113gNqnkTHUplpxQ+KuK1bCPzPkPNpWror/iXhwYExTxj39Y8pY62X\nPYyjGrjy/r5gC5UXfhI+652Q7bOi01C8M+otSKHrbqEAEK7/72X928DnWMYU\nNzOr\r\n=CG4R\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCZ8C0pKkcZUyO4DykadudkiYBP+qye2j2fgjubj7TK0wIgAioAsHto6OM0ym+22fbY0BJR9GnygfDQFZijWy2JXNw="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.1_1552483340811_0.9647052731890673"},"_hasShrinkwrap":false},"3.0.2":{"name":"studiokit-net-js","version":"3.0.2","scripts":{"tslint-check":"tslint-config-prettier-check ./tslint.json","lint:core":"tslint -c tslint.json -p tsconfig.json","lint":"yarn lint:core 'src/**/*.{ts,tsx}'","fix":"yarn lint --fix","test":"jest","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","clean":"rimraf ./lib","build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","prepublishOnly":"yarn build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","types":"lib/index.d.ts","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"@redux-saga/testing-utils":"^1.0.2","@types/jest":"^24.0.11","@types/mockdate":"^2.0.0","coveralls":"^3.0.3","cross-env":"^5.2.0","husky":"^1.3.1","jest":"^24.5.0","jest-fetch-mock":"^2.1.1","lint-staged":"^8.1.5","mockdate":"^2.0.2","prettier":"^1.16.4","rimraf":"^2.6.3","ts-jest":"^24.0.0","tslint":"^5.14.0","tslint-config-prettier":"^1.18.0","tslint-plugin-prettier":"^2.0.1","typescript":"^3.3.3333"},"dependencies":{"@redux-saga/types":"^1.0.2","@types/lodash":"^4.14.123","@types/node":"^11.11.3","@types/uuid":"^3.4.4","lodash":"^4.17.11","redux":"^4.0.1","redux-saga":"^1.0.2","uuid":"^3.3.2"},"prettier":{"parser":"typescript","trailingComma":"none","useTabs":true,"tabWidth":4,"semi":false,"singleQuote":true,"printWidth":120,"jsxBracketSameLine":true},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.ts":["yarn lint:core --fix","git add"]},"jest":{"transform":{"^.+\\.tsx?$":"ts-jest"},"automock":false,"setupFiles":["./setupJest.ts"]},"gitHead":"6b929d38f1022c41df88815702ee64da8bc3dc62","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.2","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-+FgMzRPneJ8LjwTf02KLPORXgLf6QFCMkWeSijcM6st+o4PfSE3soCV91jU6uJ/HsZYDo4+7cC0rYUd6AQo5sw==","shasum":"7455345a460887a0f28077b350291f2cec1f4631","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.2.tgz","fileCount":16,"unpackedSize":83467,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJck6m0CRA9TVsSAnZWagAALhQP/iI+ZBKkw2V1I077TO2J\neu795+v3Mn7PGmEFlrQjq2GFPe7V88jpoZ+ifvHrpLkzlp6X6ee+tPljXU/P\nT40mo2ex/GMh+b7cttKoz8ealQHsdMx46W4F6xMq9S29v3QSwfFEqmqJ4H2E\nYYrmyGhwR2uFZICfnPsXXypUHEUhuES5R5QujbNxtevsDICSoTp1BTvF8ZFG\nWKHED4ZY1T5p/NuWrICFzCLELAYqFAOYll6pSY6kPKXn6GzDamnA8jdomSCp\nOPv4pIlYO/X4jEEpyHXVZt4l5MXQqUqR9sLJvOZX3P2VgEW30cGYkBUMS53G\nitsnMIhYq8vN4HGeDhigKlqb6PGofS5ZwrdZHuh752VCiPG7TX5mobhnkGmG\nq0kFhTecs5A3hArP5d9UaFLAsvRS2nPDavwBD81MiJi6h9pe3mD4zXdAbhME\nNwK3PIXcXX+eTdt1bFs+PaT6TW0olrB4KiSZI1PzWyh4wNWFjixuN0pkEvLp\nEVqo/vEGyFrzMQ89oBHWv3pE7vgAwcbpJt1uApF5VS+pkOlZ8WRcj3Y5Xf5P\nQH/RvF4yahNlx7ZyD0vUjmqKdsPwABmsY/PW2pEastuGE6Vb+O8rpSIozZ8H\n//zRRRiCatdm4/7oxW9v7FTO+8RAVq7apvmC1OPu3xvgM48OIxwjwEuYg84Z\nM5hB\r\n=viyh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHwXUiHH69QSO790Ao9hQ8Q9x6XWs+sBKt9++BAmq3YuAiBcFsvF7IPJ9QSd/Itsr9PGxzh7e5v8l8iXlgk6dX6IIA=="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.2_1553181108024_0.6767916565370113"},"_hasShrinkwrap":false},"3.0.3":{"name":"studiokit-net-js","version":"3.0.3","scripts":{"tslint-check":"tslint-config-prettier-check ./tslint.json","lint:core":"tslint -c tslint.json -p tsconfig.json","lint":"yarn lint:core 'src/**/*.{ts,tsx}'","fix":"yarn lint --fix","test":"jest","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","clean":"rimraf ./lib","build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","prepublishOnly":"yarn build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","types":"lib/index.d.ts","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"@redux-saga/testing-utils":"^1.0.2","@types/jest":"^24.0.11","@types/mockdate":"^2.0.0","coveralls":"^3.0.3","cross-env":"^5.2.0","husky":"^1.3.1","jest":"^24.5.0","jest-fetch-mock":"^2.1.1","lint-staged":"^8.1.5","mockdate":"^2.0.2","prettier":"^1.16.4","rimraf":"^2.6.3","ts-jest":"^24.0.0","tslint":"^5.14.0","tslint-config-prettier":"^1.18.0","tslint-plugin-prettier":"^2.0.1","typescript":"^3.3.3333"},"dependencies":{"@redux-saga/types":"^1.0.2","@types/lodash":"^4.14.123","@types/node":"^11.11.3","@types/uuid":"^3.4.4","lodash":"^4.17.11","redux":"^4.0.1","redux-saga":"^1.0.2","uuid":"^3.3.2"},"prettier":{"parser":"typescript","trailingComma":"none","useTabs":true,"tabWidth":4,"semi":false,"singleQuote":true,"printWidth":120,"jsxBracketSameLine":true},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.ts":["yarn lint:core --fix","git add"]},"jest":{"transform":{"^.+\\.tsx?$":"ts-jest"},"automock":false,"setupFiles":["./setupJest.ts"]},"gitHead":"09216bb0e68828ad14e8a0d35c1d1190edb3e38b","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.3","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-JH2fob0sFxG6IHMLMSmUDeEW+U04ekhb4/AXNNp5e7a7i+vRFYg+3x9YAuMnq/PLEJVOTRlr2yoju1Zk3QRPXw==","shasum":"e14b53ee48877c9ceeaa40b2bce295ab9da5caf8","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.3.tgz","fileCount":16,"unpackedSize":83855,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJck+7dCRA9TVsSAnZWagAAr6YP/2uzSrEJAv+1Ub6FF+Np\nhajYT1CrnSPUQ/DY3vehrVIy+1LokuMfPLE3qm74F8+7eLCUTt8ShmrLAJB4\n/FHakzsHwLbJmDvlZ+weVF2Eca9P4bXThrjw5Ngsv7rX+oiG+d8mp4H9El+G\nI+Bhz34uH2HZ3QdpY7ipvwVQPIxIn5iJnpaFYzoV+aoOfkIf0NmY3pSeLeKQ\n5lNksgfICdOkfddV2RB5pLESQt3FHyrgo0081BXbMq1vV50/q59ztCWsF3h5\nWEn73boCcVbX82oEsSHcdD1dK7RW75edjCjw8QPPJ7DeA4QmqM9hyBziXm7R\n4X5xoYoQVzdT+w68bp+MfHud5PeesRnq7PzVYdma5XQvE+JPEw2/XgUTSaKa\nzRmTdNc2FyvyUE3cPkQWGPAHX0XxdV68aCAozbQnuuOlzDysq4t9lKwPI/G+\ncwYsNHkfYDdw7VPVlq4G2SA16NcQuaQHANoNR87O+SjdyQ5j80iHVonbhVqF\nkfT2kjPhLHpHoLDBBNPz2r6ui+X9iQ8KyWGH+Stl1a+jcFpB7rBzyH10M+Ao\nbQtWoZpTnBxLYM3R0tNwCFXuLR4JabutxFcuGW/K7JQhdeVHv3LJcs822oVW\nq/L+pOFn2pa7qtcU3q3g7b4MtArr6Sgdu8foL5c8NAT2GJkOdHdXWEaDRnGe\njCAl\r\n=xgGx\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDooIPz+3opxQn3mpK3NnE2OmLDrDjaNWG6IPZ1J8PJiQIhALfi4eeF+o6UawWdd+3dnCElBeF3+6dIqxW7H4Pgwp0t"}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"shi180@purdue.edu","name":"darrellshi"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"tragessere@gmail.com","name":"tragessere"}],"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.3_1553198813068_0.4874548581332474"},"_hasShrinkwrap":false},"3.0.4":{"name":"studiokit-net-js","version":"3.0.4","scripts":{"tslint-check":"tslint-config-prettier-check ./tslint.json","lint:core":"tslint -c tslint.json -p tsconfig.json","lint":"yarn lint:core 'src/**/*.{ts,tsx}'","fix":"yarn lint --fix","test":"jest","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","clean":"rimraf ./lib","build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","prepublishOnly":"yarn build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","types":"lib/index.d.ts","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"@redux-saga/testing-utils":"^1.0.2","@types/jest":"^24.0.11","@types/mockdate":"^2.0.0","coveralls":"^3.0.3","cross-env":"^5.2.0","husky":"^1.3.1","jest":"^24.5.0","jest-fetch-mock":"^2.1.1","lint-staged":"^8.1.5","mockdate":"^2.0.2","prettier":"^1.16.4","rimraf":"^2.6.3","ts-jest":"^24.0.0","tslint":"^5.14.0","tslint-config-prettier":"^1.18.0","tslint-plugin-prettier":"^2.0.1","typescript":"^3.3.3333"},"dependencies":{"@redux-saga/types":"^1.0.2","@types/lodash":"^4.14.123","@types/node":"^11.11.3","@types/uuid":"^3.4.4","lodash":"^4.17.11","redux":"^4.0.1","redux-saga":"^1.0.2","uuid":"^3.3.2"},"prettier":{"parser":"typescript","trailingComma":"none","useTabs":true,"tabWidth":4,"semi":false,"singleQuote":true,"printWidth":120,"jsxBracketSameLine":true},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.ts":["yarn lint:core --fix","git add"]},"jest":{"transform":{"^.+\\.tsx?$":"ts-jest"},"automock":false,"setupFiles":["./setupJest.ts"]},"gitHead":"94700698183068be7f89460b09c863db53a30094","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.4","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-jJs/blzFkaopm6cD90S/jqgXP0y9m2nD7xSvTGqVyzZlDSTf1NYpkkbEpbvTlMxslFw46cTkcNbp7js6qGKUSQ==","shasum":"3183325c777e80cf7ceec37fec290bc490317bc9","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.4.tgz","fileCount":16,"unpackedSize":84007,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcmnfpCRA9TVsSAnZWagAAQgUP/AuV0IXISwTCSSPwt8KB\nyxvThx79ZpYYzBLFVxpt/MxA/0FtCAuZDDDLQt5xXET2EWiu9/fF6XoD+gAT\nuP11+VOGDkTfxkhwGb17Uu2S0V6/qS0XN4Osd0YK5nah8g/k2tLv2L9/F0PO\nSF6NktUPzkHrxN+6XVNrp3syBdp/rtxFQnlqvhtlrY11XfY8khi7NOsRHIkA\nvFh5tUZTlm2yMA2jJKFLLPKLLdcB7Op9mcMP0/BDwsTe4cQBi6GeShwaavbs\nnwePAT0tFJVivnBAwHF52C1gvCiTnnbK+XhYTPdwS1896XQwQX3KbPF0Pi4F\n086Ddgksk1Dj5sdh3zrcAlgAEhxisZafvx/LPn4kE69weIx2xYQRIiBTBWGp\noazF6VYeT+zspJMCH8Ck9QpzJDe3im9NEDpRZScTa5++TA1KMNFUIqlzZSW3\nxWDB936ID+R0HiQ/B7SdiBpx4mor+zcCpuwP9gGls5xghRiW/ozti/sNLgHb\ncc4KLR11ZrgicSONvkULspDLIDAUt7LjHpDtlsN5Fviknkwh4Ux75BNbp/0l\nXTU6DG5PXjc6DEGOqT4s2uIM15Crhl7JjS9ixHVxQApsMCAQfiRanyAkxmer\n60+dqUs4csVoaJLRdk9UswMtj8XKGzYfxVSztyQ5DRLBPNKQczbRMNOg66Nt\nwNmK\r\n=lrCN\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC4mgNK3LahIvtP82Cmaup0OGOZWHXKFapvpncp6dRQnAIgbVD97uOy0NOLr95IUwnQooaHL7VBvjjH0VomL0TgI8s="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"carls118@purdue.edu","name":"lilycarlson"},{"email":"tragessere@gmail.com","name":"tragessere"}],"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.4_1553627112973_0.5709177443991016"},"_hasShrinkwrap":false},"3.0.5":{"name":"studiokit-net-js","version":"3.0.5","scripts":{"tslint-check":"tslint-config-prettier-check ./tslint.json","lint:core":"tslint -c tslint.json -p tsconfig.json","lint":"yarn lint:core 'src/**/*.{ts,tsx}'","fix":"yarn lint --fix","test":"jest","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","clean":"rimraf ./lib","build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","prepublishOnly":"yarn build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","types":"lib/index.d.ts","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"@redux-saga/testing-utils":"^1.0.2","@types/jest":"^24.0.11","@types/mockdate":"^2.0.0","coveralls":"^3.0.3","cross-env":"^5.2.0","husky":"^1.3.1","jest":"^24.5.0","jest-fetch-mock":"^2.1.1","lint-staged":"^8.1.5","mockdate":"^2.0.2","prettier":"^1.16.4","rimraf":"^2.6.3","ts-jest":"^24.0.0","tslint":"^5.14.0","tslint-config-prettier":"^1.18.0","tslint-plugin-prettier":"^2.0.1","typescript":"^3.3.3333"},"dependencies":{"@redux-saga/types":"^1.0.2","@types/lodash":"^4.14.123","@types/node":"^11.11.3","@types/uuid":"^3.4.4","lodash":"^4.17.11","redux":"^4.0.1","redux-saga":"^1.0.2","uuid":"^3.3.2"},"prettier":{"parser":"typescript","trailingComma":"none","useTabs":true,"tabWidth":4,"semi":false,"singleQuote":true,"printWidth":120,"jsxBracketSameLine":true},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.ts":["yarn lint:core --fix","git add"]},"jest":{"transform":{"^.+\\.tsx?$":"ts-jest"},"automock":false,"setupFiles":["./setupJest.ts"]},"gitHead":"864e7c92ace2a8c199568728c531a658f2cc7216","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.5","_nodeVersion":"10.15.3","_npmVersion":"6.9.0","dist":{"integrity":"sha512-zIwQH8iMQWgGcGCKuifKiM4TIWSxr9ZzL0Fo5AFuVSpQeIQD61ooyGtHIrzbRT5iloYchGh+Iu3TnRIDLQwQNg==","shasum":"55ba1407e0a8f661fe627a18149f065434ab09ec","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.5.tgz","fileCount":17,"unpackedSize":85107,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7qeeCRA9TVsSAnZWagAAhB4P/1u2WnH1DPhf+A3Xph7J\nLJT5IJoE7pnnfAEImK7yKOZX1klARCUJ2ItxdeXhLmGBiPkiKRdTaxGrJ9kP\nWdaXjr2pg8ylJR5GZMckhnkJBasYGxs8xSeYPk4SCY1q1Xc/sXR0lT5sKr2R\nLqPfYhfDmHnYST+FjgxlW0aU8E40QjFUtnXRK89cJgRtKT1NMAAvIHS7Wo49\n/+Y4PyDr2ObebzE/LeCQTNI7Q5vp0cGJ9ESxEZoa2FNxaombwMUjH0aCuQeI\nFXcWKa+WJ8Wmnegu1e5YYMTTH9sasbqVK2vL5nrkZbbdc4Ar8bVx9g4jLOeH\nVnsZo1yf0OMeIHb1suIxG7gPD9xkqSry4AfJUoomNl+5ZU9P/lA2I2+nJuE+\nEZ3jeNsNdg4CVgnol/RU7GQBb/vxoDCIVK6OKik5XAsfNul0K1A1fm3a/BGR\nZhOX7jvgNsFvJ8+0aK+pbnJXpsirIV2q21s8vIMCB/PFkVpVasQCKliXPbiI\nW0TrFPMMIjnjnpSM8qlThoIWWYNZA+yVGWQvBd+HVaj0Ru2y1+OVjo+pS+LP\nnRkDDWWgfgR0DOoNwNrtZMm53Ps/9USIvDentiYLKpf7AX7QTcaliav38io5\nBU5RCg1hdksmVQjmJJPPLcFd8mitNx07hQEDVhz4/N1adNJXAkUKA7I/cWtr\nVC4i\r\n=uLus\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCt51svEQbeNSFCXoXzoX7EZCq8I6h5KpPBJHk+aZi34wIhAKbjgwzxmTboqowXCJ2qkNlg5llG1HSwO1/6iqkPa+RV"}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"carls118@purdue.edu","name":"lilycarlson"},{"email":"tragessere@gmail.com","name":"tragessere"}],"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.5_1559144349054_0.6638126378556346"},"_hasShrinkwrap":false},"2.0.1":{"name":"studiokit-net-js","version":"2.0.1","scripts":{"eslint-check":"eslint --print-config .eslintrc.js | eslint-config-prettier-check","lint":"eslint --ext=js --ignore-pattern '!.eslintrc.js' src test","fix":"npm run lint -- --fix","test":"cross-env BABEL_ENV=test jest","test:watch":"cross-env BABEL_ENV=test jest --watch","coverage":"cross-env BABEL_ENV=test jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","build":"babel src -d lib","build:watch":"babel src --watch -d lib","prepare":"npm run build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"@redux-saga/testing-utils":"^1.0.1","babel-cli":"^6.26.0","babel-core":"^6.26.3","babel-eslint":"9.0.0","babel-plugin-rewire":"^1.2.0","babel-plugin-transform-flow-strip-types":"^6.22.0","babel-plugin-transform-runtime":"^6.23.0","babel-preset-env":"^1.7.0","babel-runtime":"^6.26.0","babel-template":"^6.26.0","babel-types":"^6.26.0","coveralls":"^3.0.6","cross-env":"^5.2.0","eslint":"5.12.0","eslint-config-prettier":"^4.0.0","eslint-config-studiokit":"^1.0.0","eslint-plugin-prettier":"^3.0.1","eslint-plugin-redux-saga":"^1.0.0","flow-bin":"^0.92.1","husky":"^1.3.1","jest":"23.6.0","lint-staged":"^8.1.3","prettier":"^1.16.4"},"dependencies":{"lodash":"^4.17.15","redux":"^4.0.1","redux-saga":"^1.0.1","uuid":"^3.3.2"},"resolutions":{"set-value":"^2.0.1","mixin-deep":"^1.3.2"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.js":["eslint --fix","git add"]},"gitHead":"12617e4ec18b085a97fec29d144c0b527d063195","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@2.0.1","_nodeVersion":"10.15.3","_npmVersion":"6.10.3","dist":{"integrity":"sha512-Eshs43N0JMbbaVM6jxD2tqtgZeWFYsAHNPrG3OpSjiPogZzqB5b8m005xdLakkU5WR9PNIwlg9fLMJDYTnZLjw==","shasum":"8a30962f15622b357af6ed2d59f7c46414c7946e","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-2.0.1.tgz","fileCount":17,"unpackedSize":85650,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdk5NhCRA9TVsSAnZWagAAROMP/1zK3ReWyxrXuCvTsLVG\nAZGdN4fycbObdmunXw8fsWplYNTz4bb7MmjzxWdWbF53POpWJ1J19mtA53n0\nhGYKffanq77AghK2hQDVnJIIeO3WCQeoiXFyPTF1FdpeiphKQ/RbfRLgDOFN\nxUKmuUQwNyMMOSbiI7lMb2J6U7WMZHwnkqTNWb9lWaXHmqGTzXLMwf/sV659\nY9L8EW13nkp9kKWx1Zm4fRME6QPv/YafGhM+Qi9iGm5gJXb43JyXCKfiYOIY\npDQMbvgsJhrBwwF1Wy9wxW1RORW7n6PHZDcdyAYx5Wphmx78/sSUek4VH+mQ\nP/yQbrsaPaN7YjqDVHiFdMjD6DDz+b87oHxEg7l9cxux/HiLonlV8XQmc0tn\nErDjRKE5mdUDFezLnSZRGiR3iAgp8guz3VfBujp04cURidTTGrvXbhO2uhe0\nH/zSxw1meltefqFkM26Dh5OF6ObG2G0Er4+e1meEMjVF8rTa9uFamixaLIe6\nJEr8g8bISLPZIoUkpulBDIv6jvr4Cu+pa/+ju4u9lOutKdahZLWJ1OIE8dtS\n9sfn4UdEL1+PhrwuUNd3alNjNZ0xgsshOi9bqqs1ZlDTmI2nh96e7bJQc4Ye\n0ll+Q6TkhiWKA343xJQLnf0JFTcGTCP7EYiVLFNEHJPTbxw/rJJCGR5poAfL\nRbj+\r\n=ASGo\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHLvvDXRQ76/qGYu92N/2Nr2wWmJDIcz+NSs1EfVnL7DAiBE+TQR0PWjHnyuaZhB6+z0Q826X416DxFdqF1fEoitow=="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"carls118@purdue.edu","name":"lilycarlson"},{"email":"tragessere@gmail.com","name":"tragessere"}],"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_2.0.1_1569952608159_0.6549361095999295"},"_hasShrinkwrap":false},"3.0.6":{"name":"studiokit-net-js","version":"3.0.6","scripts":{"tslint-check":"tslint-config-prettier-check ./tslint.json","lint:core":"tslint -c tslint.json -p tsconfig.json","lint":"yarn lint:core 'src/**/*.{ts,tsx}'","fix":"yarn lint --fix","test":"jest","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","clean":"rimraf ./lib","build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","prepublishOnly":"yarn build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","types":"lib/index.d.ts","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"@redux-saga/testing-utils":"^1.1.1","@types/jest":"^24.0.18","@types/mockdate":"^2.0.0","coveralls":"^3.0.6","cross-env":"^6.0.0","husky":"^3.0.5","jest":"^24.9.0","jest-fetch-mock":"^2.1.2","lint-staged":"^9.3.0","mockdate":"^2.0.5","prettier":"^1.18.2","rimraf":"^3.0.0","ts-jest":"^24.1.0","tslint":"^5.20.0","tslint-config-prettier":"^1.18.0","tslint-plugin-prettier":"^2.0.1","typescript":"^3.6.3"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.139","@types/node":"^12.7.7","@types/uuid":"^3.4.5","lodash":"^4.17.15","redux":"^4.0.4","redux-saga":"^1.1.1","uuid":"^3.3.3"},"resolutions":{"set-value":"^2.0.1","mixin-deep":"^1.3.2"},"prettier":{"parser":"typescript","trailingComma":"none","useTabs":true,"tabWidth":4,"semi":false,"singleQuote":true,"printWidth":120,"jsxBracketSameLine":true},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.ts":["yarn lint:core --fix","git add"]},"jest":{"transform":{"^.+\\.tsx?$":"ts-jest"},"automock":false,"setupFiles":["./setupJest.ts"]},"gitHead":"05615ac078c6b5de8e87cb4353dc7245b075af8b","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.6","_nodeVersion":"10.15.3","_npmVersion":"6.10.3","dist":{"integrity":"sha512-dHYU8JA1HKkIaHE1kRIZ7aU5roX7CXI6NyIF30YmaOwYPcVmuXli+q90+L0sYYvybKWJbaoohV/NjRCT5aTqKA==","shasum":"082c64e5cce925d79c120a37c91f0dc1d6c7a142","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.6.tgz","fileCount":17,"unpackedSize":86513,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdk5PACRA9TVsSAnZWagAA6rYQAIXuiiYqwoVLJtMTIy2M\nLtmVyOjVozrw5cDWAvAFlVVLsEKt26NKLsCzshviUhDGG5M2CL4uWltx6lTu\nKM1XF+mgon9B8PrfIGCszZZ+pncL/dmxTfmfn1S8c2LukKC0ovtvkNbhrMFG\nG4/z60IHPVxdA1x4uPSTZhSvr1v7ErVQT2sc+HpC9CFQgP5DN7HMvMgOYD0K\n1t7D7t15T/Tn1/5Ec0KoKSbFIkeWrFybIJIIajt2AwxIjASgsmF1wqYrna94\nLonWiI1dMVNVRRrOdtsSnXvBsKqueJsosDOtWyFwmeAl9k0QtXwNoRDwlk8p\nLVfiosqGAkpME3rwKSpsE5DjGFcl6kyi34yxPNyWjM4elo9VYTD2FpoAQNBP\nBS6LtypRC0eOrkUcuf3xjMkTG4bX8spKvfckSDDOwLCIYJVTwTrcqUN2TLk/\nt/iY7kmAfPmEVyY80u7DCa89arxMqsgI9dS5RaH7bE0pAql/vSLRHVD2GesY\nwKXSDGpqGEXSNqrQ6kEzTf/p6tS5LJI1OsSr8YqTZ1cvHkqNIP1nPIbGG+UR\nb87s+VO5WUxT43F2Eqr4rUWfDpFSUOAsfH3y77vzV1LqqpMH3UHTuioCFZRz\naCXEaH3yQCzJur96vrBz5y/Hm0YnbgTXdzLHl/zrI4JjHkewZiCzkL5eA5M1\nJOa0\r\n=Tr2z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIE9Sc93/V2aYogJFXb9JtgQtcmKsMD3kxhtb9C2XPizmAiBRSUn5f1+loiIRTIHC4H8bqow003YmSgkOSa6aZO54yQ=="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"carls118@purdue.edu","name":"lilycarlson"},{"email":"tragessere@gmail.com","name":"tragessere"}],"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.6_1569952703865_0.5291389287878585"},"_hasShrinkwrap":false},"3.0.7":{"name":"studiokit-net-js","version":"3.0.7","scripts":{"tslint-check":"tslint-config-prettier-check ./tslint.json","lint:core":"tslint -c tslint.json -p tsconfig.json","lint":"yarn lint:core 'src/**/*.{ts,tsx}'","fix":"yarn lint --fix","test":"jest","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","clean":"rimraf ./lib","build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","prepublishOnly":"yarn build"},"description":"Network/API functions for Studio apps at Purdue","main":"lib/index.js","types":"lib/index.d.ts","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","devDependencies":{"@redux-saga/testing-utils":"^1.1.1","@types/jest":"^24.0.18","@types/mockdate":"^2.0.0","coveralls":"^3.0.6","cross-env":"^6.0.0","husky":"^3.0.5","jest":"^24.9.0","jest-fetch-mock":"^2.1.2","lint-staged":"^9.3.0","mockdate":"^2.0.5","prettier":"^1.18.2","rimraf":"^3.0.0","ts-jest":"^24.1.0","tslint":"^5.20.0","tslint-config-prettier":"^1.18.0","tslint-plugin-prettier":"^2.0.1","typescript":"^3.6.3"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.139","@types/node":"^12.7.7","@types/uuid":"^3.4.5","lodash":"^4.17.15","redux":"^4.0.4","redux-saga":"^1.1.1","uuid":"^3.3.3"},"resolutions":{"set-value":"^2.0.1","mixin-deep":"^1.3.2"},"prettier":{"parser":"typescript","trailingComma":"none","useTabs":true,"tabWidth":4,"semi":false,"singleQuote":true,"printWidth":120,"jsxBracketSameLine":true},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.ts":["yarn lint:core --fix","git add"]},"jest":{"transform":{"^.+\\.tsx?$":"ts-jest"},"automock":false,"setupFiles":["./setupJest.ts"]},"gitHead":"9ea7059ab00ae6432dedd2184fe52f71e9059d6d","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.7","_npmVersion":"6.4.1","_nodeVersion":"10.15.3","_npmUser":{"name":"tragessere","email":"tragessere@gmail.com"},"dist":{"integrity":"sha512-XvAN6svbcaCuL4BAd8q1SuaMg9YyH7COeLhkmkWVM5k5waRS4ISCE2hW+qTpiydU2NYqIHcJYvaFDl9ZGIqSlg==","shasum":"70e5f706f3eae22546102d003b28c126b9149ce6","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.7.tgz","fileCount":17,"unpackedSize":89397,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdp3ygCRA9TVsSAnZWagAAG5kP/jn7Dgrz1dU6U7OCAdhI\n1rP7pSZFdojlB1HNeWzXSXnEnPaGBed+skhNz/UXIDlNgUk4XevIiU1N84GK\nv/va8+091x8bCDG2Po33+pGiJNwyWva403hecO3VAxEdJgyN5SOJYC/g6xFD\n5zQTESitVQaPtVIk7AWpBUoBT5Jvx31+Vr2vPpnCiteLDh3w6LYaTReBtBPJ\nUY+r0uEN4b6PxdzY5Lzwhe4n9b9hl+fnPzNe38JedlNnlQ6EAM59OqETznZV\n0E7WrNw1eclfinzG3DXS2S5fSiGIXNhwE8ruxg9wYmPW9naDkr6yrWFhcZTQ\nVs5nG2DwTRyUnTSE9PjtnBDxVFG1MFMQbmUFBM9pNBYTx+eyHZxnme5tyoqf\nQzEDqo8I/SGQ8d4ffUQ2gPCvqYeACSsX3oTcGamVk8pHRP46Hoz/JctLjpcA\ni2q0Lhve/umC5Lm5mSELmnPNRdp2neB/p9D+erUPBmrf84SFEeGw5+MZXhzm\nke4okOQr/Kg++NSPM3jCmhiYSu4vaHTB53DLVItGir1xFKo0Gc1umGYj/pKg\nMYlqAObxYN3Mu4swRnZW3/yjZCKidIawjTIPl/JMBEkGnMBvHYvj8XQc37Uw\nDVOZjZx0oA44HNuKVhCVfrcFFIItF3Jc1jZt97BjfbghQAJwuH5P9+eMhSXc\ndupF\r\n=/dI5\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQD/hZxG8X/gvG66Re9SfXm1rOqtOkz4hfuGF/JF4DQ/2QIgJ8quArEXeIzfoC59FFBHJnRWkVfQEfXEtZEoG1rHdUI="}]},"maintainers":[{"email":"alexcamliu@gmail.com","name":"acamliu"},{"email":"builtbywill@gmail.com","name":"builtbywill"},{"email":"jase@dufair.org","name":"jkdufair"},{"email":"carls118@purdue.edu","name":"lilycarlson"},{"email":"tragessere@gmail.com","name":"tragessere"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.7_1571257504140_0.6867246257771868"},"_hasShrinkwrap":false},"3.0.8":{"name":"studiokit-net-js","version":"3.0.8","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"lodash":"^4.17.15","mixin-deep":"^1.3.2","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.149","@types/node":"^13.7.4","@types/uuid":"^3.4.7","lodash":"^4.17.15","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^7.0.0"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^25.1.3","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-eslint":"^10.0.3","coveralls":"^3.0.9","cross-env":"^7.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.10.0","eslint-config-studiokit":"^2.0.1","eslint-plugin-import":"^2.20.1","eslint-plugin-prettier":"^3.1.2","husky":"^4.2.3","jest":"^25.1.0","jest-fetch-mock":"^3.0.1","lint-staged":"^10.0.7","mockdate":"^2.0.5","prettier":"^1.19.1","rimraf":"^3.0.2","sort-package-json":"^1.40.0","ts-jest":"^25.2.1","typescript":"^3.7.5"},"gitHead":"fa32ae3c637916957d8381f7b5d4c4a91c547d68","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.8","_nodeVersion":"12.19.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-v4fkPXVmXR9b0/V1eqLYdExjwzAmuFMkol0rhYos2gzEXw8xnEx3pb1RW18W9bNEotptcynfqbgKjYLjWoZW3w==","shasum":"c4a3963be7d63b55de097cc5573e2604c2b8755c","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.8.tgz","fileCount":17,"unpackedSize":87462,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfkfCICRA9TVsSAnZWagAAunoP/1MMx8qMwhWYuTEMUVJ3\n4iyVbbOToyqsi9sDo/sEl2IYTYM/gdlngxbLuoSugNuWuq7Ztw8o0SUsix8O\nUrjOqKMjLL4rc19bXY+NnmxytGV1/CYpTcu0PWqklMKjaPfE1b9KJww0znrx\nox5itbfXTB2+qdrjDYlOL94tvzpqcfmIitZf3+v5bfY73wqBkOZOs6bFAUGN\nNKLbbSCN9HhOyPDFeptqISLI40YSyWKDIzgvsJNfgCEDd3mzyK7KHZ6okgpH\nWrwgHMnxru6EjzI+8QpWZ5wpAkG0himu0Pje00ne6d7/zcaQebwVAKup0JzO\nIkHuuMfumKY1A3SWpFXmKQjSrm4Si9mV74LYUtPvNOzP7y5ex5jZsY025F7o\nuHoAlzY9u4HyasGd2CZKquo0Q9mIFwW3hqJAAmQXWKD3JZPLjVp+Luv9ZSX7\nQKfj874cdAsu5v8ZHqSaxiQPPJNuC0edgalV0MYdiKSDud9DVBvc7mWwHncN\nQ8ZvYfB/kxlVPrFLG2tg3I+RNsl4Niks4S1y5k4bmUT142/4U47LjJgXBmKG\nEno84QINYIgiAqI+U3/mkWOlGW2f2a8R7C7dxUTZ2ekACDCbQ6841ZnlVxcZ\nbVeSEjIj8nvKcRwlnPE3vrP0BBUMzyakwGFFlYcNqOj/204ZMHdeRlFNKvQd\nLMoA\r\n=v0+P\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHMKIu9BRAs2DjG5bcMY4vVYVXGabKfRW4beP9VPghjTAiAxCDuLNyi7FV4cB07JpFuHkNv5ebMGBLCyg0SuL2/S0Q=="}]},"maintainers":[{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.8_1603399816462_0.09519769232182451"},"_hasShrinkwrap":false},"3.0.9-alpha.1":{"name":"studiokit-net-js","version":"3.0.9-alpha.1","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"lodash":"^4.17.15","mixin-deep":"^1.3.2","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.149","@types/node":"^13.7.4","@types/uuid":"^3.4.7","lodash":"^4.17.15","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^7.0.0"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^25.1.3","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-eslint":"^10.0.3","coveralls":"^3.0.9","cross-env":"^7.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.10.0","eslint-config-studiokit":"^2.0.1","eslint-plugin-import":"^2.20.1","eslint-plugin-prettier":"^3.1.2","husky":"^4.2.3","jest":"^25.1.0","jest-fetch-mock":"^3.0.1","lint-staged":"^10.0.7","mockdate":"^2.0.5","prettier":"^1.19.1","rimraf":"^3.0.2","sort-package-json":"^1.40.0","ts-jest":"^25.2.1","typescript":"^3.7.5"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"50ed8f6f6497067d07f356955dafb92732931408","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.9-alpha.1","_nodeVersion":"12.19.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-KcdOUKbJGd00Dh4Y0epelw7y2BTXRQAQbpRBgRIIFFx+siHAKdqsYRovRVzwFM4A4j0dt2u5JT4ES98LAtaYgw==","shasum":"bdd3b607f1653103a2fb5e1e566e063ae76c2f33","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.9-alpha.1.tgz","fileCount":17,"unpackedSize":87551,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfmslaCRA9TVsSAnZWagAAz/4P/iDfnZckQIm/yyp5Y7b7\n7Eeu7adhzacuF5aavsARhNBHki64kCNk+ee1A4IjoJ8L/64loXt/BAJs428u\ntjlA0bzPphFGp8ziooWsCU8KrzEo4wroibLeIJkkNDNblqIIwl63mp8M57MQ\np7Nthmx2J6DiApJQ2tBFBkrsmPsfebcfxojRw6cWklqyaV5C6+hbqGu2IGHJ\nNqfvGJljhQ/0Zre3nX3FaQUR545cpwCzbe6D5IyiFl+mV2gwXON1CDL3+gmc\nZik3Vfcl/7i50rm6pC/jiVEMMTPbXoESt27rOojaDFRBCZNBp50rqlDolUvm\nF5aNO90eNIDMmkAQiSSluyN5uTTadhwCppFWacCT8UGXMwxEKk4Hu/VcZlMR\nGU8fuiicxBh6MmtjsQhT1beQiZH0YInpg53bXgNScS5D2cr4YFEv2bjZoJsl\nKkHvoAENd2q4BTea+p7T++GB3Ukgw7hLjpWlsAJ7Y4jdE8QTJZjlGSdKjNGc\n9G7Q2wfpSGWG09g2535Adn1uftqBq8B0PD67HzjoLkTeq+0PqcI8zQS26Ezk\nL3vkgsLNlzQNLxI5ldNokeWmJwyJvpdbXI4exZAPmg5d4rz6xJfy5d+XanKc\nnNx9/kd232JV6+fEzvUVz371p9YdjmrU+gXa/SsFL9kiQAMq9pbR72BGH9sw\nhhGk\r\n=YZSC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCk3KiiwrSxk4FiiVTHTgWwu4Onlg7nG+I6c8K2yWKqgwIgPXmKFcdFZQb6cLBUAkPs5042tZKm/cxxt/lsnMI0L34="}]},"maintainers":[{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.9-alpha.1_1603979610139_0.27720159682764334"},"_hasShrinkwrap":false},"3.0.9-alpha.2":{"name":"studiokit-net-js","version":"3.0.9-alpha.2","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"lodash":"^4.17.15","mixin-deep":"^1.3.2","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.149","@types/node":"^13.7.4","@types/uuid":"^3.4.7","lodash":"^4.17.15","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^7.0.0"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^25.1.3","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-eslint":"^10.0.3","coveralls":"^3.0.9","cross-env":"^7.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.10.0","eslint-config-studiokit":"^2.0.1","eslint-plugin-import":"^2.20.1","eslint-plugin-prettier":"^3.1.2","husky":"^4.2.3","jest":"^25.1.0","jest-fetch-mock":"^3.0.1","lint-staged":"^10.0.7","mockdate":"^2.0.5","prettier":"^1.19.1","rimraf":"^3.0.2","sort-package-json":"^1.40.0","ts-jest":"^25.2.1","typescript":"^3.7.5"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"9216636bb6d4729dc058aa6ecd63f1d69639d43e","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.9-alpha.2","_nodeVersion":"12.19.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-quu9xvSRheyviYwMIZ9bSzGV9HEhDWMvwCY1TOMqXs5J/ykdNFByOYeu9Pt+CAc/pLJ1IYFeYhfzLNw8JJhbAA==","shasum":"2a59d7b03f4fd369cd0929e46350ad943cdbf727","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.9-alpha.2.tgz","fileCount":17,"unpackedSize":87616,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfmwAuCRA9TVsSAnZWagAA9vcP+QFKyGbGMC90TQ27Sp6g\nqSWA4NspcFpUWW0dbvuNQss6PsSgEjUp4s7NzffLXgpUEUpMrTBk9IbM/oKL\nVP0MG1mu8VXONy1R9y7b55oNYsAD4mpTJbjdxxUSjpxBXg9+s7fmIiiMSfqk\nzKchHN8Rr0UE6Sub4bwKVFlFzpPDBjpyvf32sRn/JP9RK0i9jfdTvFIDIXTj\nn0IzSCDRiWqMMGiZ6vH608CQEDVDqwzcgfC8v74k4OwIyTv1kiwUWAl/cmYK\npaElMjyZM4U0xbZnqzlo40Vf5vKU6/OVMEFI9JvHKTKEkfzhJOg4MeydO0Zz\nY/DHy7pma1tZFQZUCcm8Kt/qZ9Uj8Kdg7+lnCvesXot+PlKXP6taYC10p5D2\njHBVjZmH4QZWoRIWzFHFki5ZqkCPm4I/7+Mh9N7CiafHtXK7she2+nNgIrVy\n4jf6t9ZxUYFcHSE8Y9lwt5m1iV8/sUexr8qfUBxhKfX6lzbxMzTgIDbklni+\nlKdtNqWU1a9n7axzrZbEORBbEgnbwQ/n9Zkd1ObitzNbKcgqO4cXzlwMasSU\nMP+tBGrW68SJYZhiqeCh+x4GUiygPxr/QzjiPkO7faWw4ZcN+RmQM6vtTz0g\nicE6++Hm9U7O0voGvAhEd2h2nQnIzKHGXvGlTM4LVwOBd4D+FpPd2BvZF3vP\nkzWZ\r\n=zU2q\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID0SM6lNv4l49kyYEy7Wr3OLCygAT6yUm9mjGuGBvCEcAiEAwTNzItw8OtJFTJkufvONzcJGveAKAPYENm92YiCXGgI="}]},"maintainers":[{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.9-alpha.2_1603993646410_0.43686676188767515"},"_hasShrinkwrap":false},"3.0.9-alpha.3":{"name":"studiokit-net-js","version":"3.0.9-alpha.3","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"lodash":"^4.17.15","mixin-deep":"^1.3.2","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.149","@types/node":"^13.7.4","@types/uuid":"^3.4.7","lodash":"^4.17.15","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^7.0.0"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^25.1.3","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-eslint":"^10.0.3","coveralls":"^3.0.9","cross-env":"^7.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.10.0","eslint-config-studiokit":"^2.0.1","eslint-plugin-import":"^2.20.1","eslint-plugin-prettier":"^3.1.2","husky":"^4.2.3","jest":"^25.1.0","jest-fetch-mock":"^3.0.1","lint-staged":"^10.0.7","mockdate":"^2.0.5","prettier":"^1.19.1","rimraf":"^3.0.2","sort-package-json":"^1.40.0","ts-jest":"^25.2.1","typescript":"^3.7.5"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"b9bc7b34b28902bf8a985cd3336a1e53dbfecaa1","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.9-alpha.3","_nodeVersion":"12.19.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-N5O8PGdw28HuAakHB6Yeu7X0S7WHq1IipyTEjWnUwslMERWuz2mbXSrn7nD24AhbxG5U54tbEfkDVI7t90fiFg==","shasum":"7dc728ab9b2e91acb7e2a84a75f672a383fd2e42","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.9-alpha.3.tgz","fileCount":17,"unpackedSize":87605,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfmyb1CRA9TVsSAnZWagAAU3YP/0XcyVjdbLV3xOlajI9f\nuQth1GN/0eFUONvR9vKnyPk/9mahqhFlR7TLhU8g57Nq945MWiqq1HYDO6db\nzPpyYy7q2Qvd5ZJAGDfSnkEYwlAIxZPLiCheZHOU+gldluIOy2kVXTaKl/7c\n9PseHX0bcs1vU7ZQi6azGu4atvI2f1jZGhiIiLq04q4zC00baURxoZ65+U6d\nn5M0ujnPJsqs81/9rL6vf7lDwCYkAM5UNDFn+4Ou6Q16CDt7OYIvgH+hdyFN\nlHZwDElZGV3GkS6J0Hnn7erisVa1Xil8wC7W2TaJCuVWEiQ4dEFjK0XHOCyd\nfcFjif1Gm07jR0xuIpij2KSQZazkhdKjR5JhgpT0srePx9Mst1KwzDuKoqti\n/8POwqfFDyEP9DL9AxJqFrfaDhNdLw3norIUzQkVR8XKCOiO1AM8Ek/ddFA0\nUWQaSKvOXpriqIqXO7dMROj2r6gP9oYYt03QhQFVkoMqPdT/zSCXHrP7iac4\nHULuJgQJ6ra+y4+NsnjVMEluNKMfjA01oaKqz9nOI5Rp7z4YZH7gYDYL/9vv\ntNGstjHI3OSxkWtrnHXixSlaDMvcAdqm7giAP2XLBUiO9Y2kvVkitjFfE21Y\nCC/vNW/huShAc0oLPTRT5XKbefClSMEPhdxq4b72lvdKc+g6Z3D1MeNJzp5d\nujzo\r\n=IdVr\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCnjJ9dJPsm5mPYg+EEyx7fNyCJuoHO5+gHy3k2Eq9A6AIgTKGdwOJpDbRA4fBgfhh2I2rk0x351K1w3zXDQmcmYxw="}]},"maintainers":[{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.9-alpha.3_1604003572619_0.6594722005979312"},"_hasShrinkwrap":false},"3.0.9-alpha.4":{"name":"studiokit-net-js","version":"3.0.9-alpha.4","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"lodash":"^4.17.15","mixin-deep":"^1.3.2","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.149","@types/node":"^13.7.4","@types/uuid":"^3.4.7","lodash":"^4.17.15","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^7.0.0"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^25.1.3","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-eslint":"^10.0.3","coveralls":"^3.0.9","cross-env":"^7.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.10.0","eslint-config-studiokit":"^2.0.1","eslint-plugin-import":"^2.20.1","eslint-plugin-prettier":"^3.1.2","husky":"^4.2.3","jest":"^25.1.0","jest-fetch-mock":"^3.0.1","lint-staged":"^10.0.7","mockdate":"^2.0.5","prettier":"^1.19.1","rimraf":"^3.0.2","sort-package-json":"^1.40.0","ts-jest":"^25.2.1","typescript":"^3.7.5"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"1296880cb29c005f7dd553e1fd04a7488dbd8607","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.9-alpha.4","_nodeVersion":"12.19.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-hZ8dIdW9Q4yMTKfSj6wxnY7FcyL1llQgBJ2M/Kl2m4ySP9njXb4r+8EPTZ+sQIFx8WYRmwUb7a2uqxhf3HRhOg==","shasum":"514f2d861ad7a8d08d76a9ce103aa7bcb7f7643c","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.9-alpha.4.tgz","fileCount":17,"unpackedSize":87597,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfmzPuCRA9TVsSAnZWagAAdY4P/2EjuskbB7pzo6x2bfo9\nB1mOzZ5prVjQjk8DMrPsgr1PL0u1oUkv0UOhB5lprBby/KHewUpe3W7WKqhr\ndIM4SLo8A3LevFFG6lRzPoFI+VlnhClMVZUfNf00Bfa8cINyY3Rn3HfVjmyk\nyuEqXGI5pXG5PaqRMqunyLWvqQkyGHZ+mQWLOo5VCHoq9H/6xoAZHkK1Iz9b\npDTeDJCQcLGITdApfxJ10QbBcAaI3YDXN39UAsneN8LNuOlXOdjDtCMvkbf9\nd8hVkQiJd9hQ1BpZh9fhPaUjn/Yj3ytabImRmzQGV0oeFmLHBlp6l6lpXKCy\n06TkmSR4Bsd+Xo69Wy4iUP+kPWEpmOYl13MUxqDMJOJ7uwQJKLYFEQRBimZE\nfjR9i6sazQSu3YUDikEIB7l0JX+E/MgWpByN8xpo0eTaxacRT3++jkt3kOur\nWR0zzGY5BzmtfasZy974VHS2GGVp39VlVErUG+1JS4RcQHtrPSqZ9Cq5mcEA\nAuNeNof3Jzcno+wRd/Gal/6ZJchY2C+rBa933EmXo/8E3DPIElpS4aY8txd5\ndQI+9ecoy7c97bqK7MO+mhgDCXA6SOm8NUEt5+R1BSSkqiH4ZY3mb2ht1xRe\neFyOIsEWJRWr6xMPi5eKXpspA29cB1vfSPXPrrElmXBy7CIZZTXN/vZzdgEK\nwSVk\r\n=H8Cj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD19fVsuqS/+RMDzAaRgmIikuOO+C5DRYrp+TYAQemHiAIhANyz3XiVsoDyJlZk9IZXmzO5Tqdd4sDr8BfVsnFaxXyF"}]},"maintainers":[{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.9-alpha.4_1604006894343_0.7435905083780066"},"_hasShrinkwrap":false},"3.0.9":{"name":"studiokit-net-js","version":"3.0.9","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"lodash":"^4.17.15","mixin-deep":"^1.3.2","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.149","@types/node":"^13.7.4","@types/uuid":"^3.4.7","lodash":"^4.17.15","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^7.0.0"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^25.1.3","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-eslint":"^10.0.3","coveralls":"^3.0.9","cross-env":"^7.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.10.0","eslint-config-studiokit":"^2.0.1","eslint-plugin-import":"^2.20.1","eslint-plugin-prettier":"^3.1.2","husky":"^4.2.3","jest":"^25.1.0","jest-fetch-mock":"^3.0.1","lint-staged":"^10.0.7","mockdate":"^2.0.5","prettier":"^1.19.1","rimraf":"^3.0.2","sort-package-json":"^1.40.0","ts-jest":"^25.2.1","typescript":"^3.7.5"},"gitHead":"9390eb685b5d5f13f11cc6cc301c8754c56871ef","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.9","_nodeVersion":"12.19.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-VVNsOjqr6BCux9+OBmY/OKs6Hr9j2FxMsqWa6PU+JioET5dB+HZMrytRPQB3eOoU/gCKHf4wTnrdPCXmyb2JuQ==","shasum":"c3c5cd8ed3f7cf63189bed99db7cbdb68edf09f4","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.9.tgz","fileCount":17,"unpackedSize":88311,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfoBaFCRA9TVsSAnZWagAAqa4P/Rc3KsB2ydQ38TJe/C8N\nev49TjOoLYL4WuhQ2MYbrXaNQ8fgSUk1hjOjwT0EYg6SEGCmKSowsmwAy0zt\nFyGbZ6Te8qeIKV3ewJAOrhVhmIb2Gws5wwB6ExRk8e8yD9hXBPhc67xHU97h\nG8UqvUt941pMEovLjrEmeqUtmqOWstmlVEdqYtsXt9jyltYVu1HC3Y/2qxDo\nBGjLHQsctskL6gqy5FacDl1/G96gv4FV2vtc4FbGXk9z9Hiym86zPNvK4QKC\nYiiawh2+3bRq6rnu+Cut73fOAB3/DHY+ZiBIeOni6LDutzPHydyICErcZiLg\nBqm899sF99AfiwOVwVyWg1eq+hSstcleGs6n/BNuOOQfxagjP6O5wqqiElL3\nzKpBwGR28kHYOg6lmBJLbh1r2DK+Cu15I9ooKubDMslHEGsTUvWhLVLp/aqv\n4s7E3rl+AguxkGJcBbh6NRzIuiaa2Ct4VxlNotVHTvQaffBYDvdLOVhx5yLX\nhgnRXmb1gkLYJM2LrmHJRVKY812jykJv2i4M+NeD3P6r8DagNbJeMU92hHko\n9Fvpim0x8vsvond032R2UHF9Ld2vIxvLXU1HeGv3aP264UaxIj2ou6PeUzOx\n67pTdq/SbxfNsb0L63Rd8Ipifmwb1d7o9L5PcM/xVpdZ1fuLfEZkpsbBIrvm\nhKoT\r\n=1ri7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCvadmKwaPNEaBcvU76LyGhBaXQHBMPGKJH+OLzC7N02wIgeraZDH4etOgxdva/ARIvIYBH+fw//LcA3LEr9YoFzZk="}]},"maintainers":[{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"}],"_npmUser":{"name":"jkdufair","email":"jase@dufair.org"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.9_1604327045394_0.2218570404805713"},"_hasShrinkwrap":false},"3.0.10-alpha.1":{"name":"studiokit-net-js","version":"3.0.10-alpha.1","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"lodash":"^4.17.15","mixin-deep":"^1.3.2","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.149","@types/node":"^13.7.4","@types/uuid":"^3.4.7","lodash":"^4.17.15","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^7.0.0"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^25.1.3","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-eslint":"^10.0.3","coveralls":"^3.0.9","cross-env":"^7.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.10.0","eslint-config-studiokit":"^2.0.1","eslint-plugin-import":"^2.20.1","eslint-plugin-prettier":"^3.1.2","husky":"^4.2.3","jest":"^25.1.0","jest-fetch-mock":"^3.0.1","lint-staged":"^10.0.7","mockdate":"^2.0.5","prettier":"^1.19.1","rimraf":"^3.0.2","sort-package-json":"^1.40.0","ts-jest":"^25.2.1","typescript":"^3.7.5"},"gitHead":"fc7a2ade3a460c2afb82c0170adcc471db32c3a4","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.10-alpha.1","_nodeVersion":"12.16.1","_npmVersion":"6.13.7","dist":{"integrity":"sha512-uaicdkhfIFMmUgCBQ0LpZ/8rpBJWbqY/NYTnxSLceUgOptnNaVVUe/JGsq21kc8fU/1Vetg+/h2uISI06RKYwg==","shasum":"ee3b10d30f8bc5793ee54216b8bbccedf7da280b","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.10-alpha.1.tgz","fileCount":17,"unpackedSize":88516,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfou8+CRA9TVsSAnZWagAAGuUP/AzyikB8NejNvddnd2xA\nRrXM3UAUODJrYN45UZ72Lc9X99u/O0+VxqpRNqnarnICNZaKuFU58oMqxXJL\nW6JUu1bb9ebwu/dYFrwCyp+LWPPM+Gu9neKzR++srJ644IrURN3lr5ZsvDGS\nD/M7HzAXExl38UYcfeIiuzcjPjoJXeYPkvDUZ/jV5oeg6RZvFHBPM6GQY9fX\nSdHdSk6u3Fa1rMSRkp+hmIZ2p7pxVUGXsRUT3vNsFkepRlDnjmE+xpl1B7eq\n88Gj2WWmFGBpUubCtNn6z9Ffny4RPXNGF+02UBW4tkC/p+MIFSGs2BbRnR7z\n1SHEO6fJCTalb36Ak6JPj42ZH6lbK5cq8lr3Q04m79p2YlZBzz3zJe1fiz9h\nvSBEe165Ot3quzdg+SVQ6vYWIbiwDGH/aZq16DT746HlsjAUDv/0RPu/xsTg\npEbYqZH+YBTd6P9fQnqJZrXorltpN8+Nb67BaWBpT6fYv/JMMa9XdvcAuIfp\nIDj47+N9MUFOBB8cqVORvaATTRgr91rHQPZtRiTnxOau71OmdNw+/t24bHUm\nW7riDQlulm23qtCVr9+4tYP5DDWo9ZWQ7S7jjN6bEa9pA214YsoMSBHTvpwT\nBekBmlIGzOozOf4LyiAkvFel5MZ14xm22B869jl5fY/qS0ZxJaPSVQTFg4SR\nd2ej\r\n=fmYn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCEWH15Zfm+qBqXrMTzukfPl/tmdoAPK9mzxg4auVfNMwIgauo+CWY9iYCVhskY8uPMkLfvxb/75jv6+QCghoTzXD8="}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.10-alpha.1_1604513598088_0.7909409886591685"},"_hasShrinkwrap":false,"deprecated":"this version has been deprecated"},"3.0.10-alpha.2":{"name":"studiokit-net-js","version":"3.0.10-alpha.2","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"lodash":"^4.17.15","mixin-deep":"^1.3.2","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.149","@types/node":"^13.7.4","@types/uuid":"^3.4.7","lodash":"^4.17.15","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^7.0.0"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^25.1.3","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-eslint":"^10.0.3","coveralls":"^3.0.9","cross-env":"^7.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.10.0","eslint-config-studiokit":"^2.0.1","eslint-plugin-import":"^2.20.1","eslint-plugin-prettier":"^3.1.2","husky":"^4.2.3","jest":"^25.1.0","jest-fetch-mock":"^3.0.1","lint-staged":"^10.0.7","mockdate":"^2.0.5","prettier":"^1.19.1","rimraf":"^3.0.2","sort-package-json":"^1.40.0","ts-jest":"^25.2.1","typescript":"^3.7.5"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"521650ed1c3d6f711f940e18a944fc89afe5a644","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.10-alpha.2","_nodeVersion":"12.16.1","_npmVersion":"6.13.7","dist":{"integrity":"sha512-n4g3x+blMbLnrrDhg1qRNTl5TtnWt4b2GU3Mf+nnhY1h0yNsjTTBaGJDcLH94CmFHuGgzSk1zrNLBGmnhfU/Ew==","shasum":"a6e76eaa29d22080e9f5da4f7417888811ca710c","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.10-alpha.2.tgz","fileCount":17,"unpackedSize":88516,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfovGACRA9TVsSAnZWagAAuhkP/3ZAXP0t2WDNHyj5PM2q\nCEkgg0u+JIb62A2Pdf0qQ/Vgtd8miqAghNkBkYABlipV5WvFuOph8XZGuy+5\nI2267M/3p6wtNumTO5XOQwEdBR4zXJqGgSdeQJgW/vYB6V3iVlCMGFkXzMRX\nOzef0xnlv4Pb+3JGU51kL5GhdYvJnrjcbBerSBdpjjO43xrpHpD0R2eHOYHd\nVlhoVCHRYlecyg291Cu56K2FpESSlAKdBb6EVBJE1MZ3TgB4ZRHkzo5m+yQu\np3h04vrcisTgrPu7quE5JKM43FwgpzI6q86yPwB5Qxx9VeyJ88wPQzVfueiP\nyTjrTgbCg/nMcIifgEjPO8vhqNQiX0fSQMoHuJNZX+sHsug+HvzTXeiQW9t2\nSiWfVUM+GeR0Qsg6CkMMOzrbkc5daxLnsgYF+iB9P9zAiA4UswioSiHKx/TF\nVahdaJR4RDN3NQdsPpgZ1b0m8KxWoXsbxe9CL6J5D322A4YP7CfOFe03kJpm\ns8e7MTm4ff4/UOlEYHAq2OhIm7j9K4npY6XBZgOHUQMWf8u4MTgPdbZRq9GF\nkOuitxlusgYhgM69Z5donLRzPtANJRxysEmwGuDgAkHlpCCU/HNpW2EqO1hT\nrIaY/mu+UTIJkWISVK2TQZ+PstuEMs7ROCK4+MiM6J7H65TkJUyfjHry89jn\nk4Hb\r\n=e1tO\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDXgubEuH9AKGBnuCKJS7w2gHdT8ZK4jHRQ/Feg1UVyMQIhAO3IN4Hn9FOzXcFGlGTOK7IHgRZxHH4ranrg8ycopF/U"}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.10-alpha.2_1604514176160_0.7834952518208691"},"_hasShrinkwrap":false},"3.0.10":{"name":"studiokit-net-js","version":"3.0.10","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"lodash":"^4.17.15","mixin-deep":"^1.3.2","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.149","@types/node":"^13.7.4","@types/uuid":"^3.4.7","lodash":"^4.17.15","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^7.0.0"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^25.1.3","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-eslint":"^10.0.3","coveralls":"^3.0.9","cross-env":"^7.0.0","eslint":"^6.8.0","eslint-config-prettier":"^6.10.0","eslint-config-studiokit":"^2.0.1","eslint-plugin-import":"^2.20.1","eslint-plugin-prettier":"^3.1.2","husky":"^4.2.3","jest":"^25.1.0","jest-fetch-mock":"^3.0.1","lint-staged":"^10.0.7","mockdate":"^2.0.5","prettier":"^1.19.1","rimraf":"^3.0.2","sort-package-json":"^1.40.0","ts-jest":"^25.2.1","typescript":"^3.7.5"},"gitHead":"0f834a971343e0204664178e2590485ef87d39bf","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@3.0.10","_nodeVersion":"12.16.1","_npmVersion":"6.13.7","dist":{"integrity":"sha512-MLIlJhYuZynRiUbo4rW9nw7hK5dI9eg2+RxDXhglVQZEfXjWnxBypn8Uwu751n5w53CmuSy9Q/uU3fhp34YiFg==","shasum":"ec1e564e44ebf1a4e1f5de6bd78a1c416fa3d40a","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-3.0.10.tgz","fileCount":17,"unpackedSize":88508,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfpFY/CRA9TVsSAnZWagAAv8kP/0gy8cNd3kNZMPLGcgZq\nuHqdVf+TxfkSNGswqFOhFLg2XqQGCQ+9C7+cLHz62wS/jqmXdzlXHgK8FzW7\n9UdPPOpFLQXBl3NYIX3rLnaNELezH9jwbObjXPnurJaC6s1ktmDLlkY03i3M\nr+Th4aT7ljGNcQkhkXUCrrw4CSl05IdW3f5jTjX/YJpZUwdlOvpRyXq24fdG\nGBhXrGf3iRLx6/D4ix54gphNM8J2Dy93o0ulg+u+kFlFHA1H9HqZpBL4zCEH\nuzAdA90QwjOg27xk3gz+E5noHPmncp9tjdP0BehN/DdBv+ScIi0zJ/YKomWQ\nba1YuzmDq3hFVgH0AiK59WQCXVljUaNi7leK4fM3m7/5dtE7RusYs3piSZhB\nabXJdBAFCSij0Oc2yOEbkQPP9O8kxAWcnreppkwCS0iythhyZiowe7M6VDxG\nUkvMcbL4cv5qAB94C1AuVuCAMi+P9ClXullD4URaa9FqD+Zgw9ihgDwryAWc\nAUtQ0g05UxXenEZNdImlaY0ZdeFI18MVNmQKpnvzcsfAO1WWzYmG8cScMDHk\nAx6SuQOn0v8GFjaAxSraPENn1frBM7QJKC6/l4XuToDJsvI4UQTMj8K86uxt\nxRYUcP5oG79edcHEoUTGkQQjpDL/htsQXnfrDcJc/qimQFAikhEmMdpVVFEo\nUndn\r\n=S56j\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD+d4Q54tMt7qclOtVRwrct5xajJBHvuYPivNuC0ogekQIhAJENmm7vNtpIu0DCJmMkl6tJkWD4b9a9mFAcvDyyeHdI"}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_3.0.10_1604605502554_0.954460287809421"},"_hasShrinkwrap":false},"4.0.0-alpha.1":{"name":"studiokit-net-js","version":"4.0.0-alpha.1","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"lodash":"^4.17.20","mixin-deep":"^1.3.2","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","lodash":"^4.17.20","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.0","@typescript-eslint/parser":"^4.14.0","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"3.0.0-alpha.3","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"gitHead":"ae536113970e0ec8aa1edfd303044c9bc507ce31","readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.0.0-alpha.1","_nodeVersion":"12.16.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-58X1LxuqoBfPKJqPoWxZjZSDDkDWQPrG1y0OFEtYhgASdt5jGJ/e0wn7yeQz/Yp2f09aauaEXW3sqYTowJyIqQ==","shasum":"bb5acd3497dcaa3088a2ec7cadf491913ec9ac4d","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.0.0-alpha.1.tgz","fileCount":17,"unpackedSize":91602,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgCfB1CRA9TVsSAnZWagAA4uEP/0XcCMfF7rVP6EuNV9JO\noWl6y12f/20idVwbDMdm7SpW1BWHo+wLUEBlGe54BpMPfPJ5XePiR2zmXMLj\njDqAsGD8LVkGjYCcmCK2htKZy1FESFesR2ukeH1Qi73DnmEOCCxAnLe9d6jW\n/aqfbrlThraGnaLoBhC0KkipjtJCxXo57zU9TA/bqFJhk+vcaF2k7T8pU4Qj\nJNm4y+x5HOgB90R+X6lIXjxKU4msi/aqyrUD0ZckmtlJBgzO9MjAlqPjTASQ\nJKkI3YvM46w8AiUskAmygfzA90rJ7yzcCV1s4eZx9wpz5RNaoghB/wUdfo4U\nB9w1tnjYjVtoGm7QklcyLOZXpugqblIWbPwkVDlzMzMYf23oNz7QbioYUGZO\na7gY3yXdHcGSvxMpIXQJ1FB5nvmWoD7aeoPQAfDWYP0u3GTyuc0vVWmF1Z5W\nSB8x6g8bB9269eaXTFlEoJFeiu4OLOUHsFUx0aFM6kqw2lHDdazwfS2V4mfz\ntfEFON7bUCr0c86j/vy4Get0+HLYml1pFgfzPnJPw0i0r3q3w5rE4Cyf5Xen\nyVIou8ffgN5ts6pdoVAjd1/blng7JaWxT5+8g/0FTGwMYmnLo7Sq6Naa7yDC\nxkcAoskTYZqXKcpX+P0jFhgxR+82q3HU/0O5LAcwqqHwmB0uSwDM+vDD+DJZ\nSmKc\r\n=3nmH\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDyJ44pBr+1kf+Pxp0JRiwd0WVOSyPVSOEVtWzX1yKoFQIgbdb3xqD8QcSjn6BeKseXVO5vXoTvDD7eVf41min5Zew="}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.0.0-alpha.1_1611264116344_0.7061247537661177"},"_hasShrinkwrap":false},"4.0.0":{"name":"studiokit-net-js","version":"4.0.0","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","lodash":"^4.17.20","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"gitHead":"8b5c5a5c4eeb9e3bf606ea1f5914eeab01cc22b0","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.0.0","_nodeVersion":"12.16.1","_npmVersion":"6.14.8","dist":{"integrity":"sha512-RJxt0eVZ91cfFmmGCer3S2/QjHjAGrjS7N066LAVAeO2LfmzCpweJ7aODNSJrYGA/B0tVqSKfQTtn9Xfw49dzQ==","shasum":"bb44046a1c33a7700b204168bf8c7b90b537d0f5","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.0.0.tgz","fileCount":17,"unpackedSize":91628,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgEW/PCRA9TVsSAnZWagAAUsgP/2haBiLDUBMglVjlsoxP\nxaF2mdhLMEBHFOXAmP4xj3RqZ1YhfG5pWlzBYLQCOdAaIY2jcXDctWc1zh0J\nkpsednOAMh0YBj4f7PCexgQbLvDhxVRnI7ZdvJAbdyuPZgJCikX6QKjTbX5s\nA5sZcxNznHVcWUBn8qBX4LUo7VwkBYbuKENw1rlZvRtYywNdioVrMAnu8ORZ\nMFZRP+OcgKWro/iTZ9l7xaU2YPuLnLBF9+7CU73Dg3Dh9wfI6VymhkSnuz0G\nfJzu8sZS5Hmi3CpJZO2i2P0/n3XZHyqWxlNcqB7kDZ0/uoUNQ6hQnoFdakxN\nCTGecKV7vWxZrteiiwhf0MVGg6a7f4CFhmf+Z2izdDapp9m92sYxYts8pfc/\nWReh8uoEIwLpq+WZQxwlh3Wyyw7Ds0IEMn+tHHLkk1PDw+M2iQksWmHFecIZ\nlQtFd3TBjlxKeVSqKtV1UNeVZ0MrUVMsoKLZl48zp/3SMYS86vhGajF5NVWg\n06PLE2yXvx1WLR2lew9Ap33aC7ehRDQ5GX4mv0d2p2WyaA3T++zC57Y/JnwG\nj982y2OuTibG6FWLK5u2FveFsKQsqW4RYq2GB2EMWKwZysA7KMb+H0PhVT+Y\nyrzAAmziQaA0vhJ6uCgh4Nneyj7dyHNFt6NKudPt2qIKW0X6wIAQ6dn6YF7d\ntI1Q\r\n=g4U6\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDMxHgURgm7PbJtE3FmIxB0VK3tpsogd7a4RCYQnKYKhAIhAP3slM/2o6ERz29AZO98vYrC2gu6RtT+dPZabvOF2TUk"}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.0.0_1611755471553_0.66792635185818"},"_hasShrinkwrap":false},"4.0.1":{"name":"studiokit-net-js","version":"4.0.1","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","lodash":"^4.17.20","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"gitHead":"0db1dff37c28f85a99f15ac7ea6b3ecf22ce4c6e","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.0.1","_nodeVersion":"12.16.1","_npmVersion":"6.13.4","dist":{"integrity":"sha512-kU342hW+NHnhHbq56OlQO/p4uVxfsm82ZxR/J15EfqqkH2IjNebKbZgKxaU+4cbHCUHmUNR6cOBRm0xIhy5Rvw==","shasum":"dc8c9a4283440d15b13c10ec4fa9ca6cbcbff236","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.0.1.tgz","fileCount":17,"unpackedSize":94118,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgEzstCRA9TVsSAnZWagAAtZQP/0Od70KKb1mkORQ7cgm1\nwUbMq98z3q60sV4uThtQXhDT/YsOOTcCuY2TtjMV7u1wzzpWHcNznIN4jh3v\nEq2F41AkXuPYNWcnTaQESctTlMnNyEnhYpesJZPpiTX6A2Go6FxzGiUWjTJU\nIk0ky+qy6rvRUTUej7kTiexXHA20CG66O2ssvoV0cDzJbaPiV4E4AZObwxde\nO0FrWtJNCqUALwEuQYKCpKYjDAIZ6G3wouTLcEsJYjsAIIGHiVSGDS81HfDC\nMyZziimAPGRa6Btsa2DIlL+iv9H1JehirO8lFg8dlDYqsZ4G8gkN9hknARxd\nrmd3G6N6sHdvIPrasyZN7cBtdeNv4K/f8nvScKw8X8osxifkYdStr66BDbpN\nrX6Gv3usrjITv+GGaVegGMUU5JFnLDBI1hnEnn7pblhV+tIPjwqGLZkpRAKq\nGitrdI/4xV/zi7Sij1qFpG8IibYM5SKSzBGa5ULLX6ImR9fQaA1rS0pIEywp\nACLovadUcQ4MrKBt9cTpVmkvoPTcDYhq4hYGzVAP17EruhaBeZhl/Jo/f2Zu\nklrsgcj6tSO7cu4uj9S/DVY8G7S3+uYMuL9X1qVXg2++YoxZ20b9+UTKk/46\nQBP7tl5Mbtjj3TxHHaAMV3Ldcmh+ZSIoIUaJ2c2DHzwMNAEMHHAfSUcYLT74\nR/VD\r\n=hj6D\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEFXnICSunYOaz0ErNMIifL3DGEPx3DNvfmSeNx1SqDBAiARZsXLi7ZtgvgMiK/THOg7AKOY0Xz18Y2AFfa42nQQfw=="}]},"_npmUser":{"name":"tragessere","email":"tragessere@gmail.com"},"directories":{},"maintainers":[{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"acamliu","email":"alexcamliu@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"bgavin","email":"bgavin@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.0.1_1611873069232_0.6265079035491841"},"_hasShrinkwrap":false},"4.0.2-alpha.1":{"name":"studiokit-net-js","version":"4.0.2-alpha.1","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","lodash":"^4.17.20","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"8af93ffc8b2f11605b35bbf8f6e7d4c0d4a77b97","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.0.2-alpha.1","_nodeVersion":"14.17.0","_npmVersion":"7.13.0","dist":{"integrity":"sha512-46vVeEB6hBc8dVHBZSWQm+Kx2tTBDNzpuEJCwwUTRgaXsQMz3/isUSLF0EST9JrzOPBmwS2GnuAupz54ooBxIg==","shasum":"58338c120b024a646bf707dbf4c7da016392f687","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.0.2-alpha.1.tgz","fileCount":17,"unpackedSize":91733,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg0yi4CRA9TVsSAnZWagAAVe0QAJwkdMpY4SXbuOgwj/qf\nZ+eHxDzF3dhwc0/hb+qPoLyKaCVTavwwl0JEn26bUEAPy4g+evOGAMoT6Mvt\n0TwCHV7KjWelLvxWcbkrf6sQVS7Iv94cwQR3cL+YlcKIyZeKt/7aOjxl7wI4\nb/IZV9UbNNLYvMa++mV09/rok50yeg3mH45E5tRzpz8pdKWupe3cZca4OzIZ\nNDb/P1yTMSWPt8iRTsOPrJ8tDrMHX9aR9lXn1f+XfQTdwnF2hqnX/+hK2ASH\nLNOX/Jbey0Kn0gM8km0hdCDF7sG0iIDalgl1ERQTjO6PYyJsrgVghO5xtPL4\nyDc+MGsPxhIYFxTQav5H/V9lcwKotqjwVQNpCGff8un/v5U36tVSZRQZHf5D\naQBYYC9lem/kEmNE8Pxtt4gytdK0avMufH+cmRIVd4t64FRpsaJMxQu4uU5Z\nC+Ij6PJCF+Dp23/J92GRD3PryqGICUhA6OGLtw180F5DwZJCM2uBR3HSZQp/\n2Zq314w4puzZtbb/4E9ROKtUR1R+OfLAW2VZP48uOKsowNYGDev8VG4WF+cx\nw5H2vA+01kzsH3gnHsocmI1+PXNPtvZZdK0iU26w1ynITnnRtutPgqDShAw+\n6drpbFsQ9idvtT6g3Uw1hllXla2rFM0wzN26FXrfFF6w2ROwfuX/YY2OeL3Y\nScBO\r\n=GkCP\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCh5CYoYegGHuRmD3UbZ6rcp5M1ytIxQueivw1cnE4G8QIgTGEu7AR0J58BCngNeBwVDtU4QVJT+Tb26qCvFJwfBQo="}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"gregstrasters","email":"gregstrasters@gmail.com"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.0.2-alpha.1_1624451255654_0.5386745295329565"},"_hasShrinkwrap":false},"4.0.2":{"name":"studiokit-net-js","version":"4.0.2","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","lodash":"^4.17.20","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"gitHead":"1e52517e96941d0880e10b4bbb79b9a5ec4fe85e","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.0.2","_nodeVersion":"14.17.0","_npmVersion":"7.13.0","dist":{"integrity":"sha512-0Twyr9AdrXpc4p372jP6y5wVc7HX9dbiE3cNqFhF8GmLYnbm1kmSZxppskTTvSpIMqE1fIZ0259zQSc+qhCFpQ==","shasum":"8b248d7ab281d40ce06dbbf4b76e34f4881e408a","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.0.2.tgz","fileCount":17,"unpackedSize":91725,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJg03adCRA9TVsSAnZWagAA6U0P/2ZQ/hdc6D1Wz8WFj4TJ\nt9xB+WlxWN9R/EfDZqAWzIxrc+voK3FGe/msm8T9lRRF8GWo5TPX6ZKCfYTI\nzDrWLCYjrAfvkwOtYmvHc6heLnPQ+hekiTKiRJBVRK29Ffk1gO5PMDXXHMv6\ncLH+8F1WERMSK+ihTkbhyiMBSl2BiuBW6Pa+K/DHht1HHrLTk3L1lCa5xOSN\n+R2Rsd1NFz0cIDUfg9L/etfCWCB4kMvglGGXqVLrDMqW67UPKWd2BHJBG6ru\nMrI+vImC+26Jp65Wfys+UEsnbsCWIVBX+ZvMZ6k++20DzmZItU+nf6OBVK7G\nh+e1LMjP2D95c8O13LeCHEOjOp4qy3/WNIovcAaN35hYgLEdbChRiznt4CVT\n6MQBBO0va0nTpPwtO1kN2J4jRophaEhIayy36SLH2hceNPBCOHTtTY46LL2l\nQTqjF/h8bAaOpMPW1SwK6S+XuQeE3IeJMeuHwPc/DRbamanFJFuR3gxfE3G1\n5od4zr5vipmiC6hzwf0B+qQOabCxNdxw6yIcSvvD8gYG/PGGUKgXFTYP5TpZ\nP7Bsvdy5sYjRPiF+5X2ufAMN+fnTthtZe7RIBCFaWZyygkqe6SedhrvTTO8k\nRv7dgMCawQED4tpDFYaNB3kpQWdT7fb4DqRGeItFOnz0sCXS2gr7YrM+/Z6p\nzy1z\r\n=wp2u\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCSDBFY9COvWoOF2ACpI8awWOBPH+O1EaWHvoQP51O/IwIhAOw2uql3Q8tTbNgRKr9ObiLmk1ZMAalovDqqWFQ3Ra35"}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"gregstrasters","email":"gregstrasters@gmail.com"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.0.2_1624471197019_0.3612386638623226"},"_hasShrinkwrap":false},"4.0.2-next.1":{"name":"studiokit-net-js","version":"4.0.2-next.1","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"d71961079d3248be29649f1e4b4fe0a4b5fcfe07","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.0.2-next.1","_nodeVersion":"14.18.2","_npmVersion":"6.14.15","dist":{"integrity":"sha512-ZoVdwj+nDFV0FCgAzjiqIgVZ+B2VTuUlzXB+OwPMQsEveknRl4GjAbTIG8EkXwaBNhfsn0EskKbVo9Uyn7fWTw==","shasum":"1a851fff89dca15cea1002992513c895250ac8b7","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.0.2-next.1.tgz","fileCount":19,"unpackedSize":93534,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhulJxCRA9TVsSAnZWagAAYqwP/iIXbjGSdYNgEGbvEqYV\nY+CRcqOCooZw7p1SpsToA+YDN9UqdgFX/uEPAjzR14qE4QVcAyabEtniR2fx\nTSXmRkIVZthkTUzNRoAD23Enhnf2dE2Uy31b+mPhaydYI7j/pJB+G7R2fNGg\nnM9unyn7a2mP7zJoBo5V95YEIqG6gbEK4TVcFVLrkmFOayuTBXItiYZhoRkb\nmj6SKl7H83hew0kBEi4rVaOkevHEb7M9EfZLB0TwuEibcquyF1feOkd3Tw+y\nQ//FQldgcCHxUYb2yGUKodaYu3rRIyINlmS1ycYwQy5A28pA9zaiC8aA4VqV\nHJgY/4LE5pqc75WFLjzGRvgtaJxOUyF/mqAWjhmD7MnnJ24JmfTmXdN9qgQQ\nByASx4xiBmrlAjxa4m0Pb+YUzIUltcy/x0ywf4e+WRy8+q9EJ8fkVPsy+OQZ\nFnBjMNXU8PPBpwa7Dbon/2l0JBnPj6WPVtPsHgEiz2gQKOoolewL4aL6ObWm\n93tkL+hBvkgLHS/kySWDu/giR+E/0VIrcq2TEByZQ14yKhokT8fgLHXgu8Mf\nEIfK5ZeqCQeVueCM4FvATunJx6wksccixiVKT/k34m649/2ukyqNaRXb4XCy\nMSDXxNyvLk6droZ7LQ92DjSUN8iJKY+wqj3Q7rx9jEcDC9rbVdPn5o6+hQJX\njP0X\r\n=TAuc\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDhqC7XxM1OzDyEL54lwhzUbkgehWHDxerocbmv0al86gIgetLfaODe5RxOfft4QjZfirEv9hK5AWfjpqExcGEb7dA="}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.0.2-next.1_1639600753766_0.9203697990316069"},"_hasShrinkwrap":false},"4.0.2-next.2":{"name":"studiokit-net-js","version":"4.0.2-next.2","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"58f6f9adebdf00c153df20cee1e6282e0140cda0","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.0.2-next.2","_nodeVersion":"14.18.2","_npmVersion":"6.14.15","dist":{"integrity":"sha512-nU9BtVTwwZDDy6FL//AnuJiaQNMF/sr4IiFMneyA5deVsaEA1K6O2/5zS1qWResIS3idGzJ8hJ+mOa4CNK0CcA==","shasum":"e160a339fac97a0b3df6f9b9d23e6b4404793103","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.0.2-next.2.tgz","fileCount":19,"unpackedSize":93493,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhulOWCRA9TVsSAnZWagAAlzkP/1q9twCDK4f0NKIivmTz\nX08eMkjvyFPWgEC/irkdKoTXfj7M7KHkQqzOBYQsHFC02OydLTRQJqusqNV0\nIN+rMq5PnFpgtCDIrAe/7uUFz+73mTuobIqXUI21OJmQb7KBmsMiMqThOsog\nW8Y7BE6D24J8NrV8B0+SsYcAp8bWF3lyz6dzpiCVR4316YbJZgHnDNsT2qTB\nfJ2KRtjwgIqYEaXIyrMkYe0fO75SNIdMzGKhFWTX6Y0LpwaYw4hh6PoKhURH\nXSRbLXer0+jVF0qNYvsbCyRIbWzm/T7CmTZNvt9l7C7v7org02/1VJBGd882\neHIcq4dw2ByX7cTGwd3dLlu4YopXPqfUeepMzsX+86GtgdEY6BTzK+JOgawa\nWDHPylJ3n3UVDo11+s2V3SkSki4WmqGf0DkUhXA7hFdnIzcYO2TgJOT0Wcsf\njyunegZEWtSOmErdZcP1uAb43OgvV4WgH/50dX03orsEryQqGEdXN/7v1ekQ\nAaAhf9RPl0i9XStoJpehnaVwRXaF9D7hjTIgskN7gb91ANk+5BnP7GSOoZs4\nNwwhO7JbjOyPiGsOgRTXG905T2W+lvuGaJ6tPDhi4q7huKqv0u1gWZUxtnin\nqwAJzyvhcPIuxGGVRkoFpLFdRy/tlY0mn8V5DBazwTSggWvK6aTj1K3Ik4DU\nh4Kk\r\n=VYu+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHHxfd1r2wK7WI9mFgQloNOhux6+/JaE7vMn0Y8kU98CAiEApqAMw/sXE4U1z2GoVqET1xjKkTk2/difIF83X+iUYx8="}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.0.2-next.2_1639601046702_0.4326288192787666"},"_hasShrinkwrap":false},"4.0.2-next.1.3":{"name":"studiokit-net-js","version":"4.0.2-next.1.3","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"3b5b463fa432ce6aca023d04267460aade7dbcb3","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.0.2-next.1.3","_nodeVersion":"14.18.2","_npmVersion":"6.14.15","dist":{"integrity":"sha512-7KvGbVSa+tmmCYv5eGEeGJLG7+jSyx768GKBT4spg+wT7MlnJrM2ekIEWtBfkV1fm9G9zbsApeAFwLLOwRE8nQ==","shasum":"64e7b51389a7167f0ecf9d734bf8d61944567ac9","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.0.2-next.1.3.tgz","fileCount":19,"unpackedSize":93534,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhummICRA9TVsSAnZWagAAAPQP/A1pjgDmmbWMhMdccPSI\n13k2gE2NCx7uplRXwAh2nsu1m+SKEDpy5n1nNGcJwt2Cj7oww0UI/4mi8ja+\nod+OWaUxxQlMt8FFwwwzi5iOPsLewGkm8kmMHwsucTljEb1PTCXEyI31LPwX\nZ0QOR/df1rNb977d1RtnaNpcqR4yH6F/Z56pUyEoTFmiTf1w7D7ZtpTropzh\nueFlA8EZ7SB7290+4bShkuhf4A/W9rWQMWEYqGJpTolu9He85UPDJlQrdkbK\nYmYlfzsgxucolOMfgzXjyjbkoozTTVBNbdjmy+QZU5zqL9INAymWtjZJDTfz\nbDqMqukkP+rxxf81dYffNT8anbCzZwOyYWbgbqIunAHo4KX6KXePQQYpooQA\n+GsHFdy8/Q0SUcZ4u5ueBwYo5PZifdlD6k9ldsLHyhgj+qAwbNFeXgaWGp4Y\nGnloIoiw02gIGw5jbkjOHOJCppRfgm8WeI5DSt46NSPOjdUUYybBCpO+JJFD\nbedcQ6OhBxHjBEDDGvsZkSJkdOTa0n44EIYO+dAQJ9P/HvGXYa8MNmVtBl/d\n0inypTxDab3ARTkYO8fAnzcjcXWdieI6hTbmT0J09qEr8coULmlJdKhwE/sV\nTcwxGOZN+AlEZhXtJD1/OKLAs90ONjqLk9rV35AVtdN2unHRqIPDUN07R3R9\nUJh2\r\n=jnUL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIH+ePXV3vhgkFHo0ehr5L03l0rHaCl1pcEapp3bvD1qqAiBwLJJQrwO1XR2JuTuT82D/aQjeggcvswX5vZmk5y6fTQ=="}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.0.2-next.1.3_1639606664472_0.4836929615392078"},"_hasShrinkwrap":false},"4.1.0":{"name":"studiokit-net-js","version":"4.1.0","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"gitHead":"9a355debf554309e5aff10acc127720ec3acbb26","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.1.0","_nodeVersion":"14.18.2","_npmVersion":"6.14.15","dist":{"integrity":"sha512-pisJwESKJLQMyR1Ebniz45v94x9VuEHsRJga1cc+QWWwhu9S6K/mZqa7TeLp3qigHli1BlaVYe8FAC+oFFUOBg==","shasum":"f8db4f293e5817b8164b7762472e24def87b3af4","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.1.0.tgz","fileCount":19,"unpackedSize":93540,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhu43BCRA9TVsSAnZWagAAdfMQAJ+mjkovxkVDphCnlGAW\nN5oOUUYu8qsXYY8qwEwskWqdoefdSozsAR/gOGkf0LMGaLvdWLZiFcnzeJvI\nEsiyj0fS5go4gcmGmU2v5fjDx4IIvEr14Tj41G0AhwwnHJpQ4gjYfKf8LzSc\njlnhk7Y2q3jNez2PrYuLU8THX9timItml/JyfW3Zal30Cb8YItcYgWvx31Qq\npYconYzncFj3EPDlxJiCgORmsVWoipTWBrgOojqmn7e2UzBHdDI21ETb2BFg\nQ4AaHWoBDFMn18LLT5Rob543iY7O2tiF4Vl+aYOX2zxCExgOQVyRd+5jqLz6\nXD6uVT40djKavdTxBpsT+YmqZQ1/vc5d3PVwgK1stek5ZQ8rW3Mu/EC9ZCtJ\ncfhIyxMYb7mQajT/9M4qOUSzoJY7l1Oyv+6P+VU1rUEJ0KOZA4nt/qxdAppw\ndFYVQ1XZKDaMm/T5+npluaE/T3MLlv11gLPUpC3yRTkiQDVt0WFcROa5412Y\n7ywigIzEx1whgwztD0BZSwUdlc6Awh37WNmTbrLc4nXskqkULO5FmHl7WgPh\nvcAHsQDJdIHo4D2F3csCwbYrCGYn+GuUHPNnen43YQQuj+JqS5uGjnkmuwfS\nH0435tp8I3xdKdnFcj67hU0MzypPfHOa6/Qy15vtTMSG7LtVitGXS3rbcp27\nLYv/\r\n=uhrF\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCT5NbezHX1h9g3y1niLcpE9JpGV/+H3U+TjqzAZo9B1AIhAJIFLYUpfOJHYjQA58rCwZsmL5bqsd7gJP9xeWdz/Irb"}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.1.0_1639681473826_0.2265397180688966"},"_hasShrinkwrap":false},"4.1.1":{"name":"studiokit-net-js","version":"4.1.1","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"gitHead":"1357eb0b9e4f9f6777470b48c934dcddfef76807","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.1.1","_nodeVersion":"14.18.2","_npmVersion":"6.14.15","dist":{"integrity":"sha512-LVomCXC+wr4lCMvut5F+XTWet0DqGAGNP7utkS+PnDZDutTXCx7nJ7735G3vBfhG2CLGS4FtZnYexM3xzERF2g==","shasum":"9ea7fb7907f7a0dd0d67926d5328705af0083a82","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.1.1.tgz","fileCount":19,"unpackedSize":93640,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhwN70CRA9TVsSAnZWagAAomIQAIBHwVRC4NJwsATzSnUV\nxtI6g4+Z54x9ts29y8Tlrp1FRVxeo2yv2YOiUw3BWjHxeS8fO8r4DgV1qjKU\nMrMxqbN23EAhLVZr6zbb7XvQQlRqwE30Lz/ZTCHKgjL55KX3QIUKYEcAQ9yp\na792uQh7Ebw0+IOLF1l5FKvxP8d7d3BG8XaknbwLe7ZedwaiBMdZ3oi0pFMg\nyWIlKb+gHZ8q1qW/sw4nGwKryoIFxrtY7lt+2qs5DPXFYPPigNs4lQ4rhODe\nCZgzP84372Yhwk3XwOBgJY2mjMLPJcK+ek+AIdRs6gI44GfxcoXN/6aW0rjc\nAfRcdl1zGNq5UHvcS1qyLsLO7wN9tuPw7mBdGMEmNrBySxaqMgMf5MQj5X0n\n3+qpJqfej3RKbtY2qo5ZyzVJFeYzSnt+jALAD6MDerEbU/dPGHLRiUgV9O5W\n1EMtQGdoOpX3q2QxZ2hEE8yGC/nKrsa59Vj85DVlSpNaqjgMGN9fsHC2iZGo\nb+XJVw9aL2OLSLxHGJ/buXlCefiYt4/mFRpZ9SQJhksH0dyUkaPD/5op4hfC\n7OG6VenomjF4SC/S0k8zb9xKEXZwzeYLcDe55EVmR7Gw9k0q16EJ5ckGL2wl\nvSE1uvxQzizOIhC+5tfmFjrZ5AUichkN3KlQmcEz7+M8+JjlSx/13ADaai/E\nPdkM\r\n=lZ/R\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGEwemxOvgqDofFBk2A8ZSqc0NPyzN46YSUW6kNwxoNLAiEA+bRnLhCMAQqpt4U5HuXcAbSV+d8756Q2eeEhcD9h/uk="}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.1.1_1640029940055_0.7963309086307029"},"_hasShrinkwrap":false},"4.1.1-next.1.1":{"name":"studiokit-net-js","version":"4.1.1-next.1.1","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"35f12d29f8afe98ca73ea19a52e126470edc50a9","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.1.1-next.1.1","_nodeVersion":"14.18.2","_npmVersion":"6.14.15","dist":{"integrity":"sha512-h43opBhar3EsIM1m04X6DFMHJTXMvqpMGfxOwM3r6iMAMS/DMqimaB/wFl+Ax2ittKiW3mg1kkel7Py/ZzCk4w==","shasum":"2828791add3543fd8bb4a73f07062184d9d16b1a","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.1.1-next.1.1.tgz","fileCount":19,"unpackedSize":93761,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh1vjpCRA9TVsSAnZWagAAhgYP/3MNSoP3oNEU9ipxcLsL\n88tAvtuDwvZL0XER1Dp/YuJ0tlmblIB6jQhfTwyBJfyG++U6HN/l80T+qmFv\nhrp6e+He4RZgj3JdDaGgftUegngTXGYLRZNtbhrgp6t0vHeRhldto8MD5B/G\nTjX6iPiOCHMKrCqlfHFAyRIvCJkayTdZ4p1I6WGgX0fWr+ONFtIoPqSkB8Cz\nfP40UvTXzHy4sXVToLlry3FqqYe4S5t4gNUlz/tiKkWt0yrLXGnEI054Mbnt\n3g3h95u3osu/JCq4MPjpqNBimkYa7z+Qt4ewvNV3MpnPAezDZkFXSwP3p4J/\nlzH/2r+/1me39COruFVoyQFW7tM/ADwTzz+cORayzQyBDEgOPYZ4DiUyS60d\nDcSGMw3WQdjEog99/gufgmWCgUSINHT7JbQpKc94VSi4CgxEINjFv4JrBELj\nzm5Wa6bMp8TcAAhmQEAIviTUtj29HngV9HF7HoJRNTHunhLCSuUGI0KrQ4Z5\nnf/o++61JKVIoFFsa24mvVHfzfVe0g3ChztRwtjsyJyGMoxA9pVik/oZUg85\ndlCKN+nPJ8cZaV9rvkyu6jrgVzdVLPWZSR16cSCaiK6GSCo9j0n+H1o7wvis\nkcDvvKOIypiH1yHo5LPrt3z/Xr2N4oFaG/BROZZdxJ8ylzrDzeTwiilzl7Cp\nWC4B\r\n=IOE+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH7l8yHggMZb60jGUSZFm9NNS0UUFMJBV/SDAsNgQjxiAiEA7rA4RkHNdI8zS6Uqln1TAdYM32jFj60Y8rSQSLfKhV4="}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.1.1-next.1.1_1641478377388_0.043034221236169845"},"_hasShrinkwrap":false},"4.1.1-next.1.2":{"name":"studiokit-net-js","version":"4.1.1-next.1.2","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"0bc37f5035d43bb3868a3820cf4c6a1ebf79469d","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.1.1-next.1.2","_nodeVersion":"14.18.2","_npmVersion":"6.14.15","dist":{"integrity":"sha512-sSKOTuRLvew9g/sZpEnQwNav1lZJL0+5IzhBOfedjeedGx+khzAOjHRvcNqYrNjnc5MRmD0IcIJaKRIxkz/HZQ==","shasum":"12ca1658f00fd549de0bdd8be2090838fdf09133","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.1.1-next.1.2.tgz","fileCount":19,"unpackedSize":94184,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh1v2gCRA9TVsSAnZWagAAiDAP/3xzWGfTRnWkGL0zqsr0\nzS0hQTpkStuMXYDURttgZGGivvhCT4ezese33LQvHsKBts9Vtu21om2RcXEx\nHNt+zYy1tEoldEIXHs9ksCxBQ7gFScBXv5mF+tdBEQTXztm09Ssz9hHfE/+5\nnT0t/KXmfoSSQNR+ypIWcGYDBCQo31ZIDLPTP9Q4eJ9CaZbTxUTvuVR4ah2n\nUV9N9IBiUA7gO5uX0PTwYEDJwNJ1izGVCoiFxtk4kleoY0GVTrjMWrdRjs2G\n7CSavQRuUpAX82hXuiqHOcYUgOcNVfX0euzNp/f/j6fjNakr2sCPY8bw2mv6\n/W/8LajE4oiIwanWpuUzREGQtHDLYDu1FiOxJXqlWojA0oEm5IdSC+9j6Qid\nW88O6p3lrmEg7C88oGRnllMEc/26OP7KHvofTqHvxklzkl3/yF1ydlKKAcAG\nGFGi4XkkXiZpw/tHGntHSNBpNBREGX0GNGVDVmzF1lqUqUL2BVfkhl38QBkc\nHDd9uuMVSwfBf7FCG/ZpXPetrr8YuRk5Q/9eHpCD65IJ/b9HEtVNmYaDem9k\noy0xnuaHzsIagp37taLU72AIB9fUt9vn816epuyMvC42FZrHCLCleejVkk0e\nJdj5JGaMy/yTNL7r3DjOebgaQy1plTitANKmd+/zyY9ARGk3+ebYMQ8UR9tl\nMSbT\r\n=e4bd\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFfrGPdo/S7SiYUgfxqhgQRHlYDK7IlHASRyrU1hQKncAiBHFxZQNmXmmVoQlkUNd42ik1PtOKqq5N02Ciz38p/0kg=="}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.1.1-next.1.2_1641479583930_0.49584773867657717"},"_hasShrinkwrap":false},"4.1.2":{"name":"studiokit-net-js","version":"4.1.2","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"gitHead":"de3c846f0b9e0a37b4c49c158890fab497870b83","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.1.2","_nodeVersion":"14.18.2","_npmVersion":"6.14.15","dist":{"integrity":"sha512-BAckRXx/tFou5rpzs+XbcCtddShmP2DRRoso4WjaqBRAQLXZIlpwu9ZXoPLnmTZWBF54FLrqu+bHHMbfpa32AQ==","shasum":"700d6f49f696aaae6ff53f0928df7e537c284bd0","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.1.2.tgz","fileCount":19,"unpackedSize":94175,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh3bs8CRA9TVsSAnZWagAAwMkP+gNjFc1HWXSgujWV3xqY\neB8WoQImSz39V61AwMyHv6lDsJ7KhmNoyOlQ15XfY0RJ8v0Xaa4XiHXPMH7z\ndxgPuZMhSeTRTziqbrzRS79PDsZYsxEOqqEc23Bli0FVK+5g05MI8LM2EtOP\nXWWSWAzFE6MfhYb7BAmDQR+5nSQ2uFRZBV63IHaXtCaut5RxT8yfy4SEwFKL\nGlDyFncJc+Gp7OWaGl9FiCEZHVMcxXRT15IvcNU0G3zBGIaVjeiGKumXL2Uc\nVAgWka3OXwH6hFoyh3gmuHgJuQg9pTBzE4A5aQ7zyDfif4EuqTmkAp9vuSyE\n/rEu2e6Pco4aVrPpxjnreHkWa7LKrtlv9CL+LCnpUAQtiCX1nTE6HQ6Hahys\nRwoXQgrsxkixTjasdqx6TVuY0DqG4SPjZpEP2KTvykYTZbb/MfIwaTrd/7hf\ng08CIswlEPiod12bIGGZ1Ze/1TDFj/QGl63LZD66qMbl3RegVoSUwpTlWSeO\nyOS9/M7rCz3upHKY1gmRez8omvuaLMNHttuLfMh+xP9TLo+uXm1Xx8f3JwxU\nuRql1GaZPWC693tWflFBrco8OZaYx+X6B9CLwg5iFEQJ2kbmrsOmVeeUYkiH\nks9tyBSbOVDhVbKzLdJQiENDhLXB6JroqgAGC9p5Uy5+K7YyeuGhQzRXaK6v\nuKcY\r\n=RzgY\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDFmPfQuKQyTiDtTpaswSO8RtAbi03UI4w/jE7YI3eG3QIgIGDSZV0vIkH5dR9ZeZqQ3aLdSZjEYJPrt/bzXK0sXvc="}]},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.1.2_1641921340647_0.007016466381546849"},"_hasShrinkwrap":false},"4.1.3":{"name":"studiokit-net-js","version":"4.1.3","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"gitHead":"b1bb05b90e371ef43f678488988f31951169a10c","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.1.3","_nodeVersion":"14.19.3","_npmVersion":"6.14.17","dist":{"integrity":"sha512-YDPMkS2T9Id7e6Pb+78Mnb5ouVgARDlrztzRVwRggyubDR8/u7n7PG7H6JJq3I2DFE7Y3jiAnEojgnA8O3FWNg==","shasum":"16c837c5032d9fbb976f19012c3793c2925c0633","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.1.3.tgz","fileCount":19,"unpackedSize":94051,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBFiKIwWTsFCRWN0f5FG0O6x3Ab6l8o11NA+3f3TOszRAiEA8cdOCdKlCuI6fdTqtJ+gTaApE9cOabK43orZ4/VnS/0="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJirOogACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqqUxAAj1VscaGaE5pNaDAq2YYxofHBSwVaXyhhBPcmjZs0SXnfvDpA\r\nK29q48rhWVZgXbyOHf9iCmLy7CR0ZtY7dC7NNS9amnZcJRiAjPsI5YD5ZClm\r\n/E8j3wfMd8HvmQR8cVIyEx0DtJN+NbrM2Qh3WnIapXCqakJpa1llLmRFZ8BI\r\ncDZuh8OOqF5qKEVmormFOAt4LTlZB/3bG9OrSc6THz3qzEhkytD7t9aOohHi\r\nZtruk+AZNxZAWuiEZNwR3X94WNbnz8/R3wx0dLVAEj2kx1LhvniwuRhnaBVM\r\nZokpePzm9FgqUJe2Bw4JCaBDZ3VPAxwei7IsOD+2Vd/6ae+fxjTIWks6Zp8w\r\nOCtT8a9XfZuCyTnvWOagaHrL2hbYjQMxYfCY9U0LotE8mkG4Z2EdKKoHNN3M\r\no2jQZMzAlhpC6jzYYYLkExrmACySEr8Z+0PubkHChxn2zWipowo/Vx2iYBY6\r\nh2iD+yKRdZjHL3DxhomalV4ZnG2xbdRil10t4Z5LGohRIIG3aMbFbcUfvNwQ\r\nKjoeLJpm8ymWSnf4qcwQSTWkoPz0DpFF8v0fgmcsVSYWUBXQuAjedeF4knb4\r\n32TfcWsDW39g4fHyYeY5GQ+rnz9guwdBB76PMFRAS/rRb9eCQQMpyfAg6Sdx\r\nSIJnNNEGbDdLdnPHJtW7uf+PRpsA85MscBY=\r\n=e36x\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"builtbywill","email":"builtbywill@gmail.com"},"directories":{},"maintainers":[{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"builtbywill","email":"builtbywill@gmail.com"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.1.3_1655499296393_0.6531010188141124"},"_hasShrinkwrap":false},"4.1.4-alpha.1":{"name":"studiokit-net-js","version":"4.1.4-alpha.1","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"e9d155febd3f08c26abf26df29b0011f1025a9b6","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.1.4-alpha.1","_nodeVersion":"14.21.2","_npmVersion":"6.14.17","dist":{"integrity":"sha512-6FjY4vmU2q4GdWOLo27/vcWe3gWZASYmH879X0XsDpUGVRKlkPGVBommJzaxzrhEyhBA9gIUhxtMw93kL0LJzg==","shasum":"03d7892b4ed3f9788c66cea4e77ea3764767ca62","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.1.4-alpha.1.tgz","fileCount":19,"unpackedSize":94064,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGzlpTmuaUAVgtTIGmvm/5HUjGuqzcI5XIa0Y1qiUrDRAiEA4vOQ2b415jF9kF4wOqwdCkx/uOggwII1Q5iLTD+WJMM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj7kl6ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmpXzhAAlF5Svu6rpc2ULBT/X5glF5mQRilcZYdj3st++WqKHaGOduua\r\nRaw46IODcxDtZ+Ht2iusCYCQUC/vE8uaQuD/6+bpBdeFYVUXdbMgA/tV/h4b\r\n/HGOZtBPlybzkeHxUBQmfXiEprjfOn+GiEx4bheaXAIUWGFgq8lsVDneJ7Pm\r\nqU5aRNT8AwenMuKRIDJwIfkMLR5AIt3SAWZ79FQpgAp2S73uVInvbDi08z/L\r\nFVfXveF4vU+0Vv1W2bPxD4h/7p7WqBOxQuUtKwhg03TGTie4u2GfzuO9tHDN\r\nYfc0qdGjrzNRk9mmbw4oFu5y4IweMElOySbZwG161/RTHWaCj50055Fvx22j\r\nGgc0efon9xokM3ZSXjXhM4Qy9QFZrOhRWzJQfpuxduMadZBOLZM0mRedGcEB\r\n2pJrXJ2wi7qtWN4fpd1Lx234v1eFnJF3StKwcfS/06K2Pc8apgkpJMlPXRxo\r\nY3MP3V7LQ47oliCyDh29nndOu2Tl08BILdDkEHS54Wx3mtTAomySMKnkWtkK\r\nz78cnzH5Yh+bWL7NIzpY/a8r0bUfJgxcs5HnOUA5mSf+BbiWqH4OYZsSd0X+\r\nlnFQj403KNqtmnsPO2V64y3jtiyD2daXIa085DcZJv1/rAi9Xz+NSk59JVEF\r\nLXZb0SNYv7UNX2cZWHPKEoFyGOHRndnHj1k=\r\n=8KUD\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"wgrauvog","email":"wgrauvog@purdue.edu"},"directories":{},"maintainers":[{"name":"lane174","email":"lane174@purdue.edu"},{"name":"wgrauvog","email":"wgrauvog@purdue.edu"},{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.1.4-alpha.1_1676560762208_0.8619414535378016"},"_hasShrinkwrap":false},"4.1.4-alpha.2":{"name":"studiokit-net-js","version":"4.1.4-alpha.2","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"36e0a753366eb2bb85e4001408f83c24d807bb52","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.1.4-alpha.2","_nodeVersion":"14.21.2","_npmVersion":"6.14.17","dist":{"integrity":"sha512-dzFngvO8gR2BbQLz2mxj7yYkXVSCOo7/4qDrW2BzXriTdeeYuk3GrbP0eDuXg/mM33/64jbvM10dzoQyOmf9Vg==","shasum":"2820a10142099283c0216b9a7938f28d9c7ab64f","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.1.4-alpha.2.tgz","fileCount":19,"unpackedSize":94086,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBy75JvXcIKzoxC20oeQTl2F7XjCZqK4g69ojjMl3rTqAiA2KBgDP3SL5K73VEEbcGgTHo4BwCt8LD7YCIdgR9tQ8A=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj7m5gACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmohYw/+MsEem7Bkbh5hmewmlBdmIbrW2hTPtOeJc+YN3GowcZLY4haW\r\nBXzeVDFuT5n3T8lCEUy9irv3WIWdLNK/SJZPAqtU9Jw9kFs3MtdvhAf5Fsm7\r\ny+ahmG4xY+P8ipWE0zQjX3YxEGwWUexJ2UJwLXSI66qEvkjZF9pZF7xFTXF+\r\nKmhhT5dUiu5ufi3hqa1Pz/WuJw4ZXjU7/LCfJAjdZIdd9eT7F5jzlKm5jpPY\r\nm75H3ulitEGbvnlYFSRTsWElkgLHVwLGsq+LehDeX0hCJXGzzxHLoSaWwTOA\r\nQ5RD69riM3FH8qiuTpQcUR9d8WHCrsAfLBolOVjcldOxvfWi98cWX5a48P7c\r\nnQFhotbowlM8D62+nWPG9mjntYOEErSuO7QtxlSrp5bvekVd1MntrWWaT1ZN\r\nO5yLOZ6xTIkuDzyf6RkIcY8rRvdWlIPYd/Imy4LTG+Au6QrOX4HXlHspJFum\r\nP+VGpH61VbXpi/nEQmBDNnbX/pF5rKV7f8kTwAKfG1K3/wDfqxpZJHX+OKZb\r\niMUJTmHfIzIhoAqICrk4Vg6TdE3k+2i/0UoMHcDzJ4dXe6dQp69DkzI8iCT4\r\nILKnfZxdmqrB0r3fn7xGF3/8meHar4kXmWOd3e+VJaYWedSYo7bnKMZpM3M1\r\nEKTVtKDux0iSuDTdOkI1c/IyfXQiJj87DuE=\r\n=vvxc\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"wgrauvog","email":"wgrauvog@purdue.edu"},"directories":{},"maintainers":[{"name":"lane174","email":"lane174@purdue.edu"},{"name":"wgrauvog","email":"wgrauvog@purdue.edu"},{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.1.4-alpha.2_1676570207853_0.19849266826268486"},"_hasShrinkwrap":false},"4.1.4-alpha.3":{"name":"studiokit-net-js","version":"4.1.4-alpha.3","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"readme":"[![Coverage Status](https://coveralls.io/repos/github/purdue-tlt/studiokit-net-js/badge.svg?branch=master)](https://coveralls.io/github/purdue-tlt/studiokit-net-js?branch=master)\n\n# StudioKit Net Library\n\nA library for declarative, configurable data (API) access with built-in retry, periodic refresh, and concurrency handling.\n\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [API](#api)\n1. [Development](#development)\n\nFor *in-vivo* examples of how to use this library, see the [example react app](https://github.com/purdue-tlt/example-react-app-js) and the [example react native app](https://github.com/purdue-tlt/example-react-native-app)\n\n# Installation\n\n## Install this library and redux-saga as a dependency\n1. `yarn add studiokit-net-js`\n1. `yarn add redux-saga` (which depends on `redux` itself)\n1. Create a `reducers.js` module that includes the reducer from this library, i.e.\n\t```js\n\timport { combineReducers } from 'redux'\n\timport { reducers as netReducers } from 'studiokit-net-js'\n\n\texport default combineReducers({\n\t\tmodels: netReducers.fetchReducer\n\t})\n\t```\n1. Create an `endpointMappings.js` module specifying a mapping of any APIs you will call in your application. All configuration properties are set under `_config`. Fetch request specific default properties are set on `_config.fetch`, i.e.\n\t```js\n\tconst endpointMappings = {\n\t\tpublicData: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: 'https://httpbin.org/get',\n\t\t\t\t\tqueryParams: {\n\t\t\t\t\t\tfoo: 'bar'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\texport default endpointMappings\n\t```\n1. Create a `rootSaga.js` module that includes the fetchSaga from this library, i.e.\n\t```js\n\timport { all } from 'redux-saga/effects'\n\timport { sagas as netSagas } from 'studiokit-net-js'\n\timport endpointMappings from '../../endpointMappings'\n\n\texport default function* rootSaga() {\n\t\tyield all({\n\t\t\tfetchSaga: netSagas.fetchSaga(\n\t\t\t\tendpointMappings,\n\t\t\t\t'https://yourapp.com'\n\t\t\t)\n\t\t})\n\t}\n\t```\n1. Wire up your store in your app (perhaps in `index.js`) with the above, i.e.\n\t```js\n\timport createSagaMiddleware from 'redux-saga'\n\timport { createStore, applyMiddleware } from 'redux'\n\timport reducer from './redux/reducers'\n\timport rootSaga from './redux/sagas/rootSaga'\n\n\tconst sagaMiddleware = createSagaMiddleware()\n\tconst store = createStore(\n\t\treducer,\n\t\tapplyMiddleware(sagaMiddleware)\n\t)\n\tsagaMiddleware.run(rootSaga)\n\n\t```\n\n# Usage\nOnce you have the above steps completed, you can dispatch actions to the store and the data will be fetched and populated in the redux store, i.e.\n\n```js\nimport { dispatchAction } from '../services/actionService'\nimport { actions as netActions } from 'studiokit-net-js'\n.\n.\n.\nstore.dispatch({ type: netActions.DATA_REQUESTED, modelName: 'publicData' })\n```\nOnce the data is fetched, it will live in the redux store at the models.publicData key, i.e.\n```js\nmodels: {\n\tpublicData: {\n\t\tdata: { foo: 'bar', baz: ['quux', 'fluux']},\n\t\tisFetching: false,\n\t\thasError: false,\n\t\tfetchedAt: \"2017-05-23T20:38:11.103Z\"\n\t}\n}\n```\n\n# API\nActions are dispatched using the following keys in the action object for configuring the request\n```ts\ntype FetchAction = {\n\tmodelName: string,\n\tguid?: string\n\tmethod?: string,\n\theaders?: Object,\n\tqueryParams?: Object,\n\tpathParams?: Object,\n\tnoStore?: boolean,\n\tperiod?: number,\n\ttaskId?: string,\n\tnoRetry?: boolean\n\tcontentType?: string\n}\n```\n\n- `modelName` refers to the path to the fetch configuration key found in `endpointMappings.js`\n- `guid` is an optional pre-generated (by your application) GUID that will be attached to a fetch result's data, to be stored in redux and used to match request results in components\n- `method` is an optional string used as the HTTP Method for the fetch. Otherwise will use the method set in `endpointMappings.js`, or `'GET'`\n- `headers` is an optional object used as key/value pairs to populate the request headers\n- `queryParams` is an optional object used as key/value pairs to populate the query parameters\n- `pathParams` is an optional array of values to be replaced in the fetch path using pattern matching, in order, e.g. `[1, 2]` and `/collection/{:id}/subcollection/{:id}` => `/collection/1/subcollection/2`\n- `noStore` is an optional boolean that, if true, indicates the request should be made without storing the response in the redux store\n- `period` is an optional number of milliseconds after which a request should repeat when dispatching a recurring fetch\n- `taskId` is a string that must be passed to a recurring fetch for future cancellation\n- `noRetry` will prevent the use of the default logarithmic backoff retry strategy\n\nThe following actions can be dispatched\n- `DATA_REQUESTED`: This will fetch the data specified at the `modelName` key of the action\n- `PERIODIC_DATA_REQUESTED`: This will fetch the data specified at the `modelName` key at an interval specified by the `period` key in the action. This also requires you to generate and pass a `taskId` key for subsequent cancellation\n- `PERIODIC_TERMINATION_REQUESTED`: This will cause the periodic fetch identified by `taskId` to be cancelled\n- `DATA_REQUESTED_USE_LATEST`: This will fetch data specified at the `modelName` key, using only the latest result in time if multiple requests are dispatched at the same time (i.e. others are started with the same `modelName` before some are completed)\n\n## Examples\n\nGiven the following `endpointMappings.js`\n```js\n{\n\tbasicData: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://httpbin.org/get'\n\t\t\t}\n\t\t}\n\t},\n\tfuturama: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://www.planetexpress.com/api/goodNewsEveryone',\n\t\t\t\tqueryParams: {\n\t\t\t\t\tdoctor: 'zoidberg'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttheWalkers: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://thewalkingdead/api/walker/{:walkerId}',\n\t\t\t\tpathParams: {\n\t\t\t\t\twalkerId: 1\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}.\n\ttheOffice: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: 'https://dundermifflin.com/api/paper'\n\t\t\t\theaders: {\n\t\t\t\t\t'Content-Type': 'x-beet-farmer'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\taGrouping: {\n\t\tapiOne: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/one'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tapiTwo: {\n\t\t\t_config: {\n\t\t\t\tfetch: {\n\t\t\t\t\tpath: '/api/two/{{models.futurama.zoidberg}}'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tbasicPost: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeThing'\n\t\t\t\tmethod: 'POST'\n\t\t\t}\n\t\t}\n\t},\n\tbasicPostTwo: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/createSomeKnownThing'\n\t\t\t\tmethod: 'POST',\n\t\t\t\tbody: { person: 'Fry' }\n\t\t\t}\n\t\t}\n\t},\n\tentities: {\n\t\t_config: {\n\t\t\tfetch: {\n\t\t\t\tpath: '/api/entities'\n\t\t\t},\n\t\t\tisCollection: true\n\t\t}\n\t},\n\ttopLevelEntities: {\n\t\t_config: {\n\t\t\tisCollection: true\n\t\t},\n\t\tsecondLevelEntities: {\n\t\t\t_config: {\n\t\t\t\tisCollection: true\n\t\t\t}\n\t\t}\n\t}\n}\n```\nYou can make the following types of requests:  \n[Basic Fetch](#basic-fetch)  \n[Nested Model](#nested-model)  \n[Add Headers](#add-headers)  \n[Add Query Params](#add-query-params)  \n[Periodic Fetch](#periodic-fetch)  \n[Cancel Periodic Fetch](#cancel-periodic-fetch)  \n[No Store](#no-store)  \n[Post](#post)  \n[Collections](#collections)  \n[Nested Collections](#nested-collections)  \n\n#\n\n### Basic fetch:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData'\n})\n```\n*request generated* \n```http\nGET https://httpbin.org/get\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tbasicData: {\n\t\t\tfoo: 'bar',\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Nested model:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'aGrouping.apiOne'\n})\n```\n*request generated* \n```http\nGET https://myapp.com/api/one\n``` \n*resulting redux*\n```js\n{\n\tmodels: {\n\t\taGrouping: {\n\t\t\tapiOne: {\n\t\t\t\tfoo: 'bar',\n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#\n\n### Add headers:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\theaders: {'Accept-Charset': 'utf-8'}\n})\n```\n*request generated*\n```http\nAccept-Charset: utf-8\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to additional header\n\n**Note**: Headers specified in the action will be merged with headers specified in `endpointMappings.js` with the headers in the action taking precedence\n\n#\n\n### Add query params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tqueryParams: {robot: 'bender'}\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get?robot=bender\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new query params\n\n**Note**: Query parameters specified in the action will be merged with query parameters specified in `endpointMappings.js` with the query params in the action taking precedence\n\n#\n\n### Add route params:\n\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'theWalkers',\n\tqueryParams: {walkerId: 1}\n})\n```\n*request generated*\n```http\nGET https://thewalkingdead/api/walker/1\n```\n*resulting redux*\n\nSame as basic fetch above, with possibly different data, depending on response relative to new route params\n\n**Note**: Route parameters specified in the action will be merged with route parameters specified in `endpointMappings.js` with the route params in the action taking precedence\n\n#\n\n### Periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tperiod: 1000,\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nSame as basic fetch above, but refreshing every 1000ms, replacing the `data` key in redux with new data and updating the `fetchedAt` key\n\n#\n\n### Cancel periodic fetch:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.PERIODIC_TERMINATION_REQUESTED,\n\tmodelName: 'basicData',\n\ttaskId: 'something-random'\n})\n```\n*request generated*\n\nNone\n\n*resulting redux*\n\nSame as basic fetch above with `data` and `fetchedAt` reflecting the most recent fetch before the cancellation request\n\n#\n\n### No store:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicData',\n\tnoStore: true\n})\n```\n*request generated*\n```http\nGET https://httpbin.org/get\n```\n*resulting redux*\n\nNo change to the redux store. Your application can create its own sagas and use `take` and friends in `redux-saga`, however, to watch for responses and cause side-effects\n\n#\n\n### Post:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: {\n\t\truleOne: \"Don't talk about Fight Club\",\n\t\truleTwo: \"Don't talk about Fight Club\"\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/createSomeThing\n{\"ruleOne\": \"Don't talk about Fight Club\",\"ruleTwo\": \"Don't talk about Fight Club\"}\n```\n*resulting redux*\n\nSame as basic fetch above, with the `data` key containing the response data from the `POST` request\n\n### Post with form data:\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'basicPost',\n\tbody: new FormData(),\n\tcontentType: 'multipart/form-data'\n})\n```\n*request generated*\n```http\nContent-Type: multipart/form-data; XXX boundary--------\nPOST https://myapp.com/api/createSomeThing\n(formData values)\n```\n*resulting redux*\n\nSame as basic fetch above, but with Content-Type equals to multipart/form-data\n\n#\n\n### Collections\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities'\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\tentities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\t...,\n\t\t\t\t_metadata: {\n\t\t\t\t\tisFetching: false,\n\t\t\t\t\thasError: false,\n\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t}\n\t\t\t},\n\t\t\t...,\n\t\t\t_metadata: {\n\t\t\t\tisFetching: false,\n\t\t\t\thasError: false,\n\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t}\n\t\t}\n\t}\n}\n```\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/entities/1\n```\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/entities/1\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `entities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `entities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'PATCH'\n\tpathParams: [1],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/entities/1\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `entities.1`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'entities',\n\tmethod: 'DELETE'\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/entities/1\n```\n*resulting redux*  \nRemoves item in store at `entities.1`\n\n#\n\n### Nested Collections\n\nNested collections behave the same as normal collections, but require a `pathParams` to have at least one value per nested level.\n\n#### GET all\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n```\n*resulting redux*\n```js\n{\n\tmodels: {\n\t\ttopLevelEntities: {\n\t\t\t1: {\n\t\t\t\tid: 1, \n\t\t\t\tsecondLevelEntities: {\n\t\t\t\t\t999: {\n\t\t\t\t\t\tid: 999,\n\t\t\t\t\t\t...,\n\t\t\t\t\t\t_metadata: {\n\t\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t...,\n\t\t\t\t\t_metadata: {\n\t\t\t\t\t\tisFetching: false,\n\t\t\t\t\t\thasError: false,\n\t\t\t\t\t\tfetchedAt: '2017-05-23T20:38:11.103Z'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nStores item in object as key/value pairs in store at `topLevelEntities.1.secondLevelEntities`\n\n\n#### GET item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nGET https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n\n#### POST item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tpathParams: [1],\n\tmethod: 'POST',\n\tbody: {\n\t\tname: 'entity name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPOST https://myapp.com/api/topLevelEntities/1/secondLevelEntities\n{\"name\": \"entity name\"}\n```\n*resulting redux*  \nAdds item in store at `topLevelEntities.1.secondLevelEntities` under the return object's `id`\n\n*Note*  \nDuring the request, status is stored in `topLevelEntities.1.secondLevelEntities` under a `guid` key, which can be provided in the action for tracking\n\n#### PATCH item\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'PATCH'\n\tpathParams: [1, 999],\n\tbody: {\n\t\top: 'replace',\n\t\tpath: 'Name',\n\t\tvalue: 'updated group name'\n\t}\n})\n```\n*request generated*\n```http\nContent-Type: application/json\nPATCH https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n{\"op\": \"replace\", \"path\": \"Name\", \"value\": \"updated group name\"}\n```\n\n*resulting redux*  \nUpdates item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n*Note*  \nSee http://jsonpatch.com/\n\n#### DELETE Entity\n*dispatch*\n```js\nstore.dispatch({\n\ttype: netActions.DATA_REQUESTED,\n\tmodelName: 'topLevelEntities.secondLevelEntities',\n\tmethod: 'DELETE'\n\tpathParams: [1, 999]\n})\n```\n*request generated*\n```http\nDELETE https://myapp.com/api/topLevelEntities/1/secondLevelEntities/999\n```\n*resulting redux*  \nRemoves item in store at `topLevelEntities.1.secondLevelEntities.999`\n\n#\n\n## Development\n\nDuring development of this library, you can clone this project and use\n\n`yarn link`\n\nto make the module available to another project's `node_modules` on the same computer without having to publish to a repo and pull to the other project. In the other folder, you can use\n\n`yarn link studiokit-net-js`\n\nto add `studiokit-foo-js` to the consuming project's `node_modules`\n\n### Build\n\nBecause this is a module, the source has to be transpiled to ES5 since the consuming project won't transpile anything in `node_modules`\n\n`yarn build`\n\nwill transpile everything in `/src` to `/lib`. `/lib/index.js` is the entry point indicated in `package.json`\n\nDuring development, you can run\n\n`yarn build:watch`\n\nand babel will rebuild the `/lib` folder when any file in `/src` changes.\n\nWhen you commit, a commit hook will automatically regenerate `/lib`\n\n### Deploy\n\nThis packaged is deployed via the npm repository. Until we add commit hooks for deployment, it must be published via `yarn publish`\n","readmeFilename":"README.md","gitHead":"00eb60779c7eb36b540abb1b6c28f1ab32f0335d","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.1.4-alpha.3","_nodeVersion":"14.21.2","_npmVersion":"6.14.17","dist":{"integrity":"sha512-BXxpypNcilLvyGQztc9z13EPXpu5HkwVNm2NGSGaCbnZXF5XpcoHqoA5g88hcc14j8vOfAcHGVyANWigYccS0Q==","shasum":"42659951309c3b97f569c1aa96798805d63740d1","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.1.4-alpha.3.tgz","fileCount":19,"unpackedSize":94180,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEPxixFmmBK9kyH9OlthINqlo0Gs6/2s5XOaPUG7EMnrAiEA4kwvKWVnuOsHe+xbxxZA6lUODEdII/KUzouM4VdlwfM="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj7nUAACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmokuw/9H7xsIhDVlxII7N3koN5GWAZ9boU501xxASoXKjKxvPcXPHZD\r\nrerov5By4DFpjAzQ0VMzkoYTbyQKgmHIWYCliGme4E1VARnHYeH72hTDJcN7\r\nTm4dBHV9Gfmi7fAW47bsg+EO/HzXpjP05ITbubU5WgENttgKY1veskkU35sq\r\nusXzPK6UveluiVgu8ysFesbgxmlIlM2O6g6NONmxZKfPad4stoDFA12HE4tI\r\nmjxkFEjviYp1IFHTw/LsFmTlXFSesaToGEQScbG57LklnP4nUm8zm9fwWlZx\r\nYJO8fMUJJZhJzXC5PYIgMMNqAl0cgp9d8428uSMcdguziRpUuwOMOcMyrLGw\r\n0frKJcm8myTN0WGmBX749mUyeVRnYKmOay8OHD+o2LaMa78e0z/RyB+lJPCe\r\niLR4LW2io9nDaKq/qB0uaFbTgMpuLJkijdpu8x3Wa/buIiGPrXV/QbCUrgCM\r\nA5dmkjnkx9jz5oUJE0tToBxqv3IJN52h5n0ZOJPy+gVlQVek63sUYq+ImHzQ\r\nTfQ5MU/0votg4aKCG74oKoEwifJVRqxIpOsC7a1srgCELnsDYihDwRHvl5X1\r\nC+S5Lo0YGzRkTfgbNGAF0ja3q4cz/csB70TKPiG3tmMobEmhQ8yDRYwiKhYV\r\ncjMFC9WtrgG19XwcffYfFIM2xxKtyqnKQF4=\r\n=VMqg\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"wgrauvog","email":"wgrauvog@purdue.edu"},"directories":{},"maintainers":[{"name":"lane174","email":"lane174@purdue.edu"},{"name":"wgrauvog","email":"wgrauvog@purdue.edu"},{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.1.4-alpha.3_1676571904198_0.5986381520729298"},"_hasShrinkwrap":false},"4.1.4":{"name":"studiokit-net-js","version":"4.1.4","description":"Network/API functions for Studio apps at Purdue","repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","main":"lib/index.js","types":"lib/index.d.ts","scripts":{"build":"yarn clean && tsc -p tsconfig.build.json","build:watch":"tsc -p tsconfig.build.json -w","clean":"rimraf ./lib","coverage":"jest --coverage","coveralls":"npm run coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage","eslint-check":"eslint --print-config src/index.ts | eslint-config-prettier-check","fix":"yarn lint --fix","lint":"yarn lint-code-core .","lint-code-core":"eslint --ext .js,.ts","prepublishOnly":"yarn build","test":"jest"},"husky":{"hooks":{"pre-commit":"lint-staged","pre-push":"npm run test"}},"lint-staged":{"*.(j|t)s":["yarn lint-code-core --fix"],"package.json":["sort-package-json"]},"eslintConfig":{"extends":["studiokit"],"overrides":[{"files":["**/*.ts?(x)"],"parser":"@typescript-eslint/parser","parserOptions":{"project":"tsconfig.json"}}],"ignorePatterns":["coverage/","lib/"]},"jest":{"automock":false,"preset":"ts-jest","setupFiles":["./setupJest.ts"]},"resolutions":{"kind-of":"^6.0.3","lodash":"^4.17.20","mixin-deep":"^1.3.2","node-fetch":"^2.6.1","set-value":"^2.0.1","sshpk":"^1.13.2"},"dependencies":{"@redux-saga/types":"^1.1.0","@types/lodash":"^4.14.168","@types/node":"^14.14.22","@types/uuid":"^8.3.0","local-storage-fallback":"^4.1.1","lodash":"^4.17.20","moment-timezone":"^0.5.32","redux":"^4.0.5","redux-saga":"^1.1.3","uuid":"^8.3.2"},"devDependencies":{"@redux-saga/testing-utils":"^1.1.3","@types/jest":"^26.0.20","@types/mockdate":"^2.0.0","@typescript-eslint/eslint-plugin":"^4.14.1","@typescript-eslint/parser":"^4.14.1","babel-eslint":"^10.1.0","coveralls":"^3.1.0","cross-env":"^7.0.3","eslint":"^7.11.0","eslint-config-prettier":"^7.2.0","eslint-config-studiokit":"^3.0.1","eslint-plugin-import":"^2.22.1","eslint-plugin-prettier":"^3.3.1","husky":"^4.3.8","jest":"^26.6.0","jest-fetch-mock":"^3.0.3","lint-staged":"^10.5.3","mockdate":"^3.0.2","prettier":"^2.2.1","rimraf":"^3.0.2","sort-package-json":"^1.48.1","ts-jest":"^26.4.4","typescript":"^4.1.3"},"gitHead":"04db9170ba6fcd26ddbfb2a7340e68d0325c23e3","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"},"homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","_id":"studiokit-net-js@4.1.4","_nodeVersion":"14.21.2","_npmVersion":"6.14.17","dist":{"integrity":"sha512-KaRAu2MHHjzoFRI8fZyzZkjbNvSUJWvSCFY/X+L8Jdp4V7gdlPJ6kUI04bLCb9grwjq0whi7MlyEFDz/h9xSHA==","shasum":"0d88d9bf9461ebdb7101ee46022356b8bd75b06b","tarball":"https://registry.npmjs.org/studiokit-net-js/-/studiokit-net-js-4.1.4.tgz","fileCount":19,"unpackedSize":94429,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICSpmOP/0CqPyLNIvjIVz9rhZDmTCf5zgH2E1J9nhnLuAiEAkQthU2Sf5uIXrcMimkwk4bqyBvvUa0Bop0OB1zGtWHA="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj7oB0ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmo6qxAAg+CWJTReg2WIuTS8lEX5RcMdc+9j9tgYr/bCsa3o5gB5trpn\r\nNqq/916IJJ3wCyxSS6UVrsvd5g9aZ8mTMnl1LnhuipIhINm3OMxa+GJ5YMhd\r\n0hjUbXkgpL5Z9ra8tdrWLJ6yol7Z5/VihqGFa/t+gT9zJs1WmGJdkt0j4C+E\r\nzWSB0FGjKKHt/II8T2uw+5ocQdCr83wrqHJluL1pP8cQLXzHqbjBNYMmkK2v\r\niWprCf5TrUqRkUUklDBg5b2pjRB9SfV2Ml8kuY+6V0itW78j6jTU/X3GTbIh\r\n3h9WgKex17Szmq/MBqGno4uPKMvj/vA4YeXB550M6q8gHmALhUYSQmd1eRX5\r\nUWpkzJ9l72uoDKoGfFV+q6hD/a+wq50KJ/ghsxfuhv4GAWceztsGZowYNggM\r\nt7nUrbEkGY3rbLTphPM/5sRhzm2fQbIs1JEJOZzrq6FZXiV6jzhtszdSEX1P\r\nD5wvfBWSC0hm/GJ4cd2db53yhggeFMhNCvGk7zHQpEO/9MUB9gQ2JM9vOJUi\r\nQeqxCie5QBhQHD3C3UCxDt7XsZX1yOrLQJYlUjim/63dQHlpUofuZaZIjloY\r\ngGNEfJFgQPE8z3URht3fi/PT7Av8fE1fKpTAITrbh9uQaR0UjaexKWtKfQmi\r\nQ1gHwqC851+N0ywzPTbyHW2dzh/S1R6Ds8g=\r\n=K+FV\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"wgrauvog","email":"wgrauvog@purdue.edu"},"directories":{},"maintainers":[{"name":"lane174","email":"lane174@purdue.edu"},{"name":"wgrauvog","email":"wgrauvog@purdue.edu"},{"name":"itap-informatics","email":"itap-informatics@lists.purdue.edu"},{"name":"jkdufair","email":"jase@dufair.org"},{"name":"tragessere","email":"tragessere@gmail.com"},{"name":"lilycarlson","email":"carls118@purdue.edu"},{"name":"caseywpurdue","email":"caseyw@purdue.edu"},{"name":"gregstrasters","email":"gregstrasters@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/studiokit-net-js_4.1.4_1676574836608_0.6688987816657981"},"_hasShrinkwrap":false}},"repository":{"type":"git","url":"git+https://github.com/purdue-tlt/studiokit-net-js.git"},"license":"MIT","readmeFilename":"README.md","homepage":"https://github.com/purdue-tlt/studiokit-net-js#readme","bugs":{"url":"https://github.com/purdue-tlt/studiokit-net-js/issues"}}