From 2dd2b55638a1fad7ab50e4bdd596b550aebdf49b Mon Sep 17 00:00:00 2001 From: Brett DeWoody Date: Sun, 19 Mar 2017 14:07:56 +0000 Subject: [PATCH] Add punkapi-javascript-wrapper --- .babelrc | 3 + .eslintrc.js | 14 ++ .gitignore | 2 + CONTRIBUTING.md | 11 ++ LICENSE | 22 +++ README.md | 247 ++++++++++++++++++++++++ bower.json | 17 ++ package.json | 37 ++++ src/punkapi-javascript-wrapper.js | 94 +++++++++ test/punkapi-javascript-wrapper.spec.js | 21 ++ webpack.config.js | 15 ++ 11 files changed, 483 insertions(+) create mode 100644 .babelrc create mode 100644 .eslintrc.js create mode 100644 .gitignore create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 bower.json create mode 100644 package.json create mode 100644 src/punkapi-javascript-wrapper.js create mode 100644 test/punkapi-javascript-wrapper.spec.js create mode 100644 webpack.config.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..4414b94 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ + { + "presets": ["es2015"] + } diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..5202e20 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,14 @@ +module.exports = { + "extends": "standard", + "plugins": [ + "standard", + "promise" + ], + "globals": { + "fetch": false, + "qa": false + }, + "rules": { + "no-extra-bind": 0 + } +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de4d1f0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +dist +node_modules diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e57d75c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# Contributing + +## Issues + +Open an issue for any problem you have with the wrapper. Please include any and all relevant information needed to reproduce the issue. + +## Contributions + +All new features and bug fixes should be submitted as pull requests, so the community can review and discuss them. + +When you submit a pull request, @mention me (@brettdewoody) so I'm notified and can review. Once reviewed and approved the pull request can be merged. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..138f5a1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2017 Brett DeWoody + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2282c75 --- /dev/null +++ b/README.md @@ -0,0 +1,247 @@ +# PunkAPI Javascript Wrapper + +A JS wrapper for the [BrewDog Punk API V2](https://punkapi.com/documentation/v2) - an API for retrieving data about [BrewDog's beers](https://www.brewdog.com/). + +## Installation + +There are 3 ways to install the PunkAPI Javascript Wrapper. + +#### Clone +Clone this repo into your project with: + + git clone https://github.com/brettdewoody/punkapi-javascript-wrapper.git + +#### NPM +Install via `npm` with: + + npm install --save punkapi-javascript-wrapper + +#### Bower +Install via `bower` with: + + bower install punkapi-javascript-wrapper + +## Usage + +There are several ways the wrapper can be used. The wrapper is available as a library script ([option #1](#library-option-1)), can be imported with [Webpack](https://webpack.github.io/) into a bundled script for the browser ([option #2](#webpack-for-the-browser-option-2)), or can be imported into Node ([option #3](#webpack-for-node-option-3)). + +**Library (Option #1)** + +Include the compiled library script on your page with: + + + +Then create a new instance of the `PunkAPIWrapper` and get to work: + + const punkAPI = new PunkAPIWrapper() + +**Webpack for the Browser (Option #2)** + +Import `PunkAPIWrapper` in your `entry` file with + + const PunkAPIWrapper = require('/path/to/punkapi-javascript-wrapper/src/punkapi-javascript-wrapper.js') + +Then create a new instance of `PunkAPIWrapper` and get to work: + + const punkAPI = new PunkAPIWrapper() + +Finally `webpack` your code using your Webpack config. + +**Node (Option #3)** + +The same implementation as Option #2. + +Import `PunkAPIWrapper` in your `entry` file with + + const PunkAPIWrapper = require(punkapi-javascript-wrapper) + +Then create a new instance of `PunkAPIWrapper` and get to work: + + const punkAPI = new PunkAPIWrapper() + +Here's a [Glitch demo](https://glitch.com/edit/#!/punkapi-javascript-wrapper-demo) showing how to use the wrapper in Node and the results: + +* A random beer - [https://punkapi-javascript-wrapper-demo.glitch.me/beer/random](https://punkapi-javascript-wrapper-demo.glitch.me/beer/random) +* A specific beer - [https://punkapi-javascript-wrapper-demo.glitch.me/beer/1](https://punkapi-javascript-wrapper-demo.glitch.me/beer/1) +* Strong beers (using a URL param of ?abv_gt=8) - [https://punkapi-javascript-wrapper-demo.glitch.me/beer?abv_gt=8](https://punkapi-javascript-wrapper-demo.glitch.me/beer?abv_gt=8) + +## Methods + +The wrapper provides 5 methods for retrieving all the BrewDog-related info you want: + +* [`punkAPI.getBeer(:id)`](#getbeerid) - a specific beer +* [`punkAPI.getBeers(:options)`]()- beers matching the options +* [`punkAPI.getRandom()`]() - a single random beer +* [`punkAPI.getRateLimit()`]() - total number of requests allowed to the PunkAPI in an hour +* [`punkAPI.getRateLimitRemaining()`]() - number of remaining requests allowed to the PunkAPI in the hour + +**Note:** All methods query the BrewDog Punk API using an asynchronous `fetch` request and return a [Promise](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise). This means you'll need to use `.then()` to wait for the response and provide a callback for handling the returned data. + + const punkAPI = new PunkAPIWrapper() + + const randomBeer = PunkAPI.getRandom() + + randomBeer.then(beer => { + alert(beer[0].name) + }) + +#### `getBeer(:id)` + +Returns an array of length 1 with the beer matching an ID of `:id`. `:id` should be a number corresponding to the ID of the desired beer. + +**Example:** const beer1 = punkAPI.getBeer(1) + +#### `getBeers(:options)` + +Returns an array with beers matching the `:options`. `:options` is an object consisting of available filters (below). + +**Example:** const strongBeers = punkAPI.getBeers({'abv_gt': 8}) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParamTypeDetails
abv_gtnumberReturns all beers with ABV greater than the supplied number
abv_ltnumberReturns all beers with ABV less than the supplied number
ibu_gtnumberReturns all beers with IBU greater than the supplied number
ibu_ltnumberReturns all beers with IBU less than the supplied number
ebc_gtnumberReturns all beers with EBC greater than the supplied number
ebc_ltnumberReturns all beers with EBC less than the supplied number
beer_namestringReturns all beers matching the supplied name (this will match partial strings as well so e.g punk will return Punk IPA), if you need to add spaces just add an underscore (_).
yeaststringReturns all beers matching the supplied yeast name, this performs a fuzzy match, if you need to add spaces just add an underscore (_).
brewed_beforedateReturns all beers brewed before this date, the date format is mm-yyyy e.g 10-2011
brewed_afterdateReturns all beers brewed after this date, the date format is mm-yyyy e.g 10-2011
hopsstringReturns all beers matching the supplied hops name, this performs a fuzzy match, if you need to add spaces just add an underscore (_).
maltstringReturns all beers matching the supplied malt name, this performs a fuzzy match, if you need to add spaces just add an underscore (_).
foodstringReturns all beers matching the supplied food string, this performs a fuzzy match, if you need to add spaces just add an underscore (_).
idsstring (id|id|...)Returns all beers matching the supplied ID's. You can pass in multiple ID's by separating them with a | symbol.
+ +For the most up-to-date filters please see the [PunkAPI docs](https://punkapi.com/documentation/v2). + +#### `getRandom()` + +Returns an array of length 1 with a random beer + +**Example:** const randomBeer = punkAPI.getRandom() + +#### `getRateLimit()` + +Returns a number displaying the rate limit. This is currently set to 3600 requests per hour per IP address. + +**Example:** const rateLimit= punkAPI.getRateLimit() + +#### `getRateLimitRemaining()` + +Returns a number displaying the available number of requests remaining for this IP address. + +**Example:** const rateLimitRemaining= punkAPI.getRateLimitRemaining() + +## Examples + +**Get a random beer** + + const randomBeer = PunkAPI.getRandom() + + randomBeer.then(beer => { + alert(beer[0].name) + }) + + +**Get strong beers** + + const strongBeers = PunkAPI.getBeers({'abv_gt': 8}) + + strongBeers.then(beers => { + beers.forEach(beer => { + alert(beer.name) + }) + }) + +**Get remaining request limit** + const remainingRequests = PunkAPI.getRateLimitRemaining() + + remainingRequests.then(requests => { + alert(requests) + }) + +## Contributing + +Please see the [Contributing Guide](/blob/develop/Contributing.md). + +## License + +This project is licensed under the terms of the MIT license. diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..2e6af3f --- /dev/null +++ b/bower.json @@ -0,0 +1,17 @@ +{ + "name": "punkapi-javascript-wrapper", + "description": "A Javascript wrapper for the PunkAPI", + "main": "dist/punkapi-javascript-wrapper.js", + "authors": [ + "Brett DeWoody (http://brettdewoody.com)" + ], + "license": "MIT", + "keywords": [ + "punkapi", + "beer", + "javascript", + "wrapper", + "api" + ], + "homepage": "https://github.com/brettdewoody/punkapi-javascript-wrapper" +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..65cabd4 --- /dev/null +++ b/package.json @@ -0,0 +1,37 @@ +{ + "name": "punkapi-javascript-wrapper", + "version": "1.0.0", + "description": "A Javascript wrapper for the PunkAPI", + "main": "src/punkapi-javascript-wrapper.js", + "scripts": { + "test": "test/punkapi-javascript-wrapper.spec.js" + }, + "keywords": [ + "punkapi", + "beer", + "javascript", + "wrapper", + "api" + ], + "author": "Brett DeWoody (http://brettdewoody.com)", + "license": "MIT", + "devDependencies": { + "babel-core": "^6.24.0", + "babel-loader": "^6.4.0", + "babel-preset-env": "^1.2.1", + "babel-preset-es2015": "^6.24.0", + "chai": "^3.5.0", + "eslint": "^3.17.1", + "eslint-config-standard": "^7.0.1", + "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-standard": "^2.1.1", + "mocha": "^3.2.0", + "should": "^11.2.1", + "webpack": "^2.2.1" + }, + "dependencies": { + "es6-promise": "^4.1.0", + "isomorphic-fetch": "^2.2.1", + "qs": "^6.4.0" + } +} diff --git a/src/punkapi-javascript-wrapper.js b/src/punkapi-javascript-wrapper.js new file mode 100644 index 0000000..6be23ae --- /dev/null +++ b/src/punkapi-javascript-wrapper.js @@ -0,0 +1,94 @@ +require('es6-promise').polyfill() +require('isomorphic-fetch') +const qs = require('qs') + +class PunkAPIWrapper { + constructor () { + this.baseURL = 'https://api.punkapi.com/v2' + this.rateLimit = null + this.rateLimitRemaining = null + this.doRequest = function (URL, options) { + const optionStr = qs.stringify(options) + + return fetch(URL + (options ? ['?', optionStr].join('') : '')) + .then(function (res) { + if (res.status >= 400) { + console.error('Bad response from server') + } + + this.rateLimit = res.headers.get('x-ratelimit-limit') + this.rateLimitRemaining = res.headers.get('x-ratelimit-remaining') + + return res.json() + }.bind(this)) + .then(function (json) { + return json + }) + .catch(function (err) { + console.error(err) + }) + } + } + + // Gets beers from the api, you can apply several filters using url + // paramaters, the available options are listed below. + getBeers (options) { + const URL = `${this.baseURL}/beers` + + return this.doRequest(URL, options) + } + + // Gets a beer from the api using the beers id. + getBeer (id) { + const URL = `${this.baseURL}/beers/${id}` + + if (!id) { + console.error('No beer ID provided.') + } + + return this.doRequest(URL) + } + + // Gets a random beer from the API, this takes no paramaters. + getRandom () { + const URL = `${this.baseURL}/beers/random` + + return this.doRequest(URL) + } + + // Gets the total rate limit set by the API + // The number returned is the total number of + // requests allowed per hour. + getRateLimit () { + return new Promise(function (resolve, reject) { + if (this.rateLimit) { + resolve(this.rateLimit) + } else { + resolve(this.getRandom() + .then(data => { + return this.rateLimit + })) + } + }.bind(this)) + } + + // Gets the remaining number of requests allowed + // by the API in the hour. That is, the rate limit minus + // the number of requests made in the past hour. + // The number returned is the number of + // remaining requests allowed per hour. + getRateLimitRemaining () { + return new Promise(function (resolve, reject) { + if (this.rateLimitRemaining) { + resolve(this.rateLimitRemaining) + } else { + resolve(this.getRandom() + .then(data => { + return this.rateLimitRemaining + })) + } + }.bind(this)) + } +} + +module.exports = PunkAPIWrapper diff --git a/test/punkapi-javascript-wrapper.spec.js b/test/punkapi-javascript-wrapper.spec.js new file mode 100644 index 0000000..5a11b80 --- /dev/null +++ b/test/punkapi-javascript-wrapper.spec.js @@ -0,0 +1,21 @@ +/* eslint-env node, mocha */ + +'use strict' + +const PunkAPI = require('../dist/punkapi-javascript-wrapper') +const should = require('chai').should() + +describe('punkapi-javascript-wrapper', function () { + let api = null + + beforeEach(function () { + api = new PunkAPI() + }) + + describe('Base URL', function () { + it('it should have the base API URL', function () { + const url = api.baseURL + url.should.equal('https://api.punkapi.com/v2') + }) + }) +}) diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..fc395b5 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,15 @@ +module.exports = { + entry: './src/punkapi-javascript-wrapper.js', + output: { + path: './dist', + filename: 'punkapi-javascript-wrapper.js', + library: 'PunkAPIWrapper' + }, + module: { + loaders: [{ + test: /\.js$/, + exclude: /node_modules/, + loader: 'babel-loader' + }] + } +}