{"_id":"@atistler/apisauce","_rev":"1-eb2abd48a136939a9923de10986536b6","name":"@atistler/apisauce","dist-tags":{"latest":"1.1.2"},"versions":{"1.1.2":{"version":"1.1.2","author":{"name":"Steve Kellock","email":"steve@kellock.ca"},"ava":{"require":["babel-core/register"]},"dependencies":{"axios":"^0.19.0","ramda":"^0.25.0"},"description":"Axios + standardized errors + request/response transforms.","devDependencies":{"@semantic-release/git":"^7.0.5","@types/ramda":"^0.25.28","ava":"^0.25.0","babel-cli":"^6.26.0","babel-core":"^6.26.3","babel-eslint":"^8.2.3","babel-plugin-ramda":"^1.6.1","babel-preset-es2015":"^6.24.1","husky":"^1.3.1","lint-staged":"^8.1.0","np":"3.0.4","npm-run-all":"^4.1.5","nyc":"^11.8.0","prettier":"^1.15.3","ramdasauce":"^2.1.0","rollup":"^0.59.1","rollup-plugin-babel":"^3.0.4","rollup-plugin-filesize":"^1.5.0","rollup-plugin-uglify":"^3.0.0","semantic-release":"^15.12.4","tslint":"^5.12.0","tslint-config-prettier":"^1.17.0","tslint-config-standard":"^8.0.1","typescript":"3.2.1"},"keywords":["axios","api","network","http"],"license":"MIT","main":"./dist/apisauce.js","name":"@atistler/apisauce","repository":{"type":"git","url":"git+https://github.com/atistler/apisauce.git"},"scripts":{"build":"BABEL_ENV=production rollup -c","clean":"rm -rf dist","compile":"tsc -p tsconfig.json","coverage":"nyc ava","prepare":"npm-run-all compile build","dist":"npm-run-all clean compile build test","lint":"tslint -p .","test":"npm-run-all compile test:unit","test:unit":"ava -s","ci:publish":"yarn semantic-release","semantic-release":"semantic-release","format":"prettier --write \"{**/*.ts,.circleci/**/*.js}\" --loglevel error && tslint -p . --fix"},"prettier":{"semi":false,"singleQuote":true,"trailingComma":"all","printWidth":120},"lint-staged":{"*.ts":["prettier --write","tslint --fix","git add"],"*.md":["prettier --write","git add"],"*.json":["prettier --write","git add"]},"types":"./apisauce.d.ts","release":{"plugins":["@semantic-release/commit-analyzer","@semantic-release/release-notes-generator","@semantic-release/npm","@semantic-release/github",["@semantic-release/git",{"assets":"package.json","message":"chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"}]]},"husky":{"hooks":{"pre-commit":"lint-staged"}},"bugs":{"url":"https://github.com/atistler/apisauce/issues"},"homepage":"https://github.com/atistler/apisauce#readme","directories":{"example":"examples","lib":"lib","test":"test"},"gitHead":"021f270f7a893d69bfe705ab2b4de296c3cb6f67","_id":"@atistler/apisauce@1.1.2","_nodeVersion":"12.13.1","_npmVersion":"6.13.6","dist":{"integrity":"sha512-CJfQ7jQuoLzj03mBY+b+mwHqya5nPaRF+AtlBNfXpYVeqJcmC3U8q2aZoz3/r/rkH6teh6zf7gvi9r+LDxPOxg==","shasum":"700a0c4536da150f311920e0c9813eb457d59f22","tarball":"https://registry.npmjs.org/@atistler/apisauce/-/apisauce-1.1.2.tgz","fileCount":5,"unpackedSize":26605,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeVkwjCRA9TVsSAnZWagAAqHQP/jManjlvD1paAHgrVEra\n3Z7+brLejs2BMtHdUkbegZVEoz63EqE3zqTKu8IpOJ+AkuqJ2No/YxjsEMiu\nJom6ZEAsvQs/YYBCgtAkmTlpHDOJTZuNSRmXJmxlrM2uFXAAVIblEBjg5QrK\n6og9bIWhjOM8iwM74HKK3yKhxXU6zy740t7h2DLGZqU8zgIjB1X8WEfgR9iv\nKf2T5xhiZJ4v/NM9ozmT7Fx9eVi2kvb1Ik0nEnw/5T9JW++5Fd5GcBmEaElI\nC/MVERXGe0REfclCS83i257Holz7HVSbzrzXG08o40ugn0lSASI8aznj4X54\nTecHwMraeXDVxtCXtPcw0b/6ZspiHqY5JWILSBdWCI1b/1ORqnZT6TdP1Qla\nnvQEHm5uBBtjljJo8UyOKSPNeLadgsI2BDO8Wu853zr3y82jF82uWDx7UoIG\n4jKrmDlGhtEOvL//kwYSF+1xFLXsxj/U9UFcr1rLD60M269YrygMqeaIzqWH\nve2PAZBm9qVreobP1MfQiXSWfflDdDJ9HjmtDcfFyXWzK4KkptD8frT3Whxt\nfEiWG37K28fdvrl1Xi5X+Dul5xcJHb7gZShMvRRA0L0qjxc/dUnvPi9V1V1i\nq8AyPtOjx8Tw8zkyS7Xr3pLfl+rl2w07dM67cSTIEUcQTmeA+Iy0fJp9atDU\nqmW+\r\n=eMvw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDytb6BjK4c9c8QFZgf6NLa6ro/dB1CxM3dcHdzCtJQ/QIhAM8NXxbp6likpfKDbCx3G7tO5utI2D0Yk1Z4WW5ZANpH"}]},"maintainers":[{"name":"atistler1","email":"adam.tistler@rackspace.com"}],"_npmUser":{"name":"atistler1","email":"adam.tistler@rackspace.com"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/apisauce_1.1.2_1582713891055_0.19931230307094427"},"_hasShrinkwrap":false}},"time":{"created":"2020-02-26T10:44:50.824Z","1.1.2":"2020-02-26T10:44:51.163Z","modified":"2022-04-04T16:04:38.245Z"},"maintainers":[{"name":"atistler1","email":"adam.tistler@rackspace.com"}],"description":"Axios + standardized errors + request/response transforms.","homepage":"https://github.com/atistler/apisauce#readme","keywords":["axios","api","network","http"],"repository":{"type":"git","url":"git+https://github.com/atistler/apisauce.git"},"author":{"name":"Steve Kellock","email":"steve@kellock.ca"},"bugs":{"url":"https://github.com/atistler/apisauce/issues"},"license":"MIT","readme":"# Apisauce\n\n```\n(Ring ring ring)\n< Hello?\n> Hi, can I speak to JSON API.\n< Speaking.\n> Hi, it's me JavaScript.  Look, we need to talk.\n< Now is not a good time...\n> Wait, I just wanted to say, sorry.\n< ...\n```\n\nTalking to APIs doesn't have to be awkward anymore.\n\n[![npm module](https://badge.fury.io/js/apisauce.svg)](https://www.npmjs.org/package/apisauce)\n\n# Features\n\n- low-fat wrapper for the amazing `axios` http client library\n- all responses follow the same flow: success and failure alike\n- responses have a `problem` property to help guide exception flow\n- attach functions that get called each request\n- attach functions that change all request or response data\n- detects connection issues (on React Native)\n\n# Installing\n\n`npm i apisauce --save`\n\n- Depends on `axios@^0.19.0`.\n- Targets ES5.\n- Built with ES6.\n- Supported in Node and the browser(s) and React Native.\n\n# Quick Start\n\n```js\n// showLastCommitMessageForThisLibrary.js\nimport { create } from 'apisauce'\n\n// define the api\nconst api = create({\n  baseURL: 'https://api.github.com',\n  headers: { Accept: 'application/vnd.github.v3+json' },\n})\n\n// start making calls\napi\n  .get('/repos/skellock/apisauce/commits')\n  .then(response => response.data[0].commit.message)\n  .then(console.log)\n\n// customizing headers per-request\napi.post('/users', { name: 'steve' }, { headers: { 'x-gigawatts': '1.21' } })\n```\n\nSee the examples folder for more code.\n\n# Documentation\n\n## Create an API\n\nYou create an api by calling `.create()` and passing in a configuration object.\n\n```js\nconst api = create({ baseURL: 'https://api.github.com' })\n```\n\nThe only required property is `baseURL` and it should be the starting point for\nyour API. It can contain a sub-path and a port as well.\n\n```js\nconst api = create({ baseURL: 'https://example.com/api/v3' })\n```\n\nHTTP request headers for all requests can be included as well.\n\n```js\nconst api = create({\n  baseURL: '...',\n  headers: {\n    'X-API-KEY': '123',\n    'X-MARKS-THE-SPOT': 'yarrrrr',\n  },\n})\n```\n\nDefault timeouts can be applied too:\n\n```js\nconst api = create({ baseURL: '...', timeout: 30000 }) // 30 seconds\n```\n\nYou can also pass an already created axios instance\n\n```js\nimport axios from 'axios'\nimport { create } from 'apisauce'\n\nconst customAxiosInstance = axios.create({ baseURL: 'https://example.com/api/v3' })\n\nconst apisauceInstance = create({ axiosInstance: customAxiosInstance })\n```\n\n## Calling The API\n\nWith your fresh `api`, you can now call it like this:\n\n```js\napi.get('/repos/skellock/apisauce/commits')\napi.head('/me')\napi.delete('/users/69')\napi.post('/todos', { note: 'jump around' }, { headers: { 'x-ray': 'machine' } })\napi.patch('/servers/1', { live: false })\napi.put('/servers/1', { live: true })\napi.link('/images/my_dog.jpg', {}, { headers: { Link: '<http://example.com/profiles/joe>; rel=\"tag\"' } })\napi.unlink('/images/my_dog.jpg', {}, { headers: { Link: '<http://example.com/profiles/joe>; rel=\"tag\"' } })\napi.any({ method: 'GET' url: '/product', params: { id: 1 } })\n```\n\n`get`, `head`, `delete`, `link` and `unlink` accept 3 parameters:\n\n- url - the relative path to the API (required)\n- params - Object - query string variables (optional)\n- axiosConfig - Object - config passed along to the `axios` request (optional)\n\n`post`, `put`, and `patch` accept 3 different parameters:\n\n- url - the relative path to the API (required)\n- data - Object - the object jumping the wire\n- axiosConfig - Object - config passed along to the `axios` request (optional)\n\n`any` only accept one parameter\n\n- config - Object - config passed along to the `axios` request, this object same as `axiosConfig`\n\n## Responses\n\nThe responses are promise-based, so you'll need to handle things in a\n`.then()` function.\n\nThe promised is always resolved with a `response` object.\n\nEven if there was a problem with the request! This is one of the goals of\nthis library. It ensures sane calling code without having to handle `.catch`\nand have 2 separate flows.\n\nA response will always have these 2 properties:\n\n```\nok      - Boolean - True if the status code is in the 200's; false otherwise.\nproblem - String  - One of 6 different values (see below - problem codes)\n```\n\nIf the request made it to the server and got a response of any kind, response\nwill also have these properties:\n\n```\ndata     - Object - this is probably the thing you're after.\nstatus   - Number - the HTTP response code\nheaders  - Object - the HTTP response headers\nconfig   - Object - the `axios` config object used to make the request\nduration - Number - the number of milliseconds it took to run this request\n```\n\nSometimes on different platforms you need access to the original axios error\nthat was thrown:\n\n```\noriginalError - Error - the error that axios threw in case you need more info\n```\n\n## Changing Base URL\n\nYou can change the URL your api is connecting to.\n\n```js\napi.setBaseURL('https://some.other.place.com/api/v100')\nconsole.log(`omg i am now at ${api.getBaseURL()}`)\n```\n\n## Changing Headers\n\nOnce you've created your api, you're able to change HTTP requests by\ncalling `setHeader` or `setHeaders` on the api. These stay with the api instance, so you can just set ['em and forget 'em](https://gitter.im/infinitered/ignite?at=582e57563f3946057acd2f84).\n\n```js\napi.setHeader('Authorization', 'the new token goes here')\napi.setHeaders({\n  Authorization: 'token',\n  'X-Even-More': 'hawtness',\n})\n```\n\n## Adding Monitors\n\nMonitors are functions you can attach to the API which will be called\nwhen any request is made. You can use it to do things like:\n\n- check for headers and record values\n- determine if you need to trigger other parts of your code\n- measure performance of API calls\n- perform logging\n\nMonitors are run just before the promise is resolved. You get an\nearly sneak peak at what will come back.\n\nYou cannot change anything, just look.\n\nHere's a sample monitor:\n\n```js\nconst naviMonitor = response => console.log('hey!  listen! ', response)\napi.addMonitor(naviMonitor)\n```\n\nAny exceptions that you trigger in your monitor will not affect the flow\nof the api request.\n\n```js\napi.addMonitor(response => this.kaboom())\n```\n\nInternally, each monitor callback is surrounded by an oppressive `try/catch`\nblock.\n\nRemember. Safety first!\n\n## Adding Transforms\n\nIn addition to monitoring, you can change every request or response globally.\n\nThis can be useful if you would like to:\n\n- fix an api response\n- add/edit/delete query string variables for all requests\n- change outbound headers without changing everywhere in your app\n\nUnlike monitors, exceptions are not swallowed. They will bring down the stack, so careful!\n\n### Response Transforms\n\nFor responses, you're provided an object with these properties.\n\n- `data` - the object originally from the server that you might wanna mess with\n- `duration` - the number of milliseconds\n- `problem` - the problem code (see the bottom for the list)\n- `ok` - true or false\n- `status` - the HTTP status code\n- `headers` - the HTTP response headers\n- `config` - the underlying axios config for the request\n\nData is the only option changeable.\n\n```js\napi.addResponseTransform(response => {\n  const badluck = Math.floor(Math.random() * 10) === 0\n  if (badluck) {\n    // just mutate the data to what you want.\n    response.data.doorsOpen = false\n    response.data.message = 'I cannot let you do that.'\n  }\n})\n```\n\nOr make it async:\n\n```js\napi.addAsyncResponseTransform(response => {\n  const something = await AsyncStorage.load('something')\n  if (something) {\n    // just mutate the data to what you want.\n    response.data.doorsOpen = false\n    response.data.message = 'I cannot let you do that.'\n  }\n})\n```\n\n### Request Transforms\n\nFor requests, you are given a `request` object. Mutate anything in here to change anything about the request.\n\nThe object passed in has these properties:\n\n- `data` - the object being passed up to the server\n- `method` - the HTTP verb\n- `url` - the url we're hitting\n- `headers` - the request headers\n- `params` - the request params for `get`, `delete`, `head`, `link`, `unlink`\n\nRequest transforms can be a function:\n\n```js\napi.addRequestTransform(request => {\n  request.headers['X-Request-Transform'] = 'Changing Stuff!'\n  request.params['page'] = 42\n  delete request.params.secure\n  request.url = request.url.replace(/\\/v1\\//, '/v2/')\n  if (request.data.password && request.data.password === 'password') {\n    request.data.username = `${request.data.username} is secure!`\n  }\n})\n```\n\nAnd you can also add an async version for use with Promises or `async/await`. When you resolve\nyour promise, ensure you pass the request along.\n\n```js\napi.addAsyncRequestTransform(request => {\n  return new Promise(resolve => setTimeout(resolve, 2000))\n})\n```\n\n```js\napi.addAsyncRequestTransform(request => async () => {\n  await AsyncStorage.load('something')\n})\n```\n\nThis is great if you need to fetch an API key from storage for example.\n\nMultiple async transforms will be run one at a time in succession, not parallel.\n\n# Using Async/Await\n\nIf you're more of a `stage-0` kinda person, you can use it like this:\n\n```js\nconst api = create({ baseURL: '...' })\nconst response = await api.get('/slowest/site/on/the/net')\nconsole.log(response.ok) // yay!\n```\n\n# Problem Codes\n\nThe `problem` property on responses is filled with the best\nguess on where the problem lies. You can use a switch to\ncheck the problem. The values are exposed as `CONSTANTS`\nhanging on your built API.\n\n```\nConstant        VALUE               Status Code   Explanation\n----------------------------------------------------------------------------------------\nNONE             null               200-299       No problems.\nCLIENT_ERROR     'CLIENT_ERROR'     400-499       Any non-specific 400 series error.\nSERVER_ERROR     'SERVER_ERROR'     500-599       Any 500 series error.\nTIMEOUT_ERROR    'TIMEOUT_ERROR'    ---           Server didn't respond in time.\nCONNECTION_ERROR 'CONNECTION_ERROR' ---           Server not available, bad dns.\nNETWORK_ERROR    'NETWORK_ERROR'    ---           Network not available.\nCANCEL_ERROR     'CANCEL_ERROR'     ---           Request has been cancelled. Only possible if `cancelToken` is provided in config, see axios `Cancellation`.\n```\n\nWhich problem is chosen will be picked by walking down the list.\n\n# Contributing\n\nBugs? Comments? Features? PRs and Issues happily welcomed! Make sure to check out our [contributing guide](./github/CONTRIBUTING.md) to get started!\n","readmeFilename":"README.md"}