diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..c13c5f6 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015"] +} diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..e9fa74e --- /dev/null +++ b/.eslintrc @@ -0,0 +1,62 @@ +{ + // http://eslint.org/docs/rules/ + + "ecmaFeatures": { + "binaryLiterals": false, // enable binary literals + "blockBindings": true, // enable let and const (aka block bindings) + "defaultParams": false, // enable default function parameters + "forOf": true, // enable for-of loops + "generators": false, // enable generators + "objectLiteralComputedProperties": false, // enable computed object literal property names + "objectLiteralDuplicateProperties": false, // enable duplicate object literal properties in strict mode + "objectLiteralShorthandMethods": false, // enable object literal shorthand methods + "objectLiteralShorthandProperties": false, // enable object literal shorthand properties + "octalLiterals": false, // enable octal literals + "regexUFlag": false, // enable the regular expression u flag + "regexYFlag": false, // enable the regular expression y flag + "templateStrings": true , // enable template strings + "unicodeCodePointEscapes": false, // enable code point escapes + "jsx": false, // enable JSX + "modules": true + }, + + "env": { + "browser": true, // browser global variables. + "node": true, // Node.js global variables and Node.js-specific rules. + "amd": true, // defines require() and define() as global variables as per the amd spec. + "es6": true // EcmaScript 6 + }, + + "globals": { + // e.g. "angular": true + }, + + "plugins": [ + // e.g. "react" (must run `npm install eslint-plugin-react` first) + ], + + "rules": { + ////////// Possible Errors ////////// + + "valid-typeof": 2, // Ensure that the results of typeof are compared against a valid string + + + ////////// Best Practices ////////// + + "eqeqeq": 2, // require the use of === and !== + "no-alert": 2, // disallow the use of alert, confirm, and prompt + + ////////// Stylistic Issues ////////// + + "eol-last": 2, // enforce newline at the end of file, with no multiple empty lines + "no-lonely-if": 2, // disallow if as the only statement in an else block (off by default) + "no-mixed-spaces-and-tabs": 2, // disallow mixed spaces and tabs for indentation + "no-multiple-empty-lines": 2, // disallow multiple empty lines (off by default) + "no-trailing-spaces": 2, // disallow trailing whitespace at the end of lines + + "quotes": [ + 2, + "double" + ] + } +} diff --git a/.gitignore b/.gitignore index 2bc2c81..9a5334e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +node_modules +npm-debug.log RELEASE_MESSAGE* -test* +test/codebirdm.js +test/codebirdt.js +test*.html *.jpg diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..44e72cd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,27 @@ +# The Travis setup: +# - run lint for every JS version +# - run testsuite for every JS version + +language: node_js + +node_js: + - "0.10" + - "0.12" + - iojs + - "8" + - "9" + - "10" + +sudo: false + +script: + - ./node_modules/eslint/bin/eslint.js codebird.js + - npm test + +matrix: + fast_finish: true + +# trigger Buildtime Trend Service to parse Travis CI log +notifications: + webhooks: + - https://buildtimetrend.herokuapp.com/travis diff --git a/CHANGELOG b/CHANGELOG index 51eb546..b492cbf 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,26 @@ codebird-js - changelog ======================= +3.0.0 (not yet released) ++ #106 Add error callback ++ #96 Add logout method ++ #98 Support promises as alternative to callbacks +- Drop support for undocumented API methods ++ Add security check hasOwnProperty ++ #110 Add support for Collections API ++ Transform codebase to EcmaScript 7 ++ #25 Add unit testing suite ++ Add POST statuses/unretweet/:id ++ #116 Update GET statuses/oembed with new endpoint ++ Support POST media/upload with media_data base64 +- Fix check for require for webpack compatibility ++ Add Account Activity API methods ++ Add new Direct Messages API +- Remove sunsetting Direct Messages API +- Remove contributor API methods +- Remove deprecated statuses/update_with_media method +- Remove deprecated statuses/update_profile_background_image method + 2.6.0 (2015-04-08) + Allow to get the supported API methods as array - #79 Use POST for users/lookup and statuses/lookup, params may get too long for GET diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f1a2b6b..dd443d1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,9 +3,13 @@ - Normal bugs are fixed in the develop branch. - New features are added to the develop branch, too. +### Which file? +- Please apply all edits to the `codebird.es7.js` file. + The codebird.js file is transpiled from it using BabelJS. + ### Code style -- Please use 4 soft spaces per indent level. -- Take a look at the coding style used in codebird.js and apply the same convention to your contributed code. +- Please use 2 soft spaces per indent level. +- Take a look at the coding style used in `codebird.es7.js` and apply the same convention to your contributed code. ### License - Code contributed by you will get the same license as Codebird itself, that is, GPU General Public License V3. diff --git a/README.md b/README.md index 775a8d0..0f05c2d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ codebird-js =========== *A Twitter library in JavaScript.* -Copyright (C) 2010-2015 Jublo Solutions +Copyright (C) 2010-2018 Jublo Limited This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,6 +17,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . +[![Travis Status](https://img.shields.io/travis/jublonet/codebird-js/develop.svg)](https://travis-ci.org/jublonet/codebird-js/branches) + Including Codebird ------------------ @@ -73,22 +75,41 @@ Or you authenticate, like this: cb.__call( "oauth_requestToken", {oauth_callback: "oob"}, - function (reply) { - // stores it - cb.setToken(reply.oauth_token, reply.oauth_token_secret); + function (reply,rate,err) { + if (err) { + console.log("error response or timeout exceeded" + err.error); + } + if (reply) { + // stores it + cb.setToken(reply.oauth_token, reply.oauth_token_secret); - // gets the authorize screen URL - cb.__call( - "oauth_authorize", - {}, - function (auth_url) { - window.codebird_auth = window.open(auth_url); - } - ); + // gets the authorize screen URL + cb.__call( + "oauth_authorize", + {}, + function (auth_url) { + window.codebird_auth = window.open(auth_url); + } + ); + } } ); ``` +:warning: Codebird server calls do not always go through when +being processed in a hyperlink onclick handler. Be sure to cancel +the default procedure before calling Codebird, like this (jQuery): + +```javascript +$(function() { + + $('#auth').click(function(e) { + e.preventDefault(); + + var cb = new Codebird; +// ... +``` + Now you need to add a PIN box to your website. After the user enters the PIN, complete the authentication: @@ -96,9 +117,14 @@ After the user enters the PIN, complete the authentication: cb.__call( "oauth_accessToken", {oauth_verifier: document.getElementById("PINFIELD").value}, - function (reply) { - // store the authenticated token, which may be different from the request token (!) - cb.setToken(reply.oauth_token, reply.oauth_token_secret); + function (reply,rate,err) { + if (err) { + console.log("error response or timeout exceeded" + err.error); + } + if (reply) { + // store the authenticated token, which may be different from the request token (!) + cb.setToken(reply.oauth_token, reply.oauth_token_secret); + } // if you need to persist the login after page reload, // consider storing the token in a cookie or HTML5 local storage @@ -106,6 +132,15 @@ cb.__call( ); ``` +### Logging out + +In case you want to log out the current user (to log in a different user without +creating a new Codebird object), just call the `logout()` method. + +```javascript +cb.logout(); +``` + ### Application-only auth Some API methods also support authenticating on a per-application level. @@ -118,8 +153,14 @@ To obtain an app-only bearer token, call the appropriate API: cb.__call( "oauth2_token", {}, - function (reply) { - var bearer_token = reply.access_token; + function (reply, err) { + var bearer_token; + if (err) { + console.log("error response or timeout exceeded" + err.error); + } + if (reply) { + bearer_token = reply.access_token; + } } ); ``` @@ -137,7 +178,6 @@ For sending an API request with app-only auth, see the ‘Usage examples’ sect ### Authenticating using a callback URL, without PIN - 1. Before sending your user off to Twitter, you have to store the request token and its secret, for example in a cookie. 2. In the callback URL, extract those values and assign them to the Codebird object. 3. Extract the ```oauth_verifier``` field from the request URI. @@ -172,8 +212,13 @@ if (typeof parameters.oauth_verifier !== "undefined") { { oauth_verifier: parameters.oauth_verifier }, - function (reply) { - cb.setToken(reply.oauth_token, reply.oauth_token_secret); + function (reply, rate, err) { + if (err) { + console.log("error response or timeout exceeded" + err.error); + } + if (reply) { + cb.setToken(reply.oauth_token, reply.oauth_token_secret); + } // if you need to persist the login after page reload, // consider storing the token in a cookie or HTML5 local storage @@ -198,8 +243,9 @@ cb.setToken("YOURTOKEN", "YOURTOKENSECRET"); // see above cb.__call( "statuses_homeTimeline", {}, - function (reply) { + function (reply, rate, err) { console.log(reply); + console.log(err); } ); ``` @@ -210,7 +256,7 @@ Tweeting is as easy as this: cb.__call( "statuses_update", {"status": "Whohoo, I just tweeted!"}, - function (reply) { + function (reply, rate, err) { // ... } ); @@ -224,7 +270,7 @@ var params = "status=" + encodeURIComponent("Fish & chips"); cb.__call( "statuses_update", params, - function (reply) { + function (reply, rate, err) { // ... } ); @@ -240,7 +286,7 @@ var params = { cb.__call( "statuses_update", params, - function (reply) { + function (reply, rate, err) { // ... } ); @@ -253,7 +299,7 @@ var params = { cb.__call( "users_show", params, - function (reply) { + function (reply, rate, err) { // ... } ); @@ -279,12 +325,12 @@ base64-encoded. **First** you send each image to Twitter, like this: ```javascript var params = { - "media": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB+0lEQVR42mP8//8/Ay0BEwONwagFoxZQDljI0PP8x7/Z93/e+PxXmpMpXp5dh4+ZgYHh0bd/clxYnMuINaMtfvRLgp3RVZwVU+rkuz+eRz+//wXVxcrEkKnEceXTX0dRlhoNTmKDaOvzXwHHv6x9+gtN/M9/hpjTX+GmMzAw/P7HMOnOj+ff//35x/Ds+z9iLfjPwPDt7//QE1/Sz319/RNh3PkPf+58+Yup/t7Xf9p8zFKcTMRa4CLGCrFm1v2fSjs+pJ/7uuvl7w+//yO7HRkUq3GEyrCREMk+kqy2IiyH3/xhYGD48uf/rPs/Z93/yczIwM3CiFU9Hw5xnD4ouvTt4Tf0AP37n+HTb+w+UOBmIs2CICm2R9/+EZlqGRkYzIVYSLMgRIYtUYGdSAsMBFgUuJhIy2iMDAwt2pysjAwLHv78RcgnOcrs5BQVHEyMG579Imi6Nh9zrBxZFgixMW624pXnwldYcTAzLjDhZmUit7AzE2K54c7fp8eF1QhWRobFptwmgiwkF3b//jMwMjJ8+P3/zPs/yx/9Wvr412+MgBJlZ1xsyuOOrbAibMHH3/87b32fce/nR2ypnpuFMVGevU6TQ5SdqKKeEVez5cuf/7te/j727s+9L/++/v3PzcyowM1kIcTiLs7Kz8pIfNnOONouGrVg1AIGAJ6gvN4J6V9GAAAAAElFTkSuQmCC" + "media_data": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAB+0lEQVR42mP8//8/Ay0BEwONwagFoxZQDljI0PP8x7/Z93/e+PxXmpMpXp5dh4+ZgYHh0bd/clxYnMuINaMtfvRLgp3RVZwVU+rkuz+eRz+//wXVxcrEkKnEceXTX0dRlhoNTmKDaOvzXwHHv6x9+gtN/M9/hpjTX+GmMzAw/P7HMOnOj+ff//35x/Ds+z9iLfjPwPDt7//QE1/Sz319/RNh3PkPf+58+Yup/t7Xf9p8zFKcTMRa4CLGCrFm1v2fSjs+pJ/7uuvl7w+//yO7HRkUq3GEyrCREMk+kqy2IiyH3/xhYGD48uf/rPs/Z93/yczIwM3CiFU9Hw5xnD4ouvTt4Tf0AP37n+HTb+w+UOBmIs2CICm2R9/+EZlqGRkYzIVYSLMgRIYtUYGdSAsMBFgUuJhIy2iMDAwt2pysjAwLHv78RcgnOcrs5BQVHEyMG579Imi6Nh9zrBxZFgixMW624pXnwldYcTAzLjDhZmUit7AzE2K54c7fp8eF1QhWRobFptwmgiwkF3b//jMwMjJ8+P3/zPs/yx/9Wvr412+MgBJlZ1xsyuOOrbAibMHH3/87b32fce/nR2ypnpuFMVGevU6TQ5SdqKKeEVez5cuf/7te/j727s+9L/++/v3PzcyowM1kIcTiLs7Kz8pIfNnOONouGrVg1AIGAJ6gvN4J6V9GAAAAAElFTkSuQmCC" ); cb.__call( "media_upload", params, - function (reply) { + function (reply, rate, err) { // you get a media id back: console.log(reply.media_id_string); @@ -303,13 +349,13 @@ cb.__call( "media_ids": "12345678901234567890,9876543210987654321" "status": "Whohoo, I just tweeted two images!" }, - function (reply) { + function (reply, rate, err) { // ... } ); ``` -More [documentation for tweeting with media](https://dev.twitter.com/rest/public/uploading-media-multiple-photos) is available on the Twitter Developer site. +More [documentation for uploading media](https://developer.twitter.com/en/docs/media/upload-media/overview) is available on the Twitter Developer site. ### Requests with app-only auth @@ -371,7 +417,7 @@ The library returns the response HTTP status code, so you can detect rate limits I suggest you to check if the ```reply.httpstatus``` property is ```400``` and check with the Twitter API to find out if you are currently being rate-limited. -See the [Rate Limiting FAQ](https://dev.twitter.com/rest/public/rate-limiting) +See the [Rate Limiting FAQ](https://developer.twitter.com/en/docs/basics/rate-limiting) for more information. If you allow your callback function to accept a second parameter, @@ -588,28 +634,96 @@ When this error occurs, advise the user to [generate a temporary password](https://twitter.com/settings/applications) on twitter.com and use that to complete signing in to the application. -### …access and use undocumented Twitter API methods? +### …access the Collections API? + +Collections are a type of timeline that you control and can be hand curated +and/or programmed using an API. + +Pay close attention to the differences in how collections are presented — +often they will be decomposed, efficient objects with information about users, +Tweets, and timelines grouped, simplified, and stripped of unnecessary repetition. -Besides the well-documented official methods, the Twitter API also contains -undocumented additional methods. They are used by official Twitter clients, -such as Twitter for iPhone and Twitter for Mac. +Never care about the OAuth signing specialities and the JSON POST body +for POST and PUT calls to these special APIs. Codebird takes off the work for you +and will always send the correct Content-Type automatically. -Access to these methods is restricted: Only white-listed applications -(consumer keys) may access undocumented methods. Codebird supports accessing -internal methods, but that will only work if you provide a white-listed API key. -By reason, the API keys and secrets for official Twitter clients are not -provided within this package, since they should have been kept a secret. +Find out more about the [Collections API](https://developer.twitter.com/en/docs/tweets/curate-a-collection/overview/about_collections) in the Twitter API docs. +More information on the [Direct Messages API](https://developer.twitter.com/en/docs/direct-messages/api-features) and the [Account Activity API](https://developer.twitter.com/en/docs/accounts-and-users/subscribe-account-activity/overview) is available there as well. -If you provide Codebird with the Twitter for iPhone consumer key and secret, -the following example will get the latest events that happened with you: +Here’s a sample for adding a Tweet using the Collections API: ```javascript cb.__call( - "activity_aboutMe", - {}, - function (reply) { - console.log(reply); - // ... + "collections_entries_curate", + { + "id": "custom-672852634622144512", + "changes": [ + {"op": "add", "tweet_id": "672727928262828032"} + ] + }, + function (reply, rate) { + document.body.innerText = JSON.stringify(reply); } ); ``` + +### …use promises instead of callback functions? + +Have you ever heard of the [Pyramid of Doom](http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/)? +It’s when code progresses more to the right because of excessive nesting +than it progresses from top to bottom. + +Because of the asynchronous requests, Codebird will use callbacks that you provide. +They are called when the result from the Twitter API has arrived. +However, to streamline code, there is a sleeker concept for this: Promises. + +There are several popular libraries that support promises. +Codebird will auto-detect and use any of the following: + +- jQuery Deferred +- Q +- RSVP +- when + +Here’s a usage sample for promises: + +```javascript +cb.__call( + "statuses_update", + {"status": "Whohoo, I just tweeted!"} +).then(function (data) { + var reply = data.reply, + rate = data.rate; + // ... + }, + function (err) { + // ... + }); +``` + +Since the app-only flag is the fourth parameter for `__call`, +you’ll have to provide a callback stub nonetheless even with promises: + +```javascript +cb.__call( + "search_tweets", + {"q": "#PHP7"}, + null, // no callback needed, we have the promise + true // app-only auth + +).then(function (data) { + var reply = data.reply, + rate = data.rate; + // ... + }, + function (err) { + // ... + }); +``` + +**Tips:** + +- If you provide **both** (callback and promise.then), + Codebird will first call the callback, then resolve the promise. + +- If the request fails due to any errors, Codebird will reject the promise. diff --git a/bower.json b/bower.json index c19e1aa..80d45d5 100644 --- a/bower.json +++ b/bower.json @@ -1,13 +1,13 @@ { "name": "codebird-js", - "version": "2.6.0", + "version": "3.0.0-dev", "homepage": "http://www.jublo.net/projects/codebird/js", "authors": [ "Joshua Atkins ", "J.M. " ], "description": "A Twitter library in JavaScript.", - "main": "codebird.js", + "main": "codebird.es7.js", "moduleType": [ "amd", "globals", @@ -25,7 +25,6 @@ "node_modules", "bower_components", "RELEASE_MESSAGE*", - "test", - "tests" + "test" ] } diff --git a/codebird.es7.js b/codebird.es7.js new file mode 100644 index 0000000..b35bcf6 --- /dev/null +++ b/codebird.es7.js @@ -0,0 +1,1621 @@ +/** + * A Twitter library in JavaScript + * + * @package codebird + * @version 3.0.0-dev + * @author Jublo Limited + * @copyright 2010-2018 Jublo Limited + * @license http://opensource.org/licenses/GPL-3.0 GNU Public License 3.0 + * @link https://github.com/jublonet/codebird-php + */ + +/* global window, + document, + navigator, + Ti, + ActiveXObject, + module, + define, + require */ + +(() => { + /** + * A Twitter library in JavaScript + * + * @package codebird + * @subpackage codebird-js + */ + class Codebird { + + constructor() { + /** + * The OAuth consumer key of your registered app + */ + this._oauth_consumer_key = null; + + /** + * The corresponding consumer secret + */ + this._oauth_consumer_secret = null; + + /** + * The app-only bearer token. Used to authorize app-only requests + */ + this._oauth_bearer_token = null; + + /** + * The API endpoint base to use + */ + this._endpoint_base = "https://api.twitter.com/"; + + /** + * The media API endpoint base to use + */ + this._endpoint_base_media = "https://upload.twitter.com/"; + + /** + * The API endpoint to use + */ + this._endpoint = `${this._endpoint_base}1.1/`; + + /** + * The media API endpoint to use + */ + this._endpoint_media = `${this._endpoint_base_media}1.1/`; + + /** + * The publish API endpoint to use + */ + this._endpoint_publish = "https://publish.twitter.com/"; + + /** + * The API endpoint base to use + */ + this._endpoint_oauth = this._endpoint_base; + + /** + * API proxy endpoint + */ + this._endpoint_proxy = "https://api.jublo.net/codebird/"; + + /** + * Whether to access the API via a proxy that is allowed by CORS + * Assume that CORS is only necessary in browsers + */ + this._use_proxy = (typeof navigator !== "undefined" + && typeof navigator.userAgent !== "undefined" + ); + + /** + * The Request or access token. Used to sign requests + */ + this._oauth_token = null; + + /** + * The corresponding request or access token secret + */ + this._oauth_token_secret = null; + + /** + * The current Codebird version + */ + this._version = "3.0.0-dev"; + + this.b64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + } + + /** + * Sets the OAuth consumer key and secret (App key) + * + * @param string key OAuth consumer key + * @param string secret OAuth consumer secret + * + * @return void + */ + setConsumerKey(key, secret) { + this._oauth_consumer_key = key; + this._oauth_consumer_secret = secret; + } + + /** + * Sets the OAuth2 app-only auth bearer token + * + * @param string token OAuth2 bearer token + * + * @return void + */ + setBearerToken(token) { + this._oauth_bearer_token = token; + } + + /** + * Gets the current Codebird version + * + * @return string The version number + */ + getVersion() { + return this._version; + } + + /** + * Sets the OAuth request or access token and secret (User key) + * + * @param string token OAuth request or access token + * @param string secret OAuth request or access token secret + * + * @return void + */ + setToken(token, secret) { + this._oauth_token = token; + this._oauth_token_secret = secret; + } + + /** + * Forgets the OAuth request or access token and secret (User key) + * + * @return bool + */ + logout() { + this._oauth_token = + this._oauth_token_secret = null; + + return true; + } + + /** + * Enables or disables CORS proxy + * + * @param bool use_proxy Whether to use CORS proxy or not + * + * @return void + */ + setUseProxy(use_proxy) { + this._use_proxy = !!use_proxy; + } + + /** + * Sets custom CORS proxy server + * + * @param string proxy Address of proxy server to use + * + * @return void + */ + setProxy(proxy) { + // add trailing slash if missing + if (!proxy.match(/\/$/)) { + proxy += "/"; + } + this._endpoint_proxy = proxy; + } + + /** + * Signing helpers + */ + + /** + * URL-encodes the given data + * + * @param mixed data + * + * @return mixed The encoded data + */ + _url(data) { + if ((/boolean|number|string/).test(typeof data)) { + return encodeURIComponent(data).replace(/!/g, "%21").replace(/'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A"); + } else { + return ""; + } + } + + /** + * Gets the base64-encoded SHA1 hash for the given data + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined + * in FIPS PUB 180-1 + * Based on version 2.1 Copyright Paul Johnston 2000 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + * + * @param string data The data to calculate the hash from + * + * @return string The hash + */ + _sha1(e) { + function n (e, b) { + e[b >> 5] |= 128 << 24 - b % 32; + e[(b + 64 >> 9 << 4) + 15] = b; + for (var c = new Array(80), a = 1732584193, d = -271733879, h = -1732584194, + k = 271733878, g = -1009589776, p = 0; p < e.length; p += 16) { + for (var o = a, q = d, r = h, s = k, t = g, f = 0; 80 > f; f++) { + let m; + + if (f < 16) { + m = e[p + f]; + } else { + m = c[f - 3] ^ c[f - 8] ^ c[f - 14] ^ c[f - 16]; + m = m << 1 | m >>> 31; + } + + c[f] = m; + m = l(l(a << 5 | a >>> 27, 20 > f ? d & h | ~d & k : 40 > f ? d ^ + h ^ k : 60 > f ? d & h | d & k | h & k : d ^ h ^ k), l( + l(g, c[f]), 20 > f ? 1518500249 : 40 > f ? 1859775393 : + 60 > f ? -1894007588 : -899497514)); + g = k; + k = h; + h = d << 30 | d >>> 2; + d = a; + a = m; + } + a = l(a, o); + d = l(d, q); + h = l(h, r); + k = l(k, s); + g = l(g, t); + } + return [a, d, h, k, g]; + } + + function l(e, b) { + var c = (e & 65535) + (b & 65535); + return (e >> 16) + (b >> 16) + (c >> 16) << 16 | c & 65535; + } + + function q(e) { + for (var b = [], c = (1 << g) - 1, a = 0; a < e.length * g; a += g) { + b[a >> 5] |= (e.charCodeAt(a / g) & c) << 24 - a % 32; + } + return b; + } + var g = 8; + + let b = `${this._oauth_consumer_secret}&${null !== this._oauth_token_secret ? + this._oauth_token_secret : ""}`; + if (this._oauth_consumer_secret === null) { + throw "To generate a hash, the consumer secret must be set."; + } + let c = q(b); + if (c.length > 16) { + c = n(c, b.length * g); + } + let bb = new Array(16); + for (var a = new Array(16), d = 0; d < 16; d++) { + a[d] = c[d] ^ 909522486; + bb[d] = c[d] ^ 1549556828; + } + c = n(a.concat(q(e)), 512 + e.length * g); + bb = n(bb.concat(c), 672); + b = ""; + for (g = 0; g < 4 * bb.length; g += 3) { + for (d = (bb[g >> 2] >> 8 * (3 - g % 4) & 255) << 16 | (bb[g + 1 >> 2] >> + 8 * (3 - (g + 1) % 4) & 255) << 8 | bb[g + 2 >> 2] >> 8 * (3 - + (g + 2) % 4) & 255, e = 0; 4 > e; e++) { + b = 8 * g + 6 * e > 32 * bb.length ? b + "=" : b + + this.b64_alphabet.charAt(d >> 6 * (3 - e) & 63); + } + } + return b; + } + + /* + * Gets the base64 representation for the given data + * + * http://phpjs.org + * + original by: Tyler Akins (http://rumkin.com) + * + improved by: Bayron Guevara + * + improved by: Thunder.m + * + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + * + bugfixed by: Pellentesque Malesuada + * + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + * + improved by: Rafał Kukawski (http://kukawski.pl) + * + * @param string data The data to calculate the base64 representation from + * + * @return string The base64 representation + */ + _base64_encode(a) { + let d, e, f, b, g = 0, + h = 0, + i = this.b64_alphabet, + c = []; + if (!a) { + return a; + } + do { + d = a.charCodeAt(g++); + e = a.charCodeAt(g++); + f = a.charCodeAt(g++); + b = d << 16 | e << 8 | f; + d = b >> 18 & 63; + e = b >> 12 & 63; + f = b >> 6 & 63; + b &= 63; + c[h++] = i.charAt(d) + i.charAt(e) + i.charAt(f) + i.charAt(b); + } while (g < a.length); + i = c.join(""); + a = a.length % 3; + return (a ? i.slice(0, a - 3) : i) + "===".slice(a || 3); + } + + /* + * Builds a HTTP query string from the given data + * + * http://phpjs.org + * + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + * + improved by: Legaev Andrey + * + improved by: Michael White (http://getsprink.com) + * + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + * + improved by: Brett Zamir (http://brett-zamir.me) + * + revised by: stag019 + * + input by: Dreamer + * + bugfixed by: Brett Zamir (http://brett-zamir.me) + * + bugfixed by: MIO_KODUKI (http://mio-koduki.blogspot.com/) + * + * @param string data The data to concatenate + * + * @return string The HTTP query + */ + _http_build_query(e, f, b) { + function g(c, a, d) { + let b, e = []; + if (a === true) { + a = "1"; + } else if (a === false) { + a = "0"; + } + if (null !== a) { + if (typeof a === "object") { + for (b in a) { + if (a.hasOwnProperty(b) && a[b] !== null) { + e.push(g.call(this, c + "[" + b + "]", a[b], d)); + } + } + return e.join(d); + } + if (typeof a !== "function") { + return this._url(c) + "=" + this._url(a); + } + throw "There was an error processing for http_build_query()."; + } else { + return ""; + } + } + var d, c, h = []; + if (!b) { + b = "&"; + } + for (c in e) { + if (!e.hasOwnProperty(c)) { + continue; + } + d = e[c]; + if (f && !isNaN(c)) { + c = String(f) + c; + } + d = g.call(this, c, d, b); + if (d !== "") { + h.push(d); + } + } + return h.join(b); + } + + /** + * Generates a (hopefully) unique random string + * + * @param int optional length The length of the string to generate + * + * @return string The random string + */ + _nonce(length = 8) { + if (length < 1) { + throw "Invalid nonce length."; + } + let nonce = ""; + for (let i = 0; i < length; i++) { + let character = Math.floor(Math.random() * 61); + nonce += this.b64_alphabet.substring(character, character + 1); + } + return nonce; + } + + /** + * Sort array elements by key + * + * @param array input_arr The array to sort + * + * @return array The sorted keys + */ + _ksort(input_arr) { + let keys = [], sorter, k; + + sorter = (a, b) => { + let a_float = parseFloat(a), + b_float = parseFloat(b), + a_numeric = a_float + "" === a, + b_numeric = b_float + "" === b; + if (a_numeric && b_numeric) { + return a_float > b_float ? 1 : a_float < b_float ? -1 : 0; + } else if (a_numeric && !b_numeric) { + return 1; + } else if (!a_numeric && b_numeric) { + return -1; + } + return a > b ? 1 : a < b ? -1 : 0; + }; + + // Make a list of key names + for (k in input_arr) { + if (input_arr.hasOwnProperty(k)) { + keys.push(k); + } + } + keys.sort(sorter); + return keys; + } + + /** + * Clone objects + * + * @param object obj The object to clone + * + * @return object clone The cloned object + */ + _clone(obj) { + let clone = {}; + for (let i in obj) { + if (typeof (obj[i]) === "object") { + clone[i] = this._clone(obj[i]); + } else { + clone[i] = obj[i]; + } + } + return clone; + } + + /** + * Gets the XML HTTP Request object, trying to load it in various ways + * + * @return object The XMLHttpRequest object instance + */ + _getXmlRequestObject() { + let xml = null; + // first, try the W3-standard object + if (typeof window === "object" + && window + && typeof window.XMLHttpRequest !== "undefined" + ) { + xml = new window.XMLHttpRequest(); + // then, try Titanium framework object + } else if (typeof Ti === "object" + && Ti + && typeof Ti.Network.createHTTPClient !== "undefined" + ) { + xml = Ti.Network.createHTTPClient(); + // are we in an old Internet Explorer? + } else if (typeof ActiveXObject !== "undefined" + ) { + try { + xml = new ActiveXObject("Microsoft.XMLHTTP"); + } catch (e) { + throw "ActiveXObject object not defined."; + } + // now, consider RequireJS and/or Node.js objects + } else if (typeof require === "function") { + var XMLHttpRequest; + // look for xmlhttprequest module + try { + XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; + xml = new XMLHttpRequest(); + } catch (e1) { + // or maybe the user is using xhr2 + try { + XMLHttpRequest = require("xhr2"); + xml = new XMLHttpRequest(); + } catch (e2) { + throw "xhr2 object not defined, cancelling."; + } + } + } + return xml; + } + + /** + * Parse URL-style parameters into object + * + * version: 1109.2015 + * discuss at: http://phpjs.org/functions/parse_str + * + original by: Cagri Ekin + * + improved by: Michael White (http://getsprink.com) + * + tweaked by: Jack + * + bugfixed by: Onno Marsman + * + reimplemented by: stag019 + * + bugfixed by: Brett Zamir (http://brett-zamir.me) + * + bugfixed by: stag019 + * - depends on: urldecode + * + input by: Dreamer + * + bugfixed by: Brett Zamir (http://brett-zamir.me) + * % note 1: When no argument is specified, will put variables in global scope. + * + * @param string str String to parse + * @param array array to load data into + * + * @return object + */ + _parse_str(str, array) { + var glue1 = "=", + glue2 = "&", + array2 = String(str).replace(/^&?([\s\S]*?)&?$/, "$1").split(glue2), + i, j, chr, tmp, key, value, bracket, keys, evalStr, + fixStr = str => { + return decodeURIComponent(str).replace(/([\\"'])/g, "\\$1").replace(/\n/g, "\\n").replace(/\r/g, "\\r"); + }; + if (!array) { + array = this.window; + } + + for (i = 0; i < array2.length; i++) { + tmp = array2[i].split(glue1); + if (tmp.length < 2) { + tmp = [tmp, ""]; + } + key = fixStr(tmp[0]); + value = fixStr(tmp[1]); + while (key.charAt(0) === " ") { + key = key.substr(1); + } + if (key.indexOf("\0") > -1) { + key = key.substr(0, key.indexOf("\0")); + } + if (key && key.charAt(0) !== "[") { + keys = []; + bracket = 0; + for (j = 0; j < key.length; j++) { + if (key.charAt(j) === "[" && !bracket) { + bracket = j + 1; + } else if (key.charAt(j) === "]") { + if (bracket) { + if (!keys.length) { + keys.push(key.substr(0, bracket - 1)); + } + keys.push(key.substr(bracket, j - bracket)); + bracket = 0; + if (key.charAt(j + 1) !== "[") { + break; + } + } + } + } + if (!keys.length) { + keys = [key]; + } + for (j = 0; j < keys[0].length; j++) { + chr = keys[0].charAt(j); + if (chr === " " || chr === "." || chr === "[") { + keys[0] = keys[0].substr(0, j) + "_" + keys[0].substr(j + 1); + } + if (chr === "[") { + break; + } + } + evalStr = "array"; + for (j = 0; j < keys.length; j++) { + key = keys[j]; + if ((key !== "" && key !== " ") || j === 0) { + key = `'${key}'`; + } else { + key = eval(evalStr + ".push([]);") - 1; + } + evalStr += `[${key}]`; + if (j !== keys.length - 1 && eval("typeof " + evalStr) === "undefined") { + eval(evalStr + " = [];"); + } + } + evalStr += " = '" + value + "';\n"; + eval(evalStr); + } + } + } + + /** + * Get allowed API methods, sorted by GET or POST + * Watch out for multiple-method "account/settings"! + * + * @return array $apimethods + */ + getApiMethods() { + const httpmethods = { + GET: [ + "account/settings", + "account/verify_credentials", + "account_activity/all/:env_name/subscriptions", + "account_activity/all/:env_name/subscriptions/list", + "account_activity/all/:env_name/webhooks", + "account_activity/all/webhooks", + "account_activity/subscriptions/count", + "account_activity/webhooks", + "account_activity/webhooks/:webhook_id/subscriptions/all", + "account_activity/webhooks/:webhook_id/subscriptions/all/list", + "application/rate_limit_status", + "blocks/ids", + "blocks/list", + "collections/entries", + "collections/list", + "collections/show", + "custom_profiles/:id", + "custom_profiles/list", + "direct_messages/events/list", + "direct_messages/events/show", + "direct_messages/welcome_messages/list", + "direct_messages/welcome_messages/rules/list", + "direct_messages/welcome_messages/rules/show", + "direct_messages/welcome_messages/show", + "favorites/list", + "feedback/events", + "feedback/show/:id", + "followers/ids", + "followers/list", + "friends/ids", + "friends/list", + "friendships/incoming", + "friendships/lookup", + "friendships/lookup", + "friendships/no_retweets/ids", + "friendships/outgoing", + "friendships/show", + "geo/id/:place_id", + "geo/reverse_geocode", + "geo/search", + "help/configuration", + "help/languages", + "help/privacy", + "help/tos", + "lists/list", + "lists/members", + "lists/members/show", + "lists/memberships", + "lists/ownerships", + "lists/show", + "lists/statuses", + "lists/subscribers", + "lists/subscribers/show", + "lists/subscriptions", + "mutes/users/ids", + "mutes/users/list", + "oauth/authenticate", + "oauth/authorize", + "saved_searches/list", + "saved_searches/show/:id", + "search/tweets", + "statuses/home_timeline", + "statuses/mentions_timeline", + "statuses/oembed", + "statuses/retweeters/ids", + "statuses/retweets/:id", + "statuses/retweets_of_me", + "statuses/sample", + "statuses/show/:id", + "statuses/user_timeline", + "trends/available", + "trends/closest", + "trends/place", + "users/profile_banner", + "users/search", + "users/show", + "users/suggestions", + "users/suggestions/:slug", + "users/suggestions/:slug/members" + ], + POST: [ + "account/remove_profile_banner", + "account/settings__post", + "account/update_profile", + "account/update_profile_banner", + "account/update_profile_image", + "account_activity/all/:env_name/subscriptions", + "account_activity/all/:env_name/webhooks", + "account_activity/webhooks", + "account_activity/webhooks/:webhook_id/subscriptions/all", + "blocks/create", + "blocks/destroy", + "collections/create", + "collections/destroy", + "collections/entries/add", + "collections/entries/curate", + "collections/entries/move", + "collections/entries/remove", + "collections/update", + "custom_profiles/new", + "direct_messages/events/new", + "direct_messages/indicate_typing", + "direct_messages/mark_read", + "direct_messages/welcome_messages/new", + "direct_messages/welcome_messages/rules/new", + "favorites/create", + "favorites/destroy", + "feedback/create", + "friendships/create", + "friendships/destroy", + "friendships/update", + "lists/create", + "lists/destroy", + "lists/members/create", + "lists/members/create_all", + "lists/members/destroy", + "lists/members/destroy_all", + "lists/subscribers/create", + "lists/subscribers/destroy", + "lists/update", + "media/metadata/create", + "media/upload", + "mutes/users/create", + "mutes/users/destroy", + "oauth/access_token", + "oauth/request_token", + "oauth2/invalidate_token", + "oauth2/token", + "saved_searches/create", + "saved_searches/destroy/:id", + "statuses/destroy/:id", + "statuses/filter", + "statuses/lookup", + "statuses/retweet/:id", + "statuses/unretweet/:id", + "statuses/update", + "users/lookup", + "users/report_spam" + ] + }; + return httpmethods; + } + + /** + * Promise helpers + */ + + /** + * Get a deferred object + */ + _getDfd() { + if (typeof window !== "undefined") { + if (typeof window.jQuery !== "undefined" && window.jQuery.Deferred) { + return window.jQuery.Deferred(); + } + if (typeof window.Q !== "undefined" && window.Q.defer) { + return window.Q.defer(); + } + if (typeof window.RSVP !== "undefined" && window.RSVP.defer) { + return window.RSVP.defer(); + } + if (typeof window.when !== "undefined" && window.when.defer) { + return window.when.defer(); + } + } + if (typeof require !== "undefined") { + let promise_class = false; + try { + promise_class = require("jquery"); + } catch (e) { } + if (promise_class) { + return promise_class.Deferred(); + } + try { + promise_class = require("q"); + } catch (e) { } + if (!promise_class) { + try { + promise_class = require("rsvp"); + } catch (e) { } + } + if (!promise_class) { + try { + promise_class = require("when"); + } catch (e) { } + } + if (promise_class) { + try { + return promise_class.defer(); + } catch (e) { } + } + } + return false; + } + + /** + * Get a promise from the dfd object + */ + _getPromise(dfd) { + if (typeof dfd.promise === "function") { + return dfd.promise(); + } + return dfd.promise; // object + } + + /** + * __call() helpers + */ + + /** + * Parse given params, detect query-style params + * + * @param array|string params Parameters to parse + * + * @return array apiparams + */ + _parseApiParams(params) { + let apiparams = {}; + if (typeof params === "object") { + apiparams = params; + } else { + this._parse_str(params, apiparams); //TODO + } + + return apiparams; + } + + /** + * Replace null and boolean parameters with their string representations + * + * @param array apiparams Parameter array to replace in + * + * @return array apiparams + */ + _stringifyNullBoolParams(apiparams) { + for (let key in apiparams) { + if (!apiparams.hasOwnProperty(key)) { + continue; + } + let value = apiparams[key]; + if (value === null) { + apiparams[key] = "null"; + } else if (value === true || value === false) { + apiparams[key] = value ? "true" : "false"; + } + } + + return apiparams; + } + + /** + * API method mapping: Replaces _ with / character + * + * @param string fn Function called + * + * @return string API method to call + */ + _mapFnInsertSlashes(fn) { + return fn.split("_").join("/"); + } + + /** + * API method mapping: Restore _ character in named parameters + * + * @param string method API method to call + * + * @return string API method with restored underscores + */ + _mapFnRestoreParamUnderscores(method) { + const url_parameters_with_underscore = ["screen_name", "place_id"]; + let i, param, replacement_was; + for (i = 0; i < url_parameters_with_underscore.length; i++) { + param = url_parameters_with_underscore[i].toUpperCase(); + replacement_was = param.split("_").join("/"); + method = method.split(replacement_was).join(param); + } + + return method; + } + + + /** + * Maps called PHP magic method name to Twitter API method + * + * @param string $fn Function called + * @param array $apiparams byref API parameters + * + * @return string[] (string method, string method_template) + */ + _mapFnToApiMethod(fn, apiparams) { + let method = "", + param, i, j; + + // replace _ by / + method = this._mapFnInsertSlashes(fn); + + // undo replacement for URL parameters + method = this._mapFnRestoreParamUnderscores(method); + + // replace AA by URL parameters + let method_template = method; + const match = method.match(/[A-Z_]{2,}/); + if (match) { + for (i = 0; i < match.length; i++) { + param = match[i]; + let param_l = param.toLowerCase(); + method_template = method_template.split(param).join(":" + param_l); + if (typeof apiparams[param_l] === "undefined") { + for (j = 0; j < 26; j++) { + method_template = method_template.split(String.fromCharCode(65 + j)).join("_" + String.fromCharCode(97 + j)); + } + throw `To call the templated method "${method_template}", specify the parameter value for "${param_l}".`; + } + method = method.split(param).join(apiparams[param_l]); + delete apiparams[param_l]; + } + } + + // replace A-Z by _a-z + for (i = 0; i < 26; i++) { + method = method.split(String.fromCharCode(65 + i)).join("_" + String.fromCharCode(97 + i)); + method_template = method_template.split(String.fromCharCode(65 + i)).join("_" + String.fromCharCode(97 + i)); + } + + return [method, method_template]; + } + + + /** + * Detects HTTP method to use for API call + * + * @param string method The API method to call + * @param array params The parameters to send along + * + * @return string The HTTP method that should be used + */ + _detectMethod(method, params) { + if (typeof params.httpmethod !== "undefined") { + let httpmethod = params.httpmethod; + delete params.httpmethod; + return httpmethod; + } + + // multi-HTTP method endpoints + switch (method) { + case "account/settings": + case "account/login_verification_enrollment": + case "account/login_verification_request": + method = Object.keys(params).length ? `${method}__post` : method; + break; + } + + const apimethods = this.getApiMethods(); + for (let httpmethod in apimethods) { + if (apimethods.hasOwnProperty(httpmethod) + && apimethods[httpmethod].indexOf(method) > -1 + ) { + return httpmethod; + } + } + throw `Can't find HTTP method to use for "${method}".`; + } + + /** + * Detects if API call should use multipart/form-data + * + * @param string method The API method to call + * + * @return bool Whether the method should be sent as multipart + */ + _detectMultipart(method) { + const multiparts = [ + // Tweets + "media/upload", + + // Users + "account/update_profile_image", + "account/update_profile_banner" + ]; + return multiparts.indexOf(method) > -1; + } + + /** + * Signature helper + * + * @param string httpmethod Usually either 'GET' or 'POST' or 'DELETE' + * @param string method The API method to call + * @param array base_params The signature base parameters + * + * @return string signature + */ + _getSignature(httpmethod, method, keys, base_params) { + // convert params to string + let base_string = "", key, value; + for (let i = 0; i < keys.length; i++) { + key = keys[i]; + value = base_params[key]; + base_string += `${key}=${this._url(value)}&`; + } + base_string = base_string.substring(0, base_string.length - 1); + return this._sha1(`${httpmethod}&${this._url(method)}&${this._url(base_string)}`); + } + + /** + * Generates the UNIX timestamp + */ + _time() { + return Math.round(new Date().getTime() / 1000); + } + + /** + * Generates an OAuth signature + * + * @param string httpmethod Usually either 'GET' or 'POST' or 'DELETE' + * @param string method The API method to call + * @param array optional params The API call parameters, associative + * + * @return string Authorization HTTP header + */ + _sign(httpmethod, method, params = {}) { + if (this._oauth_consumer_key === null) { + throw "To generate a signature, the consumer key must be set."; + } + const sign_params = { + consumer_key: this._oauth_consumer_key, + version: "1.0", + timestamp: this._time(), + nonce: this._nonce(), + signature_method: "HMAC-SHA1" + }; + let sign_base_params = {}; + for (var key in sign_params) { + if (!sign_params.hasOwnProperty(key)) { + continue; + } + let value = sign_params[key]; + sign_base_params[`oauth_${key}`] = this._url(value); + } + if (this._oauth_token !== null) { + sign_base_params.oauth_token = this._url(this._oauth_token); + } + const oauth_params = this._clone(sign_base_params); + for (key in params) { + if (!params.hasOwnProperty(key)) { + continue; + } + sign_base_params[key] = params[key]; + } + let keys = this._ksort(sign_base_params); + + const signature = this._getSignature(httpmethod, method, keys, sign_base_params); + + params = oauth_params; + params.oauth_signature = signature; + keys = this._ksort(params); + let authorization = "OAuth "; + for (let i = 0; i < keys.length; i++) { + key = keys[i]; + authorization += `${key}="${this._url(params[key])}", `; + } + return authorization.substring(0, authorization.length - 2); + } + + /** + * Build multipart request from upload params + * + * @param string method The API method to call + * @param array params The parameters to send along + * + * @return null|string The built multipart request body + */ + _buildMultipart(method, params) { + // well, files will only work in multipart methods + if (!this._detectMultipart(method)) { + return; + } + + // only check specific parameters + const possible_methods = [ + // Tweets + "media/upload", + // Accounts + "account/update_profile_image", + "account/update_profile_banner" + ]; + let possible_files = { + // Tweets + "media/upload": "media", + // Accounts + "account/update_profile_image": "image", + "account/update_profile_banner": "banner" + }; + // method might have files? + if (possible_methods.indexOf(method) === -1) { + return; + } + + // check for filenames + possible_files = possible_files[method].split(" "); + + const multipart_border = `--------------------${this._nonce()}`; + let multipart_request = ""; + for (let key in params) { + if (!params.hasOwnProperty(key)) { + continue; + } + multipart_request += + `--${multipart_border}\r\nContent-Disposition: form-data; name="${key}"`; + if (possible_files.indexOf(key) === -1) { + multipart_request += "\r\nContent-Transfer-Encoding: base64"; + } + multipart_request += `\r\n\r\n${params[key]}\r\n`; + } + multipart_request += `--${multipart_border}--`; + return multipart_request; + } + + /** + * Detects if API call should use media endpoint + * + * @param string method The API method to call + * + * @return bool Whether the method is defined in media API + */ + _detectMedia(method) { + const medias = [ + "media/metadata/create", + "media/upload" + ]; + return medias.indexOf(method) > -1; + } + + /** + * Detects if API call should use JSON body + * + * @param string method The API method to call + * + * @return bool Whether the method is defined as accepting JSON body + */ + _detectJsonBody(method) { + const json_bodies = [ + "collections/entries/curate", + "custom_profiles/new", + "direct_messages/events/new", + "direct_messages/indicate_typing", + "direct_messages/mark_read", + "direct_messages/welcome_messages/new", + "direct_messages/welcome_messages/rules/new", + "direct_messages/welcome_messages/update", + "media/metadata/create" + ]; + return json_bodies.indexOf(method) > -1; + } + + /** + * Builds the complete API endpoint url + * + * @param string method The API method to call + * + * @return string The URL to send the request to + */ + _getEndpoint(method) { + let url; + if (method.substring(0, 5) === "oauth") { + url = this._endpoint_oauth + method; + } else if (this._detectMedia(method)) { + url = this._endpoint_media + method + ".json"; + } else if (method === "statuses/oembed") { + url = this._endpoint_publish + "oembed"; + } else { + url = this._endpoint + method + ".json"; + } + return url; + } + + /** + * Parses the API reply to encode it in the set return_format + * + * @param string reply The actual reply, JSON-encoded or URL-encoded + * + * @return array|object The parsed reply + */ + _parseApiReply(reply) { + if (typeof reply !== "string" || reply === "") { + return {}; + } + if (reply === "[]") { + return []; + } + let parsed; + try { + parsed = JSON.parse(reply); + } catch (e) { + parsed = {}; + // assume query format + let elements = reply.split("&"); + for (let i = 0; i < elements.length; i++) { + let element = elements[i].split("=", 2); + if (element.length > 1) { + parsed[element[0]] = decodeURIComponent(element[1]); + } else { + parsed[element[0]] = null; + } + } + } + return parsed; + } + + + /** + * Uncommon API methods + */ + + /** + * Gets the OAuth authenticate URL for the current request token + * + * @return object Promise + */ + oauth_authenticate(params = {}, callback = undefined, type = "authenticate") { + const dfd = this._getDfd(); + if (typeof params.force_login === "undefined") { + params.force_login = null; + } + if (typeof params.screen_name === "undefined") { + params.screen_name = null; + } + if (["authenticate", "authorize"].indexOf(type) === -1) { + type = "authenticate"; + } + if (this._oauth_token === null) { + const error = `To get the ${type} URL, the OAuth token must be set.`; + if (dfd) { + dfd.reject({ error }); + return this._getPromise(dfd); + } + throw error; + } + let url = `${this._endpoint_oauth}oauth/${type}?oauth_token=${this._url(this._oauth_token)}`; + if (params.force_login === true) { + url += "&force_login=1"; + } + if (params.screen_name !== null) { + url += `&screen_name=${params.screen_name}`; + } + if (typeof callback === "function") { + callback(url); + } + if (dfd) { + dfd.resolve({ reply: url }); + return this._getPromise(dfd); + } + // no promises + return true; + } + + /** + * Gets the OAuth authorize URL for the current request token + * + * @return string The OAuth authorize URL + */ + oauth_authorize(params, callback) { + return this.oauth_authenticate(params, callback, "authorize"); + } + + /** + * Gets the OAuth bearer token + * + * @return object Promise + */ + oauth2_token(callback) { + const dfd = this._getDfd(); + + if (this._oauth_consumer_key === null) { + const error = "To obtain a bearer token, the consumer key must be set."; + if (dfd) { + dfd.reject({ error }); + return this._getPromise(dfd); + } + throw error; + } + + if (!dfd && typeof callback === "undefined") { + callback = () => {}; + } + + const post_fields = "grant_type=client_credentials"; + let url = this._endpoint_oauth + "oauth2/token"; + + if (this._use_proxy) { + url = url.replace( + this._endpoint_base, + this._endpoint_proxy + ); + } + + const xml = this._getXmlRequestObject(); + if (xml === null) { + return; + } + xml.open("POST", url, true); + xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xml.setRequestHeader( + `${this._use_proxy ? "X-" : ""}Authorization`, + "Basic " + this._base64_encode(`${this._oauth_consumer_key}:${this._oauth_consumer_secret}`) + ); + + xml.onreadystatechange = () => { + if (xml.readyState >= 4) { + let httpstatus = 12027; + try { + httpstatus = xml.status; + } catch (e) { } + let response = ""; + try { + response = xml.responseText; + } catch (e) { } + let reply = this._parseApiReply(response); + reply.httpstatus = httpstatus; + if (httpstatus === 200) { + this.setBearerToken(reply.access_token); + } + if (typeof callback === "function") { + callback(reply); + } + if (dfd) { + dfd.resolve({ reply }); + } + } + }; + // function called when an error occurs, including a timeout + xml.onerror = e => { + if (typeof callback === "function") { + callback(null, e); + } + if (dfd) { + dfd.reject(e); + } + }; + xml.timeout = 30000; // in milliseconds + + xml.send(post_fields); + if (dfd) { + return this._getPromise(dfd); + } + } + + /** + * Calls the API using cURL + * + * @param string httpmethod The HTTP method to use for making the request + * @param string method The API method to call + * @param array optional params The parameters to send along + * @param bool optional multipart Whether to use multipart/form-data + * @param bool optional app_only_auth Whether to use app-only bearer authentication + * @param function callback The function to call with the API call result + * + * @return mixed The API reply, encoded in the set return_format + */ + _callApi( + httpmethod, + method, + params = {}, + multipart = false, + app_only_auth = false, + callback = () => {} + ) { + const dfd = this._getDfd(); + + let url = this._getEndpoint(method), + authorization = null; + + const xml = this._getXmlRequestObject(); + if (xml === null) { + return; + } + let post_fields; + + if (httpmethod === "GET") { + let url_with_params = url; + if (JSON.stringify(params) !== "{}") { + url_with_params += "?" + this._http_build_query(params); + } + if (!app_only_auth) { + authorization = this._sign(httpmethod, url, params); + } + + if (this._use_proxy) { + url_with_params = url_with_params.replace( + this._endpoint_base, + this._endpoint_proxy + ).replace( + this._endpoint_base_media, + this._endpoint_proxy + ); + } + xml.open(httpmethod, url_with_params, true); + } else { + if (multipart) { + if (!app_only_auth) { + authorization = this._sign(httpmethod, url, {}); + } + params = this._buildMultipart(method, params); + } else if (this._detectJsonBody(method)) { + authorization = this._sign(httpmethod, url, {}); + params = JSON.stringify(params); + } else { + if (!app_only_auth) { + authorization = this._sign(httpmethod, url, params); + } + params = this._http_build_query(params); + } + post_fields = params; + if (this._use_proxy || multipart) { // force proxy for multipart base64 + url = url.replace( + this._endpoint_base, + this._endpoint_proxy + ).replace( + this._endpoint_base_media, + this._endpoint_proxy + ); + } + xml.open(httpmethod, url, true); + if (multipart) { + xml.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + + post_fields.split("\r\n")[0].substring(2)); + } else if (this._detectJsonBody(method)) { + xml.setRequestHeader("Content-Type", "application/json"); + } else { + xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + } + } + if (app_only_auth) { + if (this._oauth_consumer_key === null + && this._oauth_bearer_token === null + ) { + const error = "To make an app-only auth API request, consumer key or bearer token must be set."; + if (dfd) { + dfd.reject({ error }); + return this._getPromise(dfd); + } + throw error; + } + // automatically fetch bearer token, if necessary + if (this._oauth_bearer_token === null) { + if (dfd) { + return this.oauth2_token().then(() => { + return this._callApi(httpmethod, method, params, multipart, app_only_auth, callback); + }); + } + this.oauth2_token(() => { + this._callApi(httpmethod, method, params, multipart, app_only_auth, callback); + }); + return; + } + authorization = "Bearer " + this._oauth_bearer_token; + } + if (authorization !== null) { + xml.setRequestHeader(`${this._use_proxy ? "X-" : ""}Authorization`, authorization); + } + xml.onreadystatechange = () => { + if (xml.readyState >= 4) { + let httpstatus = 12027; + try { + httpstatus = xml.status; + } catch (e) { } + let response = ""; + try { + response = xml.responseText; + } catch (e) { } + let reply = this._parseApiReply(response); + reply.httpstatus = httpstatus; + let rate = null; + if (typeof xml.getResponseHeader !== "undefined" + && xml.getResponseHeader("x-rate-limit-limit") !== "" + ) { + rate = { + limit: xml.getResponseHeader("x-rate-limit-limit"), + remaining: xml.getResponseHeader("x-rate-limit-remaining"), + reset: xml.getResponseHeader("x-rate-limit-reset") + }; + } + if (typeof callback === "function") { + callback(reply, rate); + } + if (dfd) { + dfd.resolve({ reply, rate }); + } + } + }; + // function called when an error occurs, including a timeout + xml.onerror = e => { + if (typeof callback === "function") { + callback(null, null, e); + } + if (dfd) { + dfd.reject(e); + } + }; + xml.timeout = 30000; // in milliseconds + + xml.send(httpmethod === "GET" ? null : post_fields); + if (dfd) { + return this._getPromise(dfd); + } + return true; + } + + /** + * Main API handler working on any requests you issue + * + * @param string fn The member function you called + * @param array params The parameters you sent along + * @param function callback The callback to call with the reply + * @param bool app_only_auth Whether to use app-only auth + * + * @return object Promise + */ + __call(fn, params = {}, callback, app_only_auth = false) { + if (typeof callback !== "function" && typeof params === "function") { + callback = params; + params = {}; + if (typeof callback === "boolean") { + app_only_auth = callback; + } + } else if (typeof callback === "undefined") { + callback = () => {}; + } + switch (fn) { + case "oauth_authenticate": + case "oauth_authorize": + return this[fn](params, callback); + + case "oauth2_token": + return this[fn](callback); + } + + // parse parameters + let apiparams = this._parseApiParams(params); + + // stringify null and boolean parameters + apiparams = this._stringifyNullBoolParams(apiparams); + + // reset token when requesting a new token (causes 401 for signature error on 2nd+ requests) + if (fn === "oauth_requestToken") { + this.setToken(null, null); + } + + // map function name to API method + const [method, method_template] = this._mapFnToApiMethod(fn, apiparams), + httpmethod = this._detectMethod(method_template, apiparams), + multipart = this._detectMultipart(method_template); + + return this._callApi( + httpmethod, + method, + apiparams, + multipart, + app_only_auth, + callback + ); + } + }; + + if (typeof module === "object" + && module + && typeof module.exports === "object" + ) { + // Expose codebird as module.exports in loaders that implement the Node + // module pattern (including browserify). Do not create the global, since + // the user will be storing it themselves locally, and globals are frowned + // upon in the Node module world. + module.exports = Codebird; + } else { + // Otherwise expose codebird to the global object as usual + if (typeof window === "object" + && window) { + window.Codebird = Codebird; + } + + // Register as a named AMD module, since codebird can be concatenated with other + // files that may use define, but not via a proper concatenation script that + // understands anonymous AMD modules. A named AMD is safest and most robust + // way to register. Lowercase codebird is used because AMD module names are + // derived from file names, and codebird is normally delivered in a lowercase + // file name. Do this after creating the global so that if an AMD module wants + // to call noConflict to hide this version of codebird, it will work. + if (typeof define === "function" && define.amd) { + define("codebird", [], () => Codebird); + } + } + +})(); diff --git a/codebird.js b/codebird.js index baeaddd..ce4b7d9 100644 --- a/codebird.js +++ b/codebird.js @@ -1,141 +1,117 @@ +"use strict"; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + /** * A Twitter library in JavaScript * * @package codebird - * @version 2.6.0 - * @author Jublo Solutions - * @copyright 2010-2015 Jublo Solutions + * @version 3.0.0-dev + * @author Jublo Limited + * @copyright 2010-2018 Jublo Limited * @license http://opensource.org/licenses/GPL-3.0 GNU Public License 3.0 * @link https://github.com/jublonet/codebird-php */ -/* jshint curly: true, - eqeqeq: true, - latedef: true, - quotmark: double, - undef: true, - unused: true, - trailing: true, - laxbreak: true */ /* global window, - document, - navigator, - console, - Ti, - ActiveXObject, - module, - define, - require */ -(function (undefined) { -"use strict"; - -/** - * Array.indexOf polyfill - */ -if (! Array.prototype.indexOf) { - Array.prototype.indexOf = function (obj, start) { - for (var i = (start || 0); i < this.length; i++) { - if (this[i] === obj) { - return i; - } - } - return -1; - }; -} - -/** - * A Twitter library in JavaScript - * - * @package codebird - * @subpackage codebird-js - */ -/* jshint -W098 */ -var Codebird = function () { -/* jshint +W098 */ - - /** - * The OAuth consumer key of your registered app - */ - var _oauth_consumer_key = null; - - /** - * The corresponding consumer secret - */ - var _oauth_consumer_secret = null; - - /** - * The app-only bearer token. Used to authorize app-only requests - */ - var _oauth_bearer_token = null; - - /** - * The API endpoint base to use - */ - var _endpoint_base = "https://api.twitter.com/"; - - /** - * The media API endpoint base to use - */ - var _endpoint_base_media = "https://upload.twitter.com/"; - - /** - * The API endpoint to use - */ - var _endpoint = _endpoint_base + "1.1/"; - - /** - * The media API endpoint to use - */ - var _endpoint_media = _endpoint_base_media + "1.1/"; - - /** - * The API endpoint base to use - */ - var _endpoint_oauth = _endpoint_base; - - /** - * API proxy endpoint - */ - var _endpoint_proxy = "https://api.jublo.net/codebird/"; - - /** - * The API endpoint to use for old requests - */ - var _endpoint_old = _endpoint_base + "1/"; - - /** - * Use JSONP for GET requests in IE7-9 - */ - var _use_jsonp = (typeof navigator !== "undefined" - && typeof navigator.userAgent !== "undefined" - && (navigator.userAgent.indexOf("Trident/4") > -1 - || navigator.userAgent.indexOf("Trident/5") > -1 - || navigator.userAgent.indexOf("MSIE 7.0") > -1 - ) - ); - - /** - * Whether to access the API via a proxy that is allowed by CORS - * Assume that CORS is only necessary in browsers - */ - var _use_proxy = (typeof navigator !== "undefined" - && typeof navigator.userAgent !== "undefined" - ); - - /** - * The Request or access token. Used to sign requests - */ - var _oauth_token = null; - - /** - * The corresponding request or access token secret - */ - var _oauth_token_secret = null; - - /** - * The current Codebird version - */ - var _version = "2.6.0"; + document, + navigator, + Ti, + ActiveXObject, + module, + define, + require */ + +(function () { + /** + * A Twitter library in JavaScript + * + * @package codebird + * @subpackage codebird-js + */ + var Codebird = function () { + function Codebird() { + _classCallCheck(this, Codebird); + + /** + * The OAuth consumer key of your registered app + */ + this._oauth_consumer_key = null; + + /** + * The corresponding consumer secret + */ + this._oauth_consumer_secret = null; + + /** + * The app-only bearer token. Used to authorize app-only requests + */ + this._oauth_bearer_token = null; + + /** + * The API endpoint base to use + */ + this._endpoint_base = "https://api.twitter.com/"; + + /** + * The media API endpoint base to use + */ + this._endpoint_base_media = "https://upload.twitter.com/"; + + /** + * The API endpoint to use + */ + this._endpoint = this._endpoint_base + "1.1/"; + + /** + * The media API endpoint to use + */ + this._endpoint_media = this._endpoint_base_media + "1.1/"; + + /** + * The publish API endpoint to use + */ + this._endpoint_publish = "https://publish.twitter.com/"; + + /** + * The API endpoint base to use + */ + this._endpoint_oauth = this._endpoint_base; + + /** + * API proxy endpoint + */ + this._endpoint_proxy = "https://api.jublo.net/codebird/"; + + /** + * Whether to access the API via a proxy that is allowed by CORS + * Assume that CORS is only necessary in browsers + */ + this._use_proxy = typeof navigator !== "undefined" && typeof navigator.userAgent !== "undefined"; + + /** + * The Request or access token. Used to sign requests + */ + this._oauth_token = null; + + /** + * The corresponding request or access token secret + */ + this._oauth_token_secret = null; + + /** + * The current Codebird version + */ + this._version = "3.0.0-dev"; + + this.b64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + } /** * Sets the OAuth consumer key and secret (App key) @@ -145,1357 +121,1453 @@ var Codebird = function () { * * @return void */ - var setConsumerKey = function (key, secret) { - _oauth_consumer_key = key; - _oauth_consumer_secret = secret; - }; - /** - * Sets the OAuth2 app-only auth bearer token - * - * @param string token OAuth2 bearer token - * - * @return void - */ - var setBearerToken = function (token) { - _oauth_bearer_token = token; - }; - - /** - * Gets the current Codebird version - * - * @return string The version number - */ - var getVersion = function () { - return _version; - }; - - /** - * Sets the OAuth request or access token and secret (User key) - * - * @param string token OAuth request or access token - * @param string secret OAuth request or access token secret - * - * @return void - */ - var setToken = function (token, secret) { - _oauth_token = token; - _oauth_token_secret = secret; - }; - - /** - * Enables or disables CORS proxy - * - * @param bool use_proxy Whether to use CORS proxy or not - * - * @return void - */ - var setUseProxy = function (use_proxy) { - _use_proxy = !! use_proxy; - }; - /** - * Sets custom CORS proxy server - * - * @param string proxy Address of proxy server to use - * - * @return void - */ - var setProxy = function (proxy) { - // add trailing slash if missing - if (! proxy.match(/\/$/)) { - proxy += "/"; - } - _endpoint_proxy = proxy; - }; + _createClass(Codebird, [{ + key: "setConsumerKey", + value: function setConsumerKey(key, secret) { + this._oauth_consumer_key = key; + this._oauth_consumer_secret = secret; + } + + /** + * Sets the OAuth2 app-only auth bearer token + * + * @param string token OAuth2 bearer token + * + * @return void + */ + + }, { + key: "setBearerToken", + value: function setBearerToken(token) { + this._oauth_bearer_token = token; + } + + /** + * Gets the current Codebird version + * + * @return string The version number + */ + + }, { + key: "getVersion", + value: function getVersion() { + return this._version; + } + + /** + * Sets the OAuth request or access token and secret (User key) + * + * @param string token OAuth request or access token + * @param string secret OAuth request or access token secret + * + * @return void + */ + + }, { + key: "setToken", + value: function setToken(token, secret) { + this._oauth_token = token; + this._oauth_token_secret = secret; + } + + /** + * Forgets the OAuth request or access token and secret (User key) + * + * @return bool + */ + + }, { + key: "logout", + value: function logout() { + this._oauth_token = this._oauth_token_secret = null; - /** - * Parse URL-style parameters into object - * - * version: 1109.2015 - * discuss at: http://phpjs.org/functions/parse_str - * + original by: Cagri Ekin - * + improved by: Michael White (http://getsprink.com) - * + tweaked by: Jack - * + bugfixed by: Onno Marsman - * + reimplemented by: stag019 - * + bugfixed by: Brett Zamir (http://brett-zamir.me) - * + bugfixed by: stag019 - * - depends on: urldecode - * + input by: Dreamer - * + bugfixed by: Brett Zamir (http://brett-zamir.me) - * % note 1: When no argument is specified, will put variables in global scope. - * - * @param string str String to parse - * @param array array to load data into - * - * @return object - */ - var _parse_str = function (str, array) { - var glue1 = "=", - glue2 = "&", - array2 = String(str).replace(/^&?([\s\S]*?)&?$/, "$1").split(glue2), - i, j, chr, tmp, key, value, bracket, keys, evalStr, - fixStr = function (str) { - return decodeURIComponent(str).replace(/([\\"'])/g, "\\$1").replace(/\n/g, "\\n").replace(/\r/g, "\\r"); - }; - if (! array) { - array = this.window; - } - - for (i = 0; i < array2.length; i++) { - tmp = array2[i].split(glue1); - if (tmp.length < 2) { - tmp = [tmp, ""]; - } - key = fixStr(tmp[0]); - value = fixStr(tmp[1]); - while (key.charAt(0) === " ") { - key = key.substr(1); - } - if (key.indexOf("\0") !== -1) { - key = key.substr(0, key.indexOf("\0")); - } - if (key && key.charAt(0) !== "[") { - keys = []; - bracket = 0; - for (j = 0; j < key.length; j++) { - if (key.charAt(j) === "[" && !bracket) { - bracket = j + 1; - } else if (key.charAt(j) === "]") { - if (bracket) { - if (!keys.length) { - keys.push(key.substr(0, bracket - 1)); - } - keys.push(key.substr(bracket, j - bracket)); - bracket = 0; - if (key.charAt(j + 1) !== "[") { - break; - } - } - } - } - if (!keys.length) { - keys = [key]; - } - for (j = 0; j < keys[0].length; j++) { - chr = keys[0].charAt(j); - if (chr === " " || chr === "." || chr === "[") { - keys[0] = keys[0].substr(0, j) + "_" + keys[0].substr(j + 1); - } - if (chr === "[") { - break; - } - } - /* jshint -W061 */ - evalStr = "array"; - for (j = 0; j < keys.length; j++) { - key = keys[j]; - if ((key !== "" && key !== " ") || j === 0) { - key = "'" + key + "'"; - } else { - key = eval(evalStr + ".push([]);") - 1; - } - evalStr += "[" + key + "]"; - if (j !== keys.length - 1 && eval("typeof " + evalStr) === "undefined") { - eval(evalStr + " = [];"); - } - } - evalStr += " = '" + value + "';\n"; - eval(evalStr); - /* jshint +W061 */ - } - } - }; - - /** - * Get allowed API methods, sorted by GET or POST - * Watch out for multiple-method "account/settings"! - * - * @return array $apimethods - */ - var getApiMethods = function () { - var httpmethods = { - GET: [ - "account/settings", - "account/verify_credentials", - "application/rate_limit_status", - "blocks/ids", - "blocks/list", - "direct_messages", - "direct_messages/sent", - "direct_messages/show", - "favorites/list", - "followers/ids", - "followers/list", - "friends/ids", - "friends/list", - "friendships/incoming", - "friendships/lookup", - "friendships/lookup", - "friendships/no_retweets/ids", - "friendships/outgoing", - "friendships/show", - "geo/id/:place_id", - "geo/reverse_geocode", - "geo/search", - "geo/similar_places", - "help/configuration", - "help/languages", - "help/privacy", - "help/tos", - "lists/list", - "lists/members", - "lists/members/show", - "lists/memberships", - "lists/ownerships", - "lists/show", - "lists/statuses", - "lists/subscribers", - "lists/subscribers/show", - "lists/subscriptions", - "mutes/users/ids", - "mutes/users/list", - "oauth/authenticate", - "oauth/authorize", - "saved_searches/list", - "saved_searches/show/:id", - "search/tweets", - "statuses/home_timeline", - "statuses/mentions_timeline", - "statuses/oembed", - "statuses/retweeters/ids", - "statuses/retweets/:id", - "statuses/retweets_of_me", - "statuses/show/:id", - "statuses/user_timeline", - "trends/available", - "trends/closest", - "trends/place", - "users/contributees", - "users/contributors", - "users/profile_banner", - "users/search", - "users/show", - "users/suggestions", - "users/suggestions/:slug", - "users/suggestions/:slug/members", - - // Internal - "users/recommendations", - "account/push_destinations/device", - "activity/about_me", - "activity/by_friends", - "statuses/media_timeline", - "timeline/home", - "help/experiments", - "search/typeahead", - "search/universal", - "discover/universal", - "conversation/show", - "statuses/:id/activity/summary", - "account/login_verification_enrollment", - "account/login_verification_request", - "prompts/suggest", - - "beta/timelines/custom/list", - "beta/timelines/timeline", - "beta/timelines/custom/show" - ], - POST: [ - "account/remove_profile_banner", - "account/settings__post", - "account/update_delivery_device", - "account/update_profile", - "account/update_profile_background_image", - "account/update_profile_banner", - "account/update_profile_colors", - "account/update_profile_image", - "blocks/create", - "blocks/destroy", - "direct_messages/destroy", - "direct_messages/new", - "favorites/create", - "favorites/destroy", - "friendships/create", - "friendships/destroy", - "friendships/update", - "lists/create", - "lists/destroy", - "lists/members/create", - "lists/members/create_all", - "lists/members/destroy", - "lists/members/destroy_all", - "lists/subscribers/create", - "lists/subscribers/destroy", - "lists/update", - "media/upload", - "mutes/users/create", - "mutes/users/destroy", - "oauth/access_token", - "oauth/request_token", - "oauth2/invalidate_token", - "oauth2/token", - "saved_searches/create", - "saved_searches/destroy/:id", - "statuses/destroy/:id", - "statuses/lookup", - "statuses/retweet/:id", - "statuses/update", - "statuses/update_with_media", // deprecated, use media/upload - "users/lookup", - "users/report_spam", - - // Internal - "direct_messages/read", - "account/login_verification_enrollment__post", - "push_destinations/enable_login_verification", - "account/login_verification_request__post", - - "beta/timelines/custom/create", - "beta/timelines/custom/update", - "beta/timelines/custom/destroy", - "beta/timelines/custom/add", - "beta/timelines/custom/remove" - ] - }; - return httpmethods; - }; - - /** - * Main API handler working on any requests you issue - * - * @param string fn The member function you called - * @param array params The parameters you sent along - * @param function callback The callback to call with the reply - * @param bool app_only_auth Whether to use app-only auth - * - * @return mixed The API reply encoded in the set return_format - */ - - var __call = function (fn, params, callback, app_only_auth) { - if (typeof params === "undefined") { - params = {}; - } - if (typeof app_only_auth === "undefined") { - app_only_auth = false; - } - if (typeof callback !== "function" && typeof params === "function") { - callback = params; - params = {}; - if (typeof callback === "boolean") { - app_only_auth = callback; - } - } else if (typeof callback === "undefined") { - callback = function () {}; - } - switch (fn) { - case "oauth_authenticate": - case "oauth_authorize": - return this[fn](params, callback); - - case "oauth2_token": - return this[fn](callback); - } - // reset token when requesting a new token (causes 401 for signature error on 2nd+ requests) - if (fn === "oauth_requestToken") { - setToken(null, null); - } - // parse parameters - var apiparams = {}; - if (typeof params === "object") { - apiparams = params; - } else { - _parse_str(params, apiparams); //TODO - } - - // map function name to API method - var method = ""; - var param, i, j; - - // replace _ by / - var path = fn.split("_"); - for (i = 0; i < path.length; i++) { - if (i > 0) { - method += "/"; - } - method += path[i]; - } - - // undo replacement for URL parameters - var url_parameters_with_underscore = ["screen_name", "place_id"]; - for (i = 0; i < url_parameters_with_underscore.length; i++) { - param = url_parameters_with_underscore[i].toUpperCase(); - var replacement_was = param.split("_").join("/"); - method = method.split(replacement_was).join(param); - } - - // replace AA by URL parameters - var method_template = method; - var match = method.match(/[A-Z_]{2,}/); - if (match) { - for (i = 0; i < match.length; i++) { - param = match[i]; - var param_l = param.toLowerCase(); - method_template = method_template.split(param).join(":" + param_l); - if (typeof apiparams[param_l] === "undefined") { - for (j = 0; j < 26; j++) { - method_template = method_template.split(String.fromCharCode(65 + j)).join("_" + String.fromCharCode(97 + j)); - } - console.warn("To call the templated method \"" + method_template + "\", specify the parameter value for \"" + param_l + "\"."); - } - method = method.split(param).join(apiparams[param_l]); - delete apiparams[param_l]; - } - } - - // replace A-Z by _a-z - for (i = 0; i < 26; i++) { - method = method.split(String.fromCharCode(65 + i)).join("_" + String.fromCharCode(97 + i)); - method_template = method_template.split(String.fromCharCode(65 + i)).join("_" + String.fromCharCode(97 + i)); - } - - var httpmethod = _detectMethod(method_template, apiparams); - var multipart = _detectMultipart(method_template); - var internal = _detectInternal(method_template); - - return _callApi( - httpmethod, - method, - apiparams, - multipart, - app_only_auth, - internal, - callback - ); - }; - - /** - * Gets the OAuth authenticate URL for the current request token - * - * @return string The OAuth authenticate URL - */ - var oauth_authenticate = function (params, callback) { - if (typeof params.force_login === "undefined") { - params.force_login = null; - } - if (typeof params.screen_name === "undefined") { - params.screen_name = null; - } - if (_oauth_token === null) { - console.warn("To get the authenticate URL, the OAuth token must be set."); - } - var url = _endpoint_oauth + "oauth/authenticate?oauth_token=" + _url(_oauth_token); - if (params.force_login === true) { - url += "&force_login=1"; - if (params.screen_name !== null) { - url += "&screen_name=" + params.screen_name; - } - } - callback(url); - return true; - }; - - /** - * Gets the OAuth authorize URL for the current request token - * - * @return string The OAuth authorize URL - */ - var oauth_authorize = function (params, callback) { - if (typeof params.force_login === "undefined") { - params.force_login = null; - } - if (typeof params.screen_name === "undefined") { - params.screen_name = null; - } - if (_oauth_token === null) { - console.warn("To get the authorize URL, the OAuth token must be set."); - } - var url = _endpoint_oauth + "oauth/authorize?oauth_token=" + _url(_oauth_token); - if (params.force_login === true) { - url += "&force_login=1"; - if (params.screen_name !== null) { - url += "&screen_name=" + params.screen_name; - } - } - callback(url); return true; - }; - - /** - * Gets the OAuth bearer token - * - * @return string The OAuth bearer token - */ - - var oauth2_token = function (callback) { - if (_oauth_consumer_key === null) { - console.warn("To obtain a bearer token, the consumer key must be set."); - } - - if (typeof callback === "undefined") { - callback = function () {}; - } - - var post_fields = "grant_type=client_credentials"; - var url = _endpoint_oauth + "oauth2/token"; - - if (_use_proxy) { - url = url.replace( - _endpoint_base, - _endpoint_proxy - ); - } - - var xml = _getXmlRequestObject(); - if (xml === null) { - return; - } - xml.open("POST", url, true); - xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - xml.setRequestHeader( - (_use_proxy ? "X-" : "") + "Authorization", - "Basic " + _base64_encode(_oauth_consumer_key + ":" + _oauth_consumer_secret) - ); - - xml.onreadystatechange = function () { - if (xml.readyState >= 4) { - var httpstatus = 12027; - try { - httpstatus = xml.status; - } catch (e) {} - var response = ""; - try { - response = xml.responseText; - } catch (e) {} - var reply = _parseApiReply(response); - reply.httpstatus = httpstatus; - if (httpstatus === 200) { - setBearerToken(reply.access_token); - } - callback(reply); - } - }; - xml.send(post_fields); - - }; - - /** - * Signing helpers - */ - - /** - * URL-encodes the given data - * - * @param mixed data - * - * @return mixed The encoded data - */ - var _url = function (data) { - if ((/boolean|number|string/).test(typeof data)) { - return encodeURIComponent(data).replace(/!/g, "%21").replace(/'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A"); + } + + /** + * Enables or disables CORS proxy + * + * @param bool use_proxy Whether to use CORS proxy or not + * + * @return void + */ + + }, { + key: "setUseProxy", + value: function setUseProxy(use_proxy) { + this._use_proxy = !!use_proxy; + } + + /** + * Sets custom CORS proxy server + * + * @param string proxy Address of proxy server to use + * + * @return void + */ + + }, { + key: "setProxy", + value: function setProxy(proxy) { + // add trailing slash if missing + if (!proxy.match(/\/$/)) { + proxy += "/"; + } + this._endpoint_proxy = proxy; + } + + /** + * Signing helpers + */ + + /** + * URL-encodes the given data + * + * @param mixed data + * + * @return mixed The encoded data + */ + + }, { + key: "_url", + value: function _url(data) { + if (/boolean|number|string/.test(typeof data === "undefined" ? "undefined" : _typeof(data))) { + return encodeURIComponent(data).replace(/!/g, "%21").replace(/'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29").replace(/\*/g, "%2A"); } else { - return ""; - } - }; - - /** - * Gets the base64-encoded SHA1 hash for the given data - * - * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined - * in FIPS PUB 180-1 - * Based on version 2.1 Copyright Paul Johnston 2000 - 2002. - * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet - * Distributed under the BSD License - * See http://pajhome.org.uk/crypt/md5 for details. - * - * @param string data The data to calculate the hash from - * - * @return string The hash - */ - var _sha1 = function () { + return ""; + } + } + + /** + * Gets the base64-encoded SHA1 hash for the given data + * + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined + * in FIPS PUB 180-1 + * Based on version 2.1 Copyright Paul Johnston 2000 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + * + * @param string data The data to calculate the hash from + * + * @return string The hash + */ + + }, { + key: "_sha1", + value: function _sha1(e) { function n(e, b) { - e[b >> 5] |= 128 << 24 - b % 32; - e[(b + 64 >> 9 << 4) + 15] = b; - for (var c = new Array(80), a = 1732584193, d = -271733879, h = -1732584194, - k = 271733878, g = -1009589776, p = 0; p < e.length; p += 16) { - for (var o = a, q = d, r = h, s = k, t = g, f = 0; 80 > f; f++) { - var m; - - if (f < 16) { - m = e[p + f]; - } else { - m = c[f - 3] ^ c[f - 8] ^ c[f - 14] ^ c[f - 16]; - m = m << 1 | m >>> 31; - } - - c[f] = m; - m = l(l(a << 5 | a >>> 27, 20 > f ? d & h | ~d & k : 40 > f ? d ^ - h ^ k : 60 > f ? d & h | d & k | h & k : d ^ h ^ k), l( - l(g, c[f]), 20 > f ? 1518500249 : 40 > f ? 1859775393 : - 60 > f ? -1894007588 : -899497514)); - g = k; - k = h; - h = d << 30 | d >>> 2; - d = a; - a = m; - } - a = l(a, o); - d = l(d, q); - h = l(h, r); - k = l(k, s); - g = l(g, t); + e[b >> 5] |= 128 << 24 - b % 32; + e[(b + 64 >> 9 << 4) + 15] = b; + for (var c = new Array(80), a = 1732584193, d = -271733879, h = -1732584194, k = 271733878, g = -1009589776, p = 0; p < e.length; p += 16) { + for (var o = a, q = d, r = h, s = k, t = g, f = 0; 80 > f; f++) { + var m = void 0; + + if (f < 16) { + m = e[p + f]; + } else { + m = c[f - 3] ^ c[f - 8] ^ c[f - 14] ^ c[f - 16]; + m = m << 1 | m >>> 31; + } + + c[f] = m; + m = l(l(a << 5 | a >>> 27, 20 > f ? d & h | ~d & k : 40 > f ? d ^ h ^ k : 60 > f ? d & h | d & k | h & k : d ^ h ^ k), l(l(g, c[f]), 20 > f ? 1518500249 : 40 > f ? 1859775393 : 60 > f ? -1894007588 : -899497514)); + g = k; + k = h; + h = d << 30 | d >>> 2; + d = a; + a = m; } - return [a, d, h, k, g]; + a = l(a, o); + d = l(d, q); + h = l(h, r); + k = l(k, s); + g = l(g, t); + } + return [a, d, h, k, g]; } function l(e, b) { - var c = (e & 65535) + (b & 65535); - return (e >> 16) + (b >> 16) + (c >> 16) << 16 | c & 65535; + var c = (e & 65535) + (b & 65535); + return (e >> 16) + (b >> 16) + (c >> 16) << 16 | c & 65535; } function q(e) { - for (var b = [], c = (1 << g) - 1, a = 0; a < e.length * g; a += g) { - b[a >> 5] |= (e.charCodeAt(a / g) & c) << 24 - a % 32; - } - return b; + for (var b = [], c = (1 << g) - 1, a = 0; a < e.length * g; a += g) { + b[a >> 5] |= (e.charCodeAt(a / g) & c) << 24 - a % 32; + } + return b; } var g = 8; - return function (e) { - var b = _oauth_consumer_secret + "&" + (null !== _oauth_token_secret ? - _oauth_token_secret : ""); - if (_oauth_consumer_secret === null) { - console.warn("To generate a hash, the consumer secret must be set."); - } - var c = q(b); - if (c.length > 16) { - c = n(c, b.length * g); - } - b = new Array(16); - for (var a = new Array(16), d = 0; d < 16; d++) { - a[d] = c[d] ^ 909522486; - b[d] = c[d] ^ 1549556828; - } - c = n(a.concat(q(e)), 512 + e.length * g); - b = n(b.concat(c), 672); - c = ""; - for (a = 0; a < 4 * b.length; a += 3) { - for (d = (b[a >> 2] >> 8 * (3 - a % 4) & 255) << 16 | (b[a + 1 >> 2] >> - 8 * (3 - (a + 1) % 4) & 255) << 8 | b[a + 2 >> 2] >> 8 * (3 - - (a + 2) % 4) & 255, e = 0; 4 > e; e++) { - c = 8 * a + 6 * e > 32 * b.length ? c + "=" : c + - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" - .charAt(d >> 6 * (3 - e) & 63); - } - } - return c; - }; - }(); - /* - * Gets the base64 representation for the given data - * - * http://phpjs.org - * + original by: Tyler Akins (http://rumkin.com) - * + improved by: Bayron Guevara - * + improved by: Thunder.m - * + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - * + bugfixed by: Pellentesque Malesuada - * + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - * + improved by: Rafał Kukawski (http://kukawski.pl) - * - * @param string data The data to calculate the base64 representation from - * - * @return string The base64 representation - */ - var _base64_encode = function (a) { - var d, e, f, b, g = 0, + var b = this._oauth_consumer_secret + "&" + (null !== this._oauth_token_secret ? this._oauth_token_secret : ""); + if (this._oauth_consumer_secret === null) { + throw "To generate a hash, the consumer secret must be set."; + } + var c = q(b); + if (c.length > 16) { + c = n(c, b.length * g); + } + var bb = new Array(16); + for (var a = new Array(16), d = 0; d < 16; d++) { + a[d] = c[d] ^ 909522486; + bb[d] = c[d] ^ 1549556828; + } + c = n(a.concat(q(e)), 512 + e.length * g); + bb = n(bb.concat(c), 672); + b = ""; + for (g = 0; g < 4 * bb.length; g += 3) { + for (d = (bb[g >> 2] >> 8 * (3 - g % 4) & 255) << 16 | (bb[g + 1 >> 2] >> 8 * (3 - (g + 1) % 4) & 255) << 8 | bb[g + 2 >> 2] >> 8 * (3 - (g + 2) % 4) & 255, e = 0; 4 > e; e++) { + b = 8 * g + 6 * e > 32 * bb.length ? b + "=" : b + this.b64_alphabet.charAt(d >> 6 * (3 - e) & 63); + } + } + return b; + } + + /* + * Gets the base64 representation for the given data + * + * http://phpjs.org + * + original by: Tyler Akins (http://rumkin.com) + * + improved by: Bayron Guevara + * + improved by: Thunder.m + * + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + * + bugfixed by: Pellentesque Malesuada + * + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + * + improved by: Rafał Kukawski (http://kukawski.pl) + * + * @param string data The data to calculate the base64 representation from + * + * @return string The base64 representation + */ + + }, { + key: "_base64_encode", + value: function _base64_encode(a) { + var d = void 0, + e = void 0, + f = void 0, + b = void 0, + g = 0, h = 0, - i = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", + i = this.b64_alphabet, c = []; if (!a) { - return a; + return a; } do { - d = a.charCodeAt(g++); - e = a.charCodeAt(g++); - f = a.charCodeAt(g++); - b = d << 16 | e << 8 | f; - d = b >> 18 & 63; - e = b >> 12 & 63; - f = b >> 6 & 63; - b &= 63; - c[h++] = i.charAt(d) + i.charAt(e) + i.charAt(f) + i.charAt(b); + d = a.charCodeAt(g++); + e = a.charCodeAt(g++); + f = a.charCodeAt(g++); + b = d << 16 | e << 8 | f; + d = b >> 18 & 63; + e = b >> 12 & 63; + f = b >> 6 & 63; + b &= 63; + c[h++] = i.charAt(d) + i.charAt(e) + i.charAt(f) + i.charAt(b); } while (g < a.length); - c = c.join(""); + i = c.join(""); a = a.length % 3; - return (a ? c.slice(0, a - 3) : c) + "===".slice(a || 3); - }; - - /* - * Builds a HTTP query string from the given data - * - * http://phpjs.org - * + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - * + improved by: Legaev Andrey - * + improved by: Michael White (http://getsprink.com) - * + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) - * + improved by: Brett Zamir (http://brett-zamir.me) - * + revised by: stag019 - * + input by: Dreamer - * + bugfixed by: Brett Zamir (http://brett-zamir.me) - * + bugfixed by: MIO_KODUKI (http://mio-koduki.blogspot.com/) - * - * @param string data The data to concatenate - * - * @return string The HTTP query - */ - var _http_build_query = function (e, f, b) { + return (a ? i.slice(0, a - 3) : i) + "===".slice(a || 3); + } + + /* + * Builds a HTTP query string from the given data + * + * http://phpjs.org + * + original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + * + improved by: Legaev Andrey + * + improved by: Michael White (http://getsprink.com) + * + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + * + improved by: Brett Zamir (http://brett-zamir.me) + * + revised by: stag019 + * + input by: Dreamer + * + bugfixed by: Brett Zamir (http://brett-zamir.me) + * + bugfixed by: MIO_KODUKI (http://mio-koduki.blogspot.com/) + * + * @param string data The data to concatenate + * + * @return string The HTTP query + */ + + }, { + key: "_http_build_query", + value: function _http_build_query(e, f, b) { function g(c, a, d) { - var b, e = []; - if (a === true) { - a = "1"; - } else if (a === false) { - a = "0"; - } - if (null !== a) { - if (typeof a === "object") { - for (b in a) { - if (a[b] !== null) { - e.push(g(c + "[" + b + "]", a[b], d)); - } - } - return e.join(d); - } - if (typeof a !== "function") { - return _url(c) + "=" + _url(a); + var b = void 0, + e = []; + if (a === true) { + a = "1"; + } else if (a === false) { + a = "0"; + } + if (null !== a) { + if ((typeof a === "undefined" ? "undefined" : _typeof(a)) === "object") { + for (b in a) { + if (a.hasOwnProperty(b) && a[b] !== null) { + e.push(g.call(this, c + "[" + b + "]", a[b], d)); } - console.warn("There was an error processing for http_build_query()."); - } else { - return ""; + } + return e.join(d); + } + if (typeof a !== "function") { + return this._url(c) + "=" + this._url(a); } + throw "There was an error processing for http_build_query()."; + } else { + return ""; + } } - var d, c, h = []; - if (! b) { - b = "&"; + var d, + c, + h = []; + if (!b) { + b = "&"; } for (c in e) { - d = e[c]; - if (f && ! isNaN(c)) { - c = String(f) + c; - } - d = g(c, d, b); - if (d !== "") { - h.push(d); - } + if (!e.hasOwnProperty(c)) { + continue; + } + d = e[c]; + if (f && !isNaN(c)) { + c = String(f) + c; + } + d = g.call(this, c, d, b); + if (d !== "") { + h.push(d); + } } return h.join(b); - }; + } + + /** + * Generates a (hopefully) unique random string + * + * @param int optional length The length of the string to generate + * + * @return string The random string + */ + + }, { + key: "_nonce", + value: function _nonce() { + var length = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 8; - /** - * Generates a (hopefully) unique random string - * - * @param int optional length The length of the string to generate - * - * @return string The random string - */ - var _nonce = function (length) { - if (typeof length === "undefined") { - length = 8; - } if (length < 1) { - console.warn("Invalid nonce length."); + throw "Invalid nonce length."; } var nonce = ""; for (var i = 0; i < length; i++) { - var character = Math.floor(Math.random() * 61); - nonce += "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".substring(character, character + 1); + var character = Math.floor(Math.random() * 61); + nonce += this.b64_alphabet.substring(character, character + 1); } return nonce; - }; - - /** - * Sort array elements by key - * - * @param array input_arr The array to sort - * - * @return array The sorted keys - */ - var _ksort = function (input_arr) { - var keys = [], sorter, k; - - sorter = function (a, b) { - var a_float = parseFloat(a), - b_float = parseFloat(b), - a_numeric = a_float + "" === a, - b_numeric = b_float + "" === b; - if (a_numeric && b_numeric) { - return a_float > b_float ? 1 : a_float < b_float ? -1 : 0; - } else if (a_numeric && !b_numeric) { - return 1; - } else if (!a_numeric && b_numeric) { - return -1; - } - return a > b ? 1 : a < b ? -1 : 0; + } + + /** + * Sort array elements by key + * + * @param array input_arr The array to sort + * + * @return array The sorted keys + */ + + }, { + key: "_ksort", + value: function _ksort(input_arr) { + var keys = [], + sorter = void 0, + k = void 0; + + sorter = function sorter(a, b) { + var a_float = parseFloat(a), + b_float = parseFloat(b), + a_numeric = a_float + "" === a, + b_numeric = b_float + "" === b; + if (a_numeric && b_numeric) { + return a_float > b_float ? 1 : a_float < b_float ? -1 : 0; + } else if (a_numeric && !b_numeric) { + return 1; + } else if (!a_numeric && b_numeric) { + return -1; + } + return a > b ? 1 : a < b ? -1 : 0; }; // Make a list of key names for (k in input_arr) { - if (input_arr.hasOwnProperty(k)) { - keys.push(k); - } + if (input_arr.hasOwnProperty(k)) { + keys.push(k); + } } keys.sort(sorter); return keys; - }; - - /** - * Clone objects - * - * @param object obj The object to clone - * - * @return object clone The cloned object - */ - var _clone = function (obj) { + } + + /** + * Clone objects + * + * @param object obj The object to clone + * + * @return object clone The cloned object + */ + + }, { + key: "_clone", + value: function _clone(obj) { var clone = {}; for (var i in obj) { - if (typeof(obj[i]) === "object") { - clone[i] = _clone(obj[i]); - } else { - clone[i] = obj[i]; - } + if (_typeof(obj[i]) === "object") { + clone[i] = this._clone(obj[i]); + } else { + clone[i] = obj[i]; + } } return clone; - }; + } - /** - * Generates an OAuth signature - * - * @param string httpmethod Usually either 'GET' or 'POST' or 'DELETE' - * @param string method The API method to call - * @param array optional params The API call parameters, associative - * @param bool optional append_to_get Whether to append the OAuth params to GET - * - * @return string Authorization HTTP header - */ - var _sign = function (httpmethod, method, params, append_to_get) { - if (typeof params === "undefined") { - params = {}; - } - if (typeof append_to_get === "undefined") { - append_to_get = false; - } - if (_oauth_consumer_key === null) { - console.warn("To generate a signature, the consumer key must be set."); + /** + * Gets the XML HTTP Request object, trying to load it in various ways + * + * @return object The XMLHttpRequest object instance + */ + + }, { + key: "_getXmlRequestObject", + value: function _getXmlRequestObject() { + var xml = null; + // first, try the W3-standard object + if ((typeof window === "undefined" ? "undefined" : _typeof(window)) === "object" && window && typeof window.XMLHttpRequest !== "undefined") { + xml = new window.XMLHttpRequest(); + // then, try Titanium framework object + } else if ((typeof Ti === "undefined" ? "undefined" : _typeof(Ti)) === "object" && Ti && typeof Ti.Network.createHTTPClient !== "undefined") { + xml = Ti.Network.createHTTPClient(); + // are we in an old Internet Explorer? + } else if (typeof ActiveXObject !== "undefined") { + try { + xml = new ActiveXObject("Microsoft.XMLHTTP"); + } catch (e) { + throw "ActiveXObject object not defined."; + } + // now, consider RequireJS and/or Node.js objects + } else if (typeof require === "function") { + var XMLHttpRequest; + // look for xmlhttprequest module + try { + XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; + xml = new XMLHttpRequest(); + } catch (e1) { + // or maybe the user is using xhr2 + try { + XMLHttpRequest = require("xhr2"); + xml = new XMLHttpRequest(); + } catch (e2) { + throw "xhr2 object not defined, cancelling."; + } + } } - var sign_params = { - consumer_key: _oauth_consumer_key, - version: "1.0", - timestamp: Math.round(new Date().getTime() / 1000), - nonce: _nonce(), - signature_method: "HMAC-SHA1" + return xml; + } + + /** + * Parse URL-style parameters into object + * + * version: 1109.2015 + * discuss at: http://phpjs.org/functions/parse_str + * + original by: Cagri Ekin + * + improved by: Michael White (http://getsprink.com) + * + tweaked by: Jack + * + bugfixed by: Onno Marsman + * + reimplemented by: stag019 + * + bugfixed by: Brett Zamir (http://brett-zamir.me) + * + bugfixed by: stag019 + * - depends on: urldecode + * + input by: Dreamer + * + bugfixed by: Brett Zamir (http://brett-zamir.me) + * % note 1: When no argument is specified, will put variables in global scope. + * + * @param string str String to parse + * @param array array to load data into + * + * @return object + */ + + }, { + key: "_parse_str", + value: function _parse_str(str, array) { + var glue1 = "=", + glue2 = "&", + array2 = String(str).replace(/^&?([\s\S]*?)&?$/, "$1").split(glue2), + i, + j, + chr, + tmp, + key, + value, + bracket, + keys, + evalStr, + fixStr = function fixStr(str) { + return decodeURIComponent(str).replace(/([\\"'])/g, "\\$1").replace(/\n/g, "\\n").replace(/\r/g, "\\r"); }; - var sign_base_params = {}; - var value; - for (var key in sign_params) { - value = sign_params[key]; - sign_base_params["oauth_" + key] = _url(value); + if (!array) { + array = this.window; } - if (_oauth_token !== null) { - sign_base_params.oauth_token = _url(_oauth_token); - } - var oauth_params = _clone(sign_base_params); - for (key in params) { - value = params[key]; - sign_base_params[key] = value; - } - var keys = _ksort(sign_base_params); - var sign_base_string = ""; - for (var i = 0; i < keys.length; i++) { - key = keys[i]; - value = sign_base_params[key]; - sign_base_string += key + "=" + _url(value) + "&"; - } - sign_base_string = sign_base_string.substring(0, sign_base_string.length - 1); - var signature = _sha1(httpmethod + "&" + _url(method) + "&" + _url(sign_base_string)); - params = append_to_get ? sign_base_params : oauth_params; - params.oauth_signature = signature; - keys = _ksort(params); - var authorization = ""; - if (append_to_get) { - for(i = 0; i < keys.length; i++) { - key = keys[i]; - value = params[key]; - authorization += key + "=" + _url(value) + "&"; + for (i = 0; i < array2.length; i++) { + tmp = array2[i].split(glue1); + if (tmp.length < 2) { + tmp = [tmp, ""]; + } + key = fixStr(tmp[0]); + value = fixStr(tmp[1]); + while (key.charAt(0) === " ") { + key = key.substr(1); + } + if (key.indexOf("\0") > -1) { + key = key.substr(0, key.indexOf("\0")); + } + if (key && key.charAt(0) !== "[") { + keys = []; + bracket = 0; + for (j = 0; j < key.length; j++) { + if (key.charAt(j) === "[" && !bracket) { + bracket = j + 1; + } else if (key.charAt(j) === "]") { + if (bracket) { + if (!keys.length) { + keys.push(key.substr(0, bracket - 1)); + } + keys.push(key.substr(bracket, j - bracket)); + bracket = 0; + if (key.charAt(j + 1) !== "[") { + break; + } + } + } + } + if (!keys.length) { + keys = [key]; + } + for (j = 0; j < keys[0].length; j++) { + chr = keys[0].charAt(j); + if (chr === " " || chr === "." || chr === "[") { + keys[0] = keys[0].substr(0, j) + "_" + keys[0].substr(j + 1); + } + if (chr === "[") { + break; + } + } + evalStr = "array"; + for (j = 0; j < keys.length; j++) { + key = keys[j]; + if (key !== "" && key !== " " || j === 0) { + key = "'" + key + "'"; + } else { + key = eval(evalStr + ".push([]);") - 1; + } + evalStr += "[" + key + "]"; + if (j !== keys.length - 1 && eval("typeof " + evalStr) === "undefined") { + eval(evalStr + " = [];"); + } + } + evalStr += " = '" + value + "';\n"; + eval(evalStr); + } + } + } + + /** + * Get allowed API methods, sorted by GET or POST + * Watch out for multiple-method "account/settings"! + * + * @return array $apimethods + */ + + }, { + key: "getApiMethods", + value: function getApiMethods() { + var httpmethods = { + GET: ["account/settings", "account/verify_credentials", "account_activity/all/:env_name/subscriptions", "account_activity/all/:env_name/subscriptions/list", "account_activity/all/:env_name/webhooks", "account_activity/all/webhooks", "account_activity/subscriptions/count", "account_activity/webhooks", "account_activity/webhooks/:webhook_id/subscriptions/all", "account_activity/webhooks/:webhook_id/subscriptions/all/list", "application/rate_limit_status", "blocks/ids", "blocks/list", "collections/entries", "collections/list", "collections/show", "custom_profiles/:id", "custom_profiles/list", "direct_messages/events/list", "direct_messages/events/show", "direct_messages/welcome_messages/list", "direct_messages/welcome_messages/rules/list", "direct_messages/welcome_messages/rules/show", "direct_messages/welcome_messages/show", "favorites/list", "feedback/events", "feedback/show/:id", "followers/ids", "followers/list", "friends/ids", "friends/list", "friendships/incoming", "friendships/lookup", "friendships/lookup", "friendships/no_retweets/ids", "friendships/outgoing", "friendships/show", "geo/id/:place_id", "geo/reverse_geocode", "geo/search", "help/configuration", "help/languages", "help/privacy", "help/tos", "lists/list", "lists/members", "lists/members/show", "lists/memberships", "lists/ownerships", "lists/show", "lists/statuses", "lists/subscribers", "lists/subscribers/show", "lists/subscriptions", "mutes/users/ids", "mutes/users/list", "oauth/authenticate", "oauth/authorize", "saved_searches/list", "saved_searches/show/:id", "search/tweets", "statuses/home_timeline", "statuses/mentions_timeline", "statuses/oembed", "statuses/retweeters/ids", "statuses/retweets/:id", "statuses/retweets_of_me", "statuses/sample", "statuses/show/:id", "statuses/user_timeline", "trends/available", "trends/closest", "trends/place", "users/profile_banner", "users/search", "users/show", "users/suggestions", "users/suggestions/:slug", "users/suggestions/:slug/members"], + POST: ["account/remove_profile_banner", "account/settings__post", "account/update_profile", "account/update_profile_banner", "account/update_profile_image", "account_activity/all/:env_name/subscriptions", "account_activity/all/:env_name/webhooks", "account_activity/webhooks", "account_activity/webhooks/:webhook_id/subscriptions/all", "blocks/create", "blocks/destroy", "collections/create", "collections/destroy", "collections/entries/add", "collections/entries/curate", "collections/entries/move", "collections/entries/remove", "collections/update", "custom_profiles/new", "direct_messages/events/new", "direct_messages/indicate_typing", "direct_messages/mark_read", "direct_messages/welcome_messages/new", "direct_messages/welcome_messages/rules/new", "favorites/create", "favorites/destroy", "feedback/create", "friendships/create", "friendships/destroy", "friendships/update", "lists/create", "lists/destroy", "lists/members/create", "lists/members/create_all", "lists/members/destroy", "lists/members/destroy_all", "lists/subscribers/create", "lists/subscribers/destroy", "lists/update", "media/metadata/create", "media/upload", "mutes/users/create", "mutes/users/destroy", "oauth/access_token", "oauth/request_token", "oauth2/invalidate_token", "oauth2/token", "saved_searches/create", "saved_searches/destroy/:id", "statuses/destroy/:id", "statuses/filter", "statuses/lookup", "statuses/retweet/:id", "statuses/unretweet/:id", "statuses/update", "users/lookup", "users/report_spam"] + }; + return httpmethods; + } + + /** + * Promise helpers + */ + + /** + * Get a deferred object + */ + + }, { + key: "_getDfd", + value: function _getDfd() { + if (typeof window !== "undefined") { + if (typeof window.jQuery !== "undefined" && window.jQuery.Deferred) { + return window.jQuery.Deferred(); + } + if (typeof window.Q !== "undefined" && window.Q.defer) { + return window.Q.defer(); + } + if (typeof window.RSVP !== "undefined" && window.RSVP.defer) { + return window.RSVP.defer(); + } + if (typeof window.when !== "undefined" && window.when.defer) { + return window.when.defer(); + } + } + if (typeof require !== "undefined") { + var promise_class = false; + try { + promise_class = require("jquery"); + } catch (e) {} + if (promise_class) { + return promise_class.Deferred(); + } + try { + promise_class = require("q"); + } catch (e) {} + if (!promise_class) { + try { + promise_class = require("rsvp"); + } catch (e) {} + } + if (!promise_class) { + try { + promise_class = require("when"); + } catch (e) {} + } + if (promise_class) { + try { + return promise_class.defer(); + } catch (e) {} + } + } + return false; + } + + /** + * Get a promise from the dfd object + */ + + }, { + key: "_getPromise", + value: function _getPromise(dfd) { + if (typeof dfd.promise === "function") { + return dfd.promise(); + } + return dfd.promise; // object + } + + /** + * __call() helpers + */ + + /** + * Parse given params, detect query-style params + * + * @param array|string params Parameters to parse + * + * @return array apiparams + */ + + }, { + key: "_parseApiParams", + value: function _parseApiParams(params) { + var apiparams = {}; + if ((typeof params === "undefined" ? "undefined" : _typeof(params)) === "object") { + apiparams = params; + } else { + this._parse_str(params, apiparams); //TODO + } + + return apiparams; + } + + /** + * Replace null and boolean parameters with their string representations + * + * @param array apiparams Parameter array to replace in + * + * @return array apiparams + */ + + }, { + key: "_stringifyNullBoolParams", + value: function _stringifyNullBoolParams(apiparams) { + for (var key in apiparams) { + if (!apiparams.hasOwnProperty(key)) { + continue; + } + var value = apiparams[key]; + if (value === null) { + apiparams[key] = "null"; + } else if (value === true || value === false) { + apiparams[key] = value ? "true" : "false"; + } + } + + return apiparams; + } + + /** + * API method mapping: Replaces _ with / character + * + * @param string fn Function called + * + * @return string API method to call + */ + + }, { + key: "_mapFnInsertSlashes", + value: function _mapFnInsertSlashes(fn) { + return fn.split("_").join("/"); + } + + /** + * API method mapping: Restore _ character in named parameters + * + * @param string method API method to call + * + * @return string API method with restored underscores + */ + + }, { + key: "_mapFnRestoreParamUnderscores", + value: function _mapFnRestoreParamUnderscores(method) { + var url_parameters_with_underscore = ["screen_name", "place_id"]; + var i = void 0, + param = void 0, + replacement_was = void 0; + for (i = 0; i < url_parameters_with_underscore.length; i++) { + param = url_parameters_with_underscore[i].toUpperCase(); + replacement_was = param.split("_").join("/"); + method = method.split(replacement_was).join(param); + } + + return method; + } + + /** + * Maps called PHP magic method name to Twitter API method + * + * @param string $fn Function called + * @param array $apiparams byref API parameters + * + * @return string[] (string method, string method_template) + */ + + }, { + key: "_mapFnToApiMethod", + value: function _mapFnToApiMethod(fn, apiparams) { + var method = "", + param = void 0, + i = void 0, + j = void 0; + + // replace _ by / + method = this._mapFnInsertSlashes(fn); + + // undo replacement for URL parameters + method = this._mapFnRestoreParamUnderscores(method); + + // replace AA by URL parameters + var method_template = method; + var match = method.match(/[A-Z_]{2,}/); + if (match) { + for (i = 0; i < match.length; i++) { + param = match[i]; + var param_l = param.toLowerCase(); + method_template = method_template.split(param).join(":" + param_l); + if (typeof apiparams[param_l] === "undefined") { + for (j = 0; j < 26; j++) { + method_template = method_template.split(String.fromCharCode(65 + j)).join("_" + String.fromCharCode(97 + j)); + } + throw "To call the templated method \"" + method_template + "\", specify the parameter value for \"" + param_l + "\"."; } - return authorization.substring(0, authorization.length - 1); + method = method.split(param).join(apiparams[param_l]); + delete apiparams[param_l]; + } } - authorization = "OAuth "; - for (i = 0; i < keys.length; i++) { - key = keys[i]; - value = params[key]; - authorization += key + "=\"" + _url(value) + "\", "; + + // replace A-Z by _a-z + for (i = 0; i < 26; i++) { + method = method.split(String.fromCharCode(65 + i)).join("_" + String.fromCharCode(97 + i)); + method_template = method_template.split(String.fromCharCode(65 + i)).join("_" + String.fromCharCode(97 + i)); + } + + return [method, method_template]; + } + + /** + * Detects HTTP method to use for API call + * + * @param string method The API method to call + * @param array params The parameters to send along + * + * @return string The HTTP method that should be used + */ + + }, { + key: "_detectMethod", + value: function _detectMethod(method, params) { + if (typeof params.httpmethod !== "undefined") { + var httpmethod = params.httpmethod; + delete params.httpmethod; + return httpmethod; } - return authorization.substring(0, authorization.length - 2); - }; - /** - * Detects HTTP method to use for API call - * - * @param string method The API method to call - * @param array params The parameters to send along - * - * @return string The HTTP method that should be used - */ - var _detectMethod = function (method, params) { // multi-HTTP method endpoints switch (method) { - case "account/settings": - case "account/login_verification_enrollment": - case "account/login_verification_request": - method = params.length ? method + "__post" : method; + case "account/settings": + case "account/login_verification_enrollment": + case "account/login_verification_request": + method = Object.keys(params).length ? method + "__post" : method; break; } - var apimethods = getApiMethods(); - for (var httpmethod in apimethods) { - if (apimethods[httpmethod].indexOf(method) > -1) { - return httpmethod; - } + var apimethods = this.getApiMethods(); + for (var _httpmethod in apimethods) { + if (apimethods.hasOwnProperty(_httpmethod) && apimethods[_httpmethod].indexOf(method) > -1) { + return _httpmethod; + } } - console.warn("Can't find HTTP method to use for \"" + method + "\"."); - }; + throw "Can't find HTTP method to use for \"" + method + "\"."; + } - /** - * Detects if API call should use multipart/form-data - * - * @param string method The API method to call - * - * @return bool Whether the method should be sent as multipart - */ - var _detectMultipart = function (method) { + /** + * Detects if API call should use multipart/form-data + * + * @param string method The API method to call + * + * @return bool Whether the method should be sent as multipart + */ + + }, { + key: "_detectMultipart", + value: function _detectMultipart(method) { var multiparts = [ - // Tweets - "statuses/update_with_media", - - // Users - "account/update_profile_background_image", - "account/update_profile_image", - "account/update_profile_banner" - ]; + // Tweets + "media/upload", + + // Users + "account/update_profile_image", "account/update_profile_banner"]; return multiparts.indexOf(method) > -1; - }; + } + + /** + * Signature helper + * + * @param string httpmethod Usually either 'GET' or 'POST' or 'DELETE' + * @param string method The API method to call + * @param array base_params The signature base parameters + * + * @return string signature + */ + + }, { + key: "_getSignature", + value: function _getSignature(httpmethod, method, keys, base_params) { + // convert params to string + var base_string = "", + key = void 0, + value = void 0; + for (var i = 0; i < keys.length; i++) { + key = keys[i]; + value = base_params[key]; + base_string += key + "=" + this._url(value) + "&"; + } + base_string = base_string.substring(0, base_string.length - 1); + return this._sha1(httpmethod + "&" + this._url(method) + "&" + this._url(base_string)); + } + + /** + * Generates the UNIX timestamp + */ + + }, { + key: "_time", + value: function _time() { + return Math.round(new Date().getTime() / 1000); + } + + /** + * Generates an OAuth signature + * + * @param string httpmethod Usually either 'GET' or 'POST' or 'DELETE' + * @param string method The API method to call + * @param array optional params The API call parameters, associative + * + * @return string Authorization HTTP header + */ + + }, { + key: "_sign", + value: function _sign(httpmethod, method) { + var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + + if (this._oauth_consumer_key === null) { + throw "To generate a signature, the consumer key must be set."; + } + var sign_params = { + consumer_key: this._oauth_consumer_key, + version: "1.0", + timestamp: this._time(), + nonce: this._nonce(), + signature_method: "HMAC-SHA1" + }; + var sign_base_params = {}; + for (var key in sign_params) { + if (!sign_params.hasOwnProperty(key)) { + continue; + } + var value = sign_params[key]; + sign_base_params["oauth_" + key] = this._url(value); + } + if (this._oauth_token !== null) { + sign_base_params.oauth_token = this._url(this._oauth_token); + } + var oauth_params = this._clone(sign_base_params); + for (key in params) { + if (!params.hasOwnProperty(key)) { + continue; + } + sign_base_params[key] = params[key]; + } + var keys = this._ksort(sign_base_params); - /** - * Build multipart request from upload params - * - * @param string method The API method to call - * @param array params The parameters to send along - * - * @return null|string The built multipart request body - */ - var _buildMultipart = function (method, params) { + var signature = this._getSignature(httpmethod, method, keys, sign_base_params); + + params = oauth_params; + params.oauth_signature = signature; + keys = this._ksort(params); + var authorization = "OAuth "; + for (var i = 0; i < keys.length; i++) { + key = keys[i]; + authorization += key + "=\"" + this._url(params[key]) + "\", "; + } + return authorization.substring(0, authorization.length - 2); + } + + /** + * Build multipart request from upload params + * + * @param string method The API method to call + * @param array params The parameters to send along + * + * @return null|string The built multipart request body + */ + + }, { + key: "_buildMultipart", + value: function _buildMultipart(method, params) { // well, files will only work in multipart methods - if (! _detectMultipart(method)) { - return; + if (!this._detectMultipart(method)) { + return; } // only check specific parameters var possible_methods = [ - // Tweets - "statuses/update_with_media", - // Accounts - "account/update_profile_background_image", - "account/update_profile_image", - "account/update_profile_banner" - ]; + // Tweets + "media/upload", + // Accounts + "account/update_profile_image", "account/update_profile_banner"]; var possible_files = { - // Tweets - "statuses/update_with_media": "media[]", - // Accounts - "account/update_profile_background_image": "image", - "account/update_profile_image": "image", - "account/update_profile_banner": "banner" + // Tweets + "media/upload": "media", + // Accounts + "account/update_profile_image": "image", + "account/update_profile_banner": "banner" }; // method might have files? if (possible_methods.indexOf(method) === -1) { - return; + return; } // check for filenames possible_files = possible_files[method].split(" "); - var multipart_border = "--------------------" + _nonce(); + var multipart_border = "--------------------" + this._nonce(); var multipart_request = ""; for (var key in params) { - multipart_request += - "--" + multipart_border + "\r\n" - + "Content-Disposition: form-data; name=\"" + key + "\""; - if (possible_files.indexOf(key) > -1) { - multipart_request += - "\r\nContent-Transfer-Encoding: base64"; - } - multipart_request += - "\r\n\r\n" + params[key] + "\r\n"; + if (!params.hasOwnProperty(key)) { + continue; + } + multipart_request += "--" + multipart_border + "\r\nContent-Disposition: form-data; name=\"" + key + "\""; + if (possible_files.indexOf(key) === -1) { + multipart_request += "\r\nContent-Transfer-Encoding: base64"; + } + multipart_request += "\r\n\r\n" + params[key] + "\r\n"; } multipart_request += "--" + multipart_border + "--"; return multipart_request; - }; - - /** - * Detects if API call is internal - * - * @param string method The API method to call - * - * @return bool Whether the method is defined in internal API - */ - var _detectInternal = function (method) { - var internals = [ - "users/recommendations" - ]; - return internals.join(" ").indexOf(method) > -1; - }; - - /** - * Detects if API call should use media endpoint - * - * @param string method The API method to call - * - * @return bool Whether the method is defined in media API - */ - var _detectMedia = function (method) { - var medias = [ - "media/upload" - ]; - return medias.join(" ").indexOf(method) > -1; - }; - - /** - * Detects if API call should use old endpoint - * - * @param string method The API method to call - * - * @return bool Whether the method is defined in old API - */ - var _detectOld = function (method) { - var olds = [ - "account/push_destinations/device" - ]; - return olds.join(" ").indexOf(method) > -1; - }; - - /** - * Builds the complete API endpoint url - * - * @param string method The API method to call - * - * @return string The URL to send the request to - */ - var _getEndpoint = function (method) { - var url; + } + + /** + * Detects if API call should use media endpoint + * + * @param string method The API method to call + * + * @return bool Whether the method is defined in media API + */ + + }, { + key: "_detectMedia", + value: function _detectMedia(method) { + var medias = ["media/metadata/create", "media/upload"]; + return medias.indexOf(method) > -1; + } + + /** + * Detects if API call should use JSON body + * + * @param string method The API method to call + * + * @return bool Whether the method is defined as accepting JSON body + */ + + }, { + key: "_detectJsonBody", + value: function _detectJsonBody(method) { + var json_bodies = ["collections/entries/curate", "custom_profiles/new", "direct_messages/events/new", "direct_messages/indicate_typing", "direct_messages/mark_read", "direct_messages/welcome_messages/new", "direct_messages/welcome_messages/rules/new", "direct_messages/welcome_messages/update", "media/metadata/create"]; + return json_bodies.indexOf(method) > -1; + } + + /** + * Builds the complete API endpoint url + * + * @param string method The API method to call + * + * @return string The URL to send the request to + */ + + }, { + key: "_getEndpoint", + value: function _getEndpoint(method) { + var url = void 0; if (method.substring(0, 5) === "oauth") { - url = _endpoint_oauth + method; - } else if (_detectMedia(method)) { - url = _endpoint_media + method + ".json"; - } else if (_detectOld(method)) { - url = _endpoint_old + method + ".json"; + url = this._endpoint_oauth + method; + } else if (this._detectMedia(method)) { + url = this._endpoint_media + method + ".json"; + } else if (method === "statuses/oembed") { + url = this._endpoint_publish + "oembed"; } else { - url = _endpoint + method + ".json"; + url = this._endpoint + method + ".json"; } return url; - }; - - /** - * Gets the XML HTTP Request object, trying to load it in various ways - * - * @return object The XMLHttpRequest object instance - */ - var _getXmlRequestObject = function () { - var xml = null; - // first, try the W3-standard object - if (typeof window === "object" - && window - && typeof window.XMLHttpRequest !== "undefined" - ) { - xml = new window.XMLHttpRequest(); - // then, try Titanium framework object - } else if (typeof Ti === "object" - && Ti - && typeof Ti.Network.createHTTPClient !== "undefined" - ) { - xml = Ti.Network.createHTTPClient(); - // are we in an old Internet Explorer? - } else if (typeof ActiveXObject !== "undefined" - ) { - try { - xml = new ActiveXObject("Microsoft.XMLHTTP"); - } catch (e) { - console.error("ActiveXObject object not defined."); - } - // now, consider RequireJS and/or Node.js objects - } else if (typeof require === "function" - && require - ) { - // look for xmlhttprequest module - try { - var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; - xml = new XMLHttpRequest(); - } catch (e1) { - // or maybe the user is using xhr2 - try { - var XMLHttpRequest = require("xhr2"); - xml = new XMLHttpRequest(); - } catch (e2) { - console.error("xhr2 object not defined, cancelling."); - } + } + + /** + * Parses the API reply to encode it in the set return_format + * + * @param string reply The actual reply, JSON-encoded or URL-encoded + * + * @return array|object The parsed reply + */ + + }, { + key: "_parseApiReply", + value: function _parseApiReply(reply) { + if (typeof reply !== "string" || reply === "") { + return {}; + } + if (reply === "[]") { + return []; + } + var parsed = void 0; + try { + parsed = JSON.parse(reply); + } catch (e) { + parsed = {}; + // assume query format + var elements = reply.split("&"); + for (var i = 0; i < elements.length; i++) { + var element = elements[i].split("=", 2); + if (element.length > 1) { + parsed[element[0]] = decodeURIComponent(element[1]); + } else { + parsed[element[0]] = null; } + } } - return xml; - }; - - /** - * Calls the API using cURL - * - * @param string httpmethod The HTTP method to use for making the request - * @param string method The API method to call - * @param array optional params The parameters to send along - * @param bool optional multipart Whether to use multipart/form-data - * @param bool optional app_only_auth Whether to use app-only bearer authentication - * @param bool optional internal Whether to use internal call - * @param function callback The function to call with the API call result - * - * @return mixed The API reply, encoded in the set return_format - */ - - var _callApi = function (httpmethod, method, params, multipart, app_only_auth, internal, callback) { - if (typeof params === "undefined") { - params = {}; + return parsed; + } + + /** + * Uncommon API methods + */ + + /** + * Gets the OAuth authenticate URL for the current request token + * + * @return object Promise + */ + + }, { + key: "oauth_authenticate", + value: function oauth_authenticate() { + var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + var type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "authenticate"; + + var dfd = this._getDfd(); + if (typeof params.force_login === "undefined") { + params.force_login = null; + } + if (typeof params.screen_name === "undefined") { + params.screen_name = null; + } + if (["authenticate", "authorize"].indexOf(type) === -1) { + type = "authenticate"; + } + if (this._oauth_token === null) { + var error = "To get the " + type + " URL, the OAuth token must be set."; + if (dfd) { + dfd.reject({ error: error }); + return this._getPromise(dfd); + } + throw error; } - if (typeof multipart === "undefined") { - multipart = false; + var url = this._endpoint_oauth + "oauth/" + type + "?oauth_token=" + this._url(this._oauth_token); + if (params.force_login === true) { + url += "&force_login=1"; } - if (typeof app_only_auth === "undefined") { - app_only_auth = false; + if (params.screen_name !== null) { + url += "&screen_name=" + params.screen_name; } - if (typeof callback !== "function") { - callback = function () {}; + if (typeof callback === "function") { + callback(url); } - if (internal) { - params.adc = "phone"; - params.application_id = 333903271; + if (dfd) { + dfd.resolve({ reply: url }); + return this._getPromise(dfd); } + // no promises + return true; + } + + /** + * Gets the OAuth authorize URL for the current request token + * + * @return string The OAuth authorize URL + */ + + }, { + key: "oauth_authorize", + value: function oauth_authorize(params, callback) { + return this.oauth_authenticate(params, callback, "authorize"); + } - var url = _getEndpoint(method); - var authorization = null; + /** + * Gets the OAuth bearer token + * + * @return object Promise + */ + + }, { + key: "oauth2_token", + value: function oauth2_token(callback) { + var _this = this; + + var dfd = this._getDfd(); + + if (this._oauth_consumer_key === null) { + var error = "To obtain a bearer token, the consumer key must be set."; + if (dfd) { + dfd.reject({ error: error }); + return this._getPromise(dfd); + } + throw error; + } - var xml = _getXmlRequestObject(); + if (!dfd && typeof callback === "undefined") { + callback = function callback() {}; + } + + var post_fields = "grant_type=client_credentials"; + var url = this._endpoint_oauth + "oauth2/token"; + + if (this._use_proxy) { + url = url.replace(this._endpoint_base, this._endpoint_proxy); + } + + var xml = this._getXmlRequestObject(); if (xml === null) { - return; + return; } - var post_fields; + xml.open("POST", url, true); + xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + xml.setRequestHeader((this._use_proxy ? "X-" : "") + "Authorization", "Basic " + this._base64_encode(this._oauth_consumer_key + ":" + this._oauth_consumer_secret)); - if (httpmethod === "GET") { - var url_with_params = url; - if (JSON.stringify(params) !== "{}") { - url_with_params += "?" + _http_build_query(params); + xml.onreadystatechange = function () { + if (xml.readyState >= 4) { + var httpstatus = 12027; + try { + httpstatus = xml.status; + } catch (e) {} + var response = ""; + try { + response = xml.responseText; + } catch (e) {} + var reply = _this._parseApiReply(response); + reply.httpstatus = httpstatus; + if (httpstatus === 200) { + _this.setBearerToken(reply.access_token); } - if (! app_only_auth) { - authorization = _sign(httpmethod, url, params); + if (typeof callback === "function") { + callback(reply); } - - // append auth params to GET url for IE7-9, to send via JSONP - if (_use_jsonp) { - if (JSON.stringify(params) !== "{}") { - url_with_params += "&"; - } else { - url_with_params += "?"; - } - var callback_name = _nonce(); - window[callback_name] = function (reply) { - reply.httpstatus = 200; - - var rate = null; - if (typeof xml.getResponseHeader !== "undefined" - && xml.getResponseHeader("x-rate-limit-limit") !== "" - ) { - rate = { - limit: xml.getResponseHeader("x-rate-limit-limit"), - remaining: xml.getResponseHeader("x-rate-limit-remaining"), - reset: xml.getResponseHeader("x-rate-limit-reset") - }; - } - callback(reply, rate); - }; - params.callback = callback_name; - url_with_params = url + "?" + _sign(httpmethod, url, params, true); - var tag = document.createElement("script"); - tag.type = "text/javascript"; - tag.src = url_with_params; - var body = document.getElementsByTagName("body")[0]; - body.appendChild(tag); - return; - - } else if (_use_proxy) { - url_with_params = url_with_params.replace( - _endpoint_base, - _endpoint_proxy - ).replace( - _endpoint_base_media, - _endpoint_proxy - ); + if (dfd) { + dfd.resolve({ reply: reply }); } - xml.open(httpmethod, url_with_params, true); + } + }; + // function called when an error occurs, including a timeout + xml.onerror = function (e) { + if (typeof callback === "function") { + callback(null, e); + } + if (dfd) { + dfd.reject(e); + } + }; + xml.timeout = 30000; // in milliseconds + + xml.send(post_fields); + if (dfd) { + return this._getPromise(dfd); + } + } + + /** + * Calls the API using cURL + * + * @param string httpmethod The HTTP method to use for making the request + * @param string method The API method to call + * @param array optional params The parameters to send along + * @param bool optional multipart Whether to use multipart/form-data + * @param bool optional app_only_auth Whether to use app-only bearer authentication + * @param function callback The function to call with the API call result + * + * @return mixed The API reply, encoded in the set return_format + */ + + }, { + key: "_callApi", + value: function _callApi(httpmethod, method) { + var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + var multipart = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; + + var _this2 = this; + + var app_only_auth = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + var callback = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : function () {}; + + var dfd = this._getDfd(); + + var url = this._getEndpoint(method), + authorization = null; + + var xml = this._getXmlRequestObject(); + if (xml === null) { + return; + } + var post_fields = void 0; + + if (httpmethod === "GET") { + var url_with_params = url; + if (JSON.stringify(params) !== "{}") { + url_with_params += "?" + this._http_build_query(params); + } + if (!app_only_auth) { + authorization = this._sign(httpmethod, url, params); + } + + if (this._use_proxy) { + url_with_params = url_with_params.replace(this._endpoint_base, this._endpoint_proxy).replace(this._endpoint_base_media, this._endpoint_proxy); + } + xml.open(httpmethod, url_with_params, true); } else { - if (_use_jsonp) { - console.warn("Sending POST requests is not supported for IE7-9."); - return; + if (multipart) { + if (!app_only_auth) { + authorization = this._sign(httpmethod, url, {}); } - if (multipart) { - if (! app_only_auth) { - authorization = _sign(httpmethod, url, {}); - } - params = _buildMultipart(method, params); - } else { - if (! app_only_auth) { - authorization = _sign(httpmethod, url, params); - } - params = _http_build_query(params); - } - post_fields = params; - if (_use_proxy || multipart) { // force proxy for multipart base64 - url = url.replace( - _endpoint_base, - _endpoint_proxy - ).replace( - _endpoint_base_media, - _endpoint_proxy - ); - } - xml.open(httpmethod, url, true); - if (multipart) { - xml.setRequestHeader("Content-Type", "multipart/form-data; boundary=" - + post_fields.split("\r\n")[0].substring(2)); - } else { - xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + params = this._buildMultipart(method, params); + } else if (this._detectJsonBody(method)) { + authorization = this._sign(httpmethod, url, {}); + params = JSON.stringify(params); + } else { + if (!app_only_auth) { + authorization = this._sign(httpmethod, url, params); } + params = this._http_build_query(params); + } + post_fields = params; + if (this._use_proxy || multipart) { + // force proxy for multipart base64 + url = url.replace(this._endpoint_base, this._endpoint_proxy).replace(this._endpoint_base_media, this._endpoint_proxy); + } + xml.open(httpmethod, url, true); + if (multipart) { + xml.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + post_fields.split("\r\n")[0].substring(2)); + } else if (this._detectJsonBody(method)) { + xml.setRequestHeader("Content-Type", "application/json"); + } else { + xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + } } if (app_only_auth) { - if (_oauth_consumer_key === null - && _oauth_bearer_token === null - ) { - console.warn("To make an app-only auth API request, consumer key or bearer token must be set."); + if (this._oauth_consumer_key === null && this._oauth_bearer_token === null) { + var error = "To make an app-only auth API request, consumer key or bearer token must be set."; + if (dfd) { + dfd.reject({ error: error }); + return this._getPromise(dfd); } - // automatically fetch bearer token, if necessary - if (_oauth_bearer_token === null) { - return oauth2_token(function () { - _callApi(httpmethod, method, params, multipart, app_only_auth, false, callback); - }); + throw error; + } + // automatically fetch bearer token, if necessary + if (this._oauth_bearer_token === null) { + if (dfd) { + return this.oauth2_token().then(function () { + return _this2._callApi(httpmethod, method, params, multipart, app_only_auth, callback); + }); } - authorization = "Bearer " + _oauth_bearer_token; + this.oauth2_token(function () { + _this2._callApi(httpmethod, method, params, multipart, app_only_auth, callback); + }); + return; + } + authorization = "Bearer " + this._oauth_bearer_token; } if (authorization !== null) { - xml.setRequestHeader((_use_proxy ? "X-" : "") + "Authorization", authorization); + xml.setRequestHeader((this._use_proxy ? "X-" : "") + "Authorization", authorization); } xml.onreadystatechange = function () { - if (xml.readyState >= 4) { - var httpstatus = 12027; - try { - httpstatus = xml.status; - } catch (e) {} - var response = ""; - try { - response = xml.responseText; - } catch (e) {} - var reply = _parseApiReply(response); - reply.httpstatus = httpstatus; - var rate = null; - if (typeof xml.getResponseHeader !== "undefined" - && xml.getResponseHeader("x-rate-limit-limit") !== "" - ) { - rate = { - limit: xml.getResponseHeader("x-rate-limit-limit"), - remaining: xml.getResponseHeader("x-rate-limit-remaining"), - reset: xml.getResponseHeader("x-rate-limit-reset") - }; - } - callback(reply, rate); + if (xml.readyState >= 4) { + var httpstatus = 12027; + try { + httpstatus = xml.status; + } catch (e) {} + var response = ""; + try { + response = xml.responseText; + } catch (e) {} + var reply = _this2._parseApiReply(response); + reply.httpstatus = httpstatus; + var rate = null; + if (typeof xml.getResponseHeader !== "undefined" && xml.getResponseHeader("x-rate-limit-limit") !== "") { + rate = { + limit: xml.getResponseHeader("x-rate-limit-limit"), + remaining: xml.getResponseHeader("x-rate-limit-remaining"), + reset: xml.getResponseHeader("x-rate-limit-reset") + }; + } + if (typeof callback === "function") { + callback(reply, rate); + } + if (dfd) { + dfd.resolve({ reply: reply, rate: rate }); } + } }; + // function called when an error occurs, including a timeout + xml.onerror = function (e) { + if (typeof callback === "function") { + callback(null, null, e); + } + if (dfd) { + dfd.reject(e); + } + }; + xml.timeout = 30000; // in milliseconds + xml.send(httpmethod === "GET" ? null : post_fields); + if (dfd) { + return this._getPromise(dfd); + } return true; - }; + } + + /** + * Main API handler working on any requests you issue + * + * @param string fn The member function you called + * @param array params The parameters you sent along + * @param function callback The callback to call with the reply + * @param bool app_only_auth Whether to use app-only auth + * + * @return object Promise + */ + + }, { + key: "__call", + value: function __call(fn) { + var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var callback = arguments[2]; + var app_only_auth = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; - /** - * Parses the API reply to encode it in the set return_format - * - * @param string reply The actual reply, JSON-encoded or URL-encoded - * - * @return array|object The parsed reply - */ - var _parseApiReply = function (reply) { - if (typeof reply !== "string" || reply === "") { - return {}; + if (typeof callback !== "function" && typeof params === "function") { + callback = params; + params = {}; + if (typeof callback === "boolean") { + app_only_auth = callback; + } + } else if (typeof callback === "undefined") { + callback = function callback() {}; } - if (reply === "[]") { - return []; + switch (fn) { + case "oauth_authenticate": + case "oauth_authorize": + return this[fn](params, callback); + + case "oauth2_token": + return this[fn](callback); } - var parsed; - try { - parsed = JSON.parse(reply); - } catch (e) { - parsed = {}; - if (reply.indexOf("<" + "?xml version=\"1.0\" encoding=\"UTF-8\"?" + ">") === 0) { - // we received XML... - // since this only happens for errors, - // don't perform a full decoding - parsed.request = reply.match(/(.*)<\/request>/)[1]; - parsed.error = reply.match(/(.*)<\/error>/)[1]; - } else { - // assume query format - var elements = reply.split("&"); - for (var i = 0; i < elements.length; i++) { - var element = elements[i].split("=", 2); - if (element.length > 1) { - parsed[element[0]] = decodeURIComponent(element[1]); - } else { - parsed[element[0]] = null; - } - } - } + + // parse parameters + var apiparams = this._parseApiParams(params); + + // stringify null and boolean parameters + apiparams = this._stringifyNullBoolParams(apiparams); + + // reset token when requesting a new token (causes 401 for signature error on 2nd+ requests) + if (fn === "oauth_requestToken") { + this.setToken(null, null); } - return parsed; - }; - - return { - setConsumerKey: setConsumerKey, - getVersion: getVersion, - setToken: setToken, - setBearerToken: setBearerToken, - setUseProxy: setUseProxy, - setProxy: setProxy, - getApiMethods: getApiMethods, - __call: __call, - oauth_authenticate: oauth_authenticate, - oauth_authorize: oauth_authorize, - oauth2_token: oauth2_token - }; -}; - -if (typeof module === "object" - && module - && typeof module.exports === "object" -) { + + // map function name to API method + + var _mapFnToApiMethod2 = this._mapFnToApiMethod(fn, apiparams), + _mapFnToApiMethod3 = _slicedToArray(_mapFnToApiMethod2, 2), + method = _mapFnToApiMethod3[0], + method_template = _mapFnToApiMethod3[1], + httpmethod = this._detectMethod(method_template, apiparams), + multipart = this._detectMultipart(method_template); + + return this._callApi(httpmethod, method, apiparams, multipart, app_only_auth, callback); + } + }]); + + return Codebird; + }(); + + ; + + if ((typeof module === "undefined" ? "undefined" : _typeof(module)) === "object" && module && _typeof(module.exports) === "object") { // Expose codebird as module.exports in loaders that implement the Node // module pattern (including browserify). Do not create the global, since // the user will be storing it themselves locally, and globals are frowned // upon in the Node module world. module.exports = Codebird; -} else { + } else { // Otherwise expose codebird to the global object as usual - if (typeof window === "object" - && window) { - window.Codebird = Codebird; + if ((typeof window === "undefined" ? "undefined" : _typeof(window)) === "object" && window) { + window.Codebird = Codebird; } // Register as a named AMD module, since codebird can be concatenated with other @@ -1506,8 +1578,9 @@ if (typeof module === "object" // file name. Do this after creating the global so that if an AMD module wants // to call noConflict to hide this version of codebird, it will work. if (typeof define === "function" && define.amd) { - define("codebird", [], function () { return Codebird; }); + define("codebird", [], function () { + return Codebird; + }); } -} - + } })(); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f4adf61 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3618 @@ +{ + "name": "codebird", + "version": "3.0.0-dev", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "acorn": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", + "dev": true + }, + "acorn-jsx": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", + "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", + "dev": true, + "requires": { + "acorn": "^5.0.3" + } + }, + "ajv": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", + "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.1" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", + "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "optional": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true, + "optional": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true, + "optional": true + }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-polyfill": "^6.26.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "chokidar": "^1.6.1", + "commander": "^2.11.0", + "convert-source-map": "^1.5.0", + "fs-readdir-recursive": "^1.0.0", + "glob": "^7.1.2", + "lodash": "^4.17.4", + "output-file-sync": "^1.1.2", + "path-is-absolute": "^1.0.1", + "slash": "^1.0.0", + "source-map": "^0.5.6", + "v8flags": "^2.1.1" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + } + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + } + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + } + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + } + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "^0.10.0" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-es2015": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", + "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.24.1", + "babel-plugin-transform-es2015-classes": "^6.24.1", + "babel-plugin-transform-es2015-computed-properties": "^6.24.1", + "babel-plugin-transform-es2015-destructuring": "^6.22.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", + "babel-plugin-transform-es2015-for-of": "^6.22.0", + "babel-plugin-transform-es2015-function-name": "^6.24.1", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1", + "babel-plugin-transform-es2015-modules-umd": "^6.24.1", + "babel-plugin-transform-es2015-object-super": "^6.24.1", + "babel-plugin-transform-es2015-parameters": "^6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.24.1", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.24.1", + "babel-plugin-transform-regenerator": "^6.24.1" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + }, + "dependencies": { + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "dev": true + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==", + "dev": true + } + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + } + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + } + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "optional": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "color-convert": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", + "dev": true, + "requires": { + "color-name": "1.1.1" + } + }, + "color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", + "dev": true + }, + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "^1.1.1", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.1" + } + }, + "escape-string-regexp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.4.tgz", + "integrity": "sha1-uF5nm0b3LQP7voo79yWdU1whti8=", + "dev": true + }, + "eslint": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.3.0.tgz", + "integrity": "sha512-N/tCqlMKkyNvAvLu+zI9AqDasnSLt00K+Hu8kdsERliC9jYEc8ck12XtjvOXrBKu8fK6RrBcN9bat6Xk++9jAg==", + "dev": true, + "requires": { + "ajv": "^6.5.0", + "babel-code-frame": "^6.26.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^4.0.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.2", + "imurmurhash": "^0.1.4", + "inquirer": "^5.2.0", + "is-resolvable": "^1.1.0", + "js-yaml": "^3.11.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.5", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^2.0.0", + "require-uncached": "^1.0.3", + "semver": "^5.5.0", + "string.prototype.matchall": "^2.0.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^4.0.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", + "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", + "dev": true, + "requires": { + "acorn": "^5.6.0", + "acorn-jsx": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "optional": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^2.1.0" + } + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "faucet": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/faucet/-/faucet-0.0.1.tgz", + "integrity": "sha1-WX3PHSGJosBiMhtZHo8VHtIDnZw=", + "dev": true, + "requires": { + "defined": "0.0.0", + "duplexer": "~0.1.1", + "minimist": "0.0.5", + "sprintf": "~0.1.3", + "tap-parser": "~0.4.0", + "tape": "~2.3.2", + "through2": "~0.2.3" + }, + "dependencies": { + "deep-equal": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.1.2.tgz", + "integrity": "sha1-skbCuApXCkfBG+HZvRBw7IeLh84=", + "dev": true + }, + "defined": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", + "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", + "dev": true + }, + "minimist": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.5.tgz", + "integrity": "sha1-16oye87PUY+RBqxrjwA/o7zqhWY=", + "dev": true + }, + "tape": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tape/-/tape-2.3.3.tgz", + "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=", + "dev": true, + "requires": { + "deep-equal": "~0.1.0", + "defined": "~0.0.0", + "inherits": "~2.0.1", + "jsonify": "~0.0.0", + "resumer": "~0.0.0", + "through": "~2.3.4" + } + } + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + } + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" + } + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "optional": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "optional": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "optional": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "globals": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.7.0.tgz", + "integrity": "sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.2.tgz", + "integrity": "sha1-/iI5t1dJcuZ+QfgIgj+b+kqZHjc=", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz", + "integrity": "sha1-bLtFIevVHODsCpNr/XZX736bFyo=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "inquirer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.1.0", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^5.5.2", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true, + "optional": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "optional": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "optional": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true, + "optional": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true, + "optional": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "optional": true, + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + } + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "math-random": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true, + "optional": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true, + "optional": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "nice-try": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", + "dev": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "number-is-nan": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz", + "integrity": "sha1-wCD1KcUoKt/dIz2R1LGBw9aG3Es=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-inspect": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", + "dev": true + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "optional": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-homedir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz", + "integrity": "sha1-DWK99EuRb9O73PLKsZGUj7CU8Ac=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.4", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "optional": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", + "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true, + "optional": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.6.tgz", + "integrity": "sha1-D5awAc6pCxJZLOVm7bl+wR5pvQU=", + "dev": true, + "optional": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "randomatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", + "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "optional": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.5.tgz", + "integrity": "sha1-okJvjc1FUcd6M/lu3yiGojyClmk=", + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true, + "optional": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "optional": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regexp.prototype.flags": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", + "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2" + } + }, + "regexpp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.0.tgz", + "integrity": "sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA==", + "dev": true + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.5.2.tgz", + "integrity": "sha1-IQZfcHJ60FOg3V6VesngDHVg2Qo=", + "dev": true, + "optional": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, + "resolve": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + } + } + }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "dev": true, + "requires": { + "through": "~2.3.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rxjs": { + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz", + "integrity": "sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==", + "dev": true, + "requires": { + "symbol-observable": "1.0.1" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "optional": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "sprintf": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz", + "integrity": "sha1-j4PjmpMXwaUCy324BQ5Rxnn27c8=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string.prototype.matchall": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-2.0.0.tgz", + "integrity": "sha512-WoZ+B2ypng1dp4iFLF2kmZlwwlE19gmjgKuhL1FJfDgCREWb3ye3SDVHSzLH6bxfnvYmkCxbzkmWcQZHA4P//Q==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.10.0", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "regexp.prototype.flags": "^1.2.0" + } + }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.0", + "function-bind": "^1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.0.tgz", + "integrity": "sha1-dRC2ZVZ8qRTMtdfgcnY6yWi+NyQ=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", + "dev": true + }, + "table": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", + "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "dev": true, + "requires": { + "ajv": "^6.0.1", + "ajv-keywords": "^3.0.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + }, + "tap-parser": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-0.4.3.tgz", + "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~1.1.11" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "integrity": "sha1-9u73ZPUUyJ4rniMUanW6EGdW0j4=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, + "tape": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz", + "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==", + "dev": true, + "requires": { + "deep-equal": "~1.0.1", + "defined": "~1.0.0", + "for-each": "~0.3.3", + "function-bind": "~1.1.1", + "glob": "~7.1.2", + "has": "~1.0.3", + "inherits": "~2.0.3", + "minimist": "~1.2.0", + "object-inspect": "~1.6.0", + "resolve": "~1.7.1", + "resumer": "~0.0.0", + "string.prototype.trim": "~1.1.2", + "through": "~2.3.8" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "tape-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tape-promise/-/tape-promise-1.1.0.tgz", + "integrity": "sha1-5XVNU3GwtkoN74WllQtPwCZNoCk=", + "dev": true, + "requires": { + "onetime": "^1.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "dev": true, + "requires": { + "readable-stream": "~1.1.9", + "xtend": "~2.1.1" + }, + "dependencies": { + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "readable-stream": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", + "integrity": "sha1-9u73ZPUUyJ4rniMUanW6EGdW0j4=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "requires": { + "object-keys": "~0.4.0" + } + } + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true, + "optional": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "^1.1.1" + }, + "dependencies": { + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.1.tgz", + "integrity": "sha1-HmWWmWXMvC20VIxrhKbyxa7dRzk=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 9a98048..b2a6cb0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codebird", - "version": "2.6.0", + "version": "3.0.0-dev", "description": "A Twitter library in JavaScript.", "keywords": [ "Twitter", @@ -11,12 +11,12 @@ "homepage": "http://www.jublo.net/projects/codebird/js", "bugs": "https://github.com/jublonet/codebird-js/issues", "license": "GPL-3.0+", - "author": "Jublo Solutions (http://jublo.net/)", + "author": "Jublo Limited (http://jublo.net/)", "contributors": [ "Joshua Atkins (http://atkins.im/)", "J.M. (http://mynetx.net/)" ], - "main": "codebird.js", + "main": "codebird.es7.js", "directories": { "example": "examples" }, @@ -25,6 +25,21 @@ "url": "https://github.com/jublonet/codebird-js.git" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "build-cb": "babel codebird.es7.js -o codebird.js", + "build-cbt": "babel test/codebirdt.es7.js -o test/codebirdt.js", + "build-cbm": "babel test/codebirdm.es7.js -o test/codebirdm.js", + "build": "npm run build-cb && npm run build-cbt && npm run build-cbm", + "test-run": "tape test/*_tests.js | faucet", + "test": "npm run build && npm run test-run" + }, + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-preset-es2015": "^6.24.1", + "eslint": "^5.3.0", + "faucet": "0.0.1", + "q": "^1.5.1", + "tape": "^4.9.1", + "tape-promise": "^1.1.0", + "xmlhttprequest": "^1.8.0" } } diff --git a/test/README b/test/README new file mode 100644 index 0000000..c2249fc --- /dev/null +++ b/test/README @@ -0,0 +1,9 @@ +The following methods are covered by unit tests: + +_detectMethod +_detectMultipart +_detectMedia +_getEndpoint +oauth_authenticate +oauth_authorize +oauth2_token diff --git a/test/codebirdm.es7.js b/test/codebirdm.es7.js new file mode 100644 index 0000000..766ad4b --- /dev/null +++ b/test/codebirdm.es7.js @@ -0,0 +1,66 @@ +import CodebirdT from "./codebirdt"; + +/** + * A Twitter library in JavaScript + * + * @package codebird-test + * @version 3.0.0-dev + * @author Jublo Limited + * @copyright 2010-2018 Jublo Limited + * @license http://opensource.org/licenses/GPL-3.0 GNU Public License 3.0 + * @link https://github.com/jublonet/codebird-php + */ + +/** + * A Twitter library in JavaScript + * + * @package codebird-test + */ +export default class CodebirdM extends CodebirdT { + + constructor() { + super(); + /** + * Mock API replies + */ + this._mock_replies = { + default: { + httpstatus: 404, + reply: "{\"errors\":[{\"message\":\"Sorry, that page does not exist\",\"code\":34}]}" + }, + "GET https://api.twitter.com/1.1/users/show.json?screen_name=TwitterAPI": { + httpstatus: 200, + reply: "{\"id\":6253282,\"id_str\":\"6253282\",\"name\":\"Twitter API\",\"screen_name\":\"twitterapi\",\"location\":\"San Francisco, CA\",\"profile_location\":null,\"description\":\"The Real Twitter API. I tweet about API changes, service issues and happily answer questions about Twitter and our API. Don't get an answer? It's on my website.\",\"url\":\"http:\/\/t.co\/78pYTvWfJd\",\"entities\":{\"url\":{\"urls\":[{\"url\":\"http:\/\/t.co\/78pYTvWfJd\",\"expanded_url\":\"http:\/\/dev.twitter.com\",\"display_url\":\"dev.twitter.com\",\"indices\":[0,22]}]},\"description\":{\"urls\":[]}},\"protected\":false,\"followers_count\":4993679,\"friends_count\":48,\"listed_count\":13001,\"created_at\":\"Wed May 23 06:01:13 +0000 2007\",\"favourites_count\":27,\"utc_offset\":-28800,\"time_zone\":\"Pacific Time (US & Canada)\",\"geo_enabled\":true,\"verified\":true,\"statuses_count\":3553,\"lang\":\"en\",\"status\":{\"created_at\":\"Tue Nov 24 08:56:07 +0000 2015\",\"id\":669077021138493440,\"id_str\":\"669077021138493440\",\"text\":\"Additional 64-bit entity ID migration coming in Feb 2016 https:\/\/t.co\/eQIGvw1rsJ\",\"source\":\"\u003ca href=\\\"https:\/\/about.twitter.com\/products\/tweetdeck\\\" rel=\\\"nofollow\\\"\u003eTweetDeck\u003c\/a\u003e\",\"truncated\":false,\"in_reply_to_status_id\":null,\"in_reply_to_status_id_str\":null,\"in_reply_to_user_id\":null,\"in_reply_to_user_id_str\":null,\"in_reply_to_screen_name\":null,\"geo\":null,\"coordinates\":null,\"place\":null,\"contributors\":null,\"retweet_count\":67,\"favorite_count\":79,\"entities\":{\"hashtags\":[],\"symbols\":[],\"user_mentions\":[],\"urls\":[{\"url\":\"https:\/\/t.co\/eQIGvw1rsJ\",\"expanded_url\":\"https:\/\/twittercommunity.com\/t\/migration-of-twitter-core-entities-to-64-bit-ids\/56881\",\"display_url\":\"twittercommunity.com\/t\/migration-of\u2026\",\"indices\":[57,80]}]},\"favorited\":false,\"retweeted\":false,\"possibly_sensitive\":false,\"lang\":\"en\"},\"contributors_enabled\":false,\"is_translator\":false,\"is_translation_enabled\":false,\"profile_background_color\":\"C0DEED\",\"profile_background_image_url\":\"http:\/\/pbs.twimg.com\/profile_background_images\/656927849\/miyt9dpjz77sc0w3d4vj.png\",\"profile_background_image_url_https\":\"https:\/\/pbs.twimg.com\/profile_background_images\/656927849\/miyt9dpjz77sc0w3d4vj.png\",\"profile_background_tile\":true,\"profile_image_url\":\"http:\/\/pbs.twimg.com\/profile_images\/2284174872\/7df3h38zabcvjylnyfe3_normal.png\",\"profile_image_url_https\":\"https:\/\/pbs.twimg.com\/profile_images\/2284174872\/7df3h38zabcvjylnyfe3_normal.png\",\"profile_banner_url\":\"https:\/\/pbs.twimg.com\/profile_banners\/6253282\/1431474710\",\"profile_link_color\":\"0084B4\",\"profile_sidebar_border_color\":\"C0DEED\",\"profile_sidebar_fill_color\":\"DDEEF6\",\"profile_text_color\":\"333333\",\"profile_use_background_image\":true,\"has_extended_profile\":false,\"default_profile\":false,\"default_profile_image\":false,\"following\":true,\"follow_request_sent\":false,\"notifications\":false}" + }, + "POST https://api.twitter.com/oauth2/token": { + httpstatus: 200, + reply: "{\"token_type\":\"bearer\",\"access_token\":\"VqiO0n2HrKE\"}" + } + }; + + this.xml = { + readyState: 4, + open: (httpmethod, url) => { + this.xml.httpmethod = httpmethod; + this.xml.url = url; + const key = `${httpmethod} ${url}`; + if (this._mock_replies.hasOwnProperty(key)) { + this.xml.status = this._mock_replies[key].httpstatus; + this.xml.responseText = this._mock_replies[key].reply; + } else { + this.xml.status = this._mock_replies.default.httpstatus; + this.xml.responseText = this._mock_replies.default.reply; + } + }, + setRequestHeader: () => true, + onreadystatechange: () => false, + send: function () { + setTimeout(this.onreadystatechange, 200); + } + }; + } + + _getXmlRequestObject() { + return this.xml; + }; +} diff --git a/test/codebirdt.es7.js b/test/codebirdt.es7.js new file mode 100644 index 0000000..88861d0 --- /dev/null +++ b/test/codebirdt.es7.js @@ -0,0 +1,93 @@ +import Codebird from "../codebird"; + +/** + * A Twitter library in JavaScript + * + * @package codebird-test + * @version 3.0.0-dev + * @author Jublo Limited + * @copyright 2010-2018 Jublo Limited + * @license http://opensource.org/licenses/GPL-3.0 GNU Public License 3.0 + * @link https://github.com/jublonet/codebird-php + */ + +/** + * A Twitter library in JavaScript + * + * @package codebird-test + */ +export default class CodebirdT extends Codebird { + + /** + * Returns properties + * + * @param string property The property to get + * + * @return mixed Property + */ + get(property) { + if (typeof this.property !== "undefined") { + return this.property; + } + throw `Property ${property} is not defined.`; + } + + /** + * Returns static properties + * + * @param string property The property to get + * + * @return mixed Property + */ + getStatic(property) { + if (typeof CodebirdT.property !== "undefined") { + return CodebirdT.property; + } + throw `Static property ${property} is not defined.`; + } + + /** + * Calls methods + * + * @param string method The method to call + * @param mixed params The parameters to send along + * + * @return mixed Return value + */ + call(method, params = []) { + if (typeof this[method] === "function") { + return this[method].apply(this, params); + } + throw `Method ${method} is not defined.`; + } + + /** + * Calls static methods + * + * @param string method The method to call + * @param mixed params The parameters to send along + * + * @return mixed Return value + */ + callStatic(method, params = []) { + if (typeof CodebirdT[method] === "function") { + return CodebirdT[method].apply(this, params); + } + throw `Static method ${method} is not defined.`; + } + +/* +// Unit testing code + this.__test = { + call: (name, params = []) => this[name].apply(this, params), + get: name => this[name], + mock: methods_to_mock => { + for (let name in methods_to_mock) { + if (methods_to_mock.hasOwnProperty(name)) { + this[name] = methods_to_mock[name]; + } + } + } + }; +*/ +} diff --git a/test/detection_tests.js b/test/detection_tests.js new file mode 100644 index 0000000..8c7d7a1 --- /dev/null +++ b/test/detection_tests.js @@ -0,0 +1,100 @@ +const tape = require("tape"), + _test = require("tape-promise"), + test = _test(tape), // decorate tape + CodebirdT = require("./codebirdt"); + +function getCB() { + return new CodebirdT.default; +} + +test("Tests _detectMethod", function (t) { + const cb = getCB(); + + t.throws( + function () { + cb.call("_detectMethod", ["non-existent", {}]); + }, + "Can't find HTTP method to use for \"non-existent\"." + ); + + // forced httpmethod + t.equal( + cb.call("_detectMethod", ["doesnt-matter", {httpmethod: "DELETE"}]), + "DELETE" + ); + + // normal detection + t.equal( + cb.call("_detectMethod", ["account_activity/all/:env_name/subscriptions", {}]), + "GET" + ); + t.equal( + cb.call("_detectMethod", ["search/tweets", {}]), + "GET" + ); + t.equal( + cb.call("_detectMethod", ["statuses/update", {}]), + "POST" + ); + t.equal( + cb.call("_detectMethod", ["statuses/destroy/:id", {}]), + "POST" + ); + + // parameter-based detection + t.equal( + cb.call("_detectMethod", ["account/settings", {}]), + "GET" + ); + t.equal( + cb.call("_detectMethod", ["account/settings", {test: 12}]), + "POST" + ); + + t.end(); +}); + +test("Tests _detectMultipart", function (t) { + const cb = getCB(); + + t.false(cb.call("_detectMultipart", ["statuses/update"])); + t.true(cb.call("_detectMultipart", ["media/upload"])); + + t.end(); +}); + +test("Tests _detectMedia", function (t) { + const cb = getCB(); + + t.false(cb.call("_detectMedia", ["statuses/update"])); + t.true(cb.call("_detectMedia", ["media/upload"])); + + t.end(); +}); + +test("Tests _getEndpoint", function (t) { + const cb = getCB(); + + t.equal( + cb.call("_getEndpoint", ["statuses/update", "statuses/update"]), + "https://api.twitter.com/1.1/statuses/update.json" + ); + t.equal( + cb.call("_getEndpoint", ["oauth/authenticate", "oauth/authenticate"]), + "https://api.twitter.com/oauth/authenticate" + ); + t.equal( + cb.call("_getEndpoint", ["oauth2/token", "oauth2/token"]), + "https://api.twitter.com/oauth2/token" + ); + t.equal( + cb.call("_getEndpoint", ["media/upload", "media/upload"]), + "https://upload.twitter.com/1.1/media/upload.json" + ); + t.equal( + cb.call("_getEndpoint", ["statuses/oembed", "statuses/oembed"]), + "https://publish.twitter.com/oembed" + ); + + t.end(); +}); diff --git a/test/functional_tests.js b/test/functional_tests.js new file mode 100644 index 0000000..aa717aa --- /dev/null +++ b/test/functional_tests.js @@ -0,0 +1,37 @@ +const tape = require("tape"), + _test = require("tape-promise"), + test = _test(tape), // decorate tape + CodebirdT = require("./codebirdt"); + +function getCB() { + var cb = new CodebirdT.default; + cb.setConsumerKey("123", "456"); + + return cb; +} + +test("Tests statuses/update", function (t) { + const cb = getCB(); + t.plan(1); + + cb.setToken("123", "456"); + return cb.__call( + "statuses_update", + {"status": "Whohoo, I just tweeted!"} + ).then(function (reply, rate, err) { + t.deepEqual( + reply, + { + rate: { + limit: null, remaining: null, reset: null + }, + reply: { + errors: [ + { code: 89, message: "Invalid or expired token." } + ], + httpstatus: 401 + } + } + ) + }); +}); diff --git a/test/media_tests.js b/test/media_tests.js new file mode 100644 index 0000000..97781c0 --- /dev/null +++ b/test/media_tests.js @@ -0,0 +1,37 @@ +const tape = require("tape"), + _test = require("tape-promise"), + test = _test(tape), // decorate tape + CodebirdT = require("./codebirdt"); + +function getCB() { + var cb = new CodebirdT.default; + cb.setConsumerKey("123", "456"); + + return cb; +} + +test("Tests media/upload base64", function (t) { + const cb = getCB(); + t.plan(1); + + cb.setToken("123", "456"); + return cb.__call( + "media_upload", + {"media_data": "R0lGODlhPQBEAPeoAJosM//AwO/AwHVYZ/z595kzAP/s7P+goOXMv8+fhw/v739/f+8PD98fH/8mJl+fn/9ZWb8/PzWlwv///6wWGbImAPgTEMImIN9gUFCEm/gDALULDN8PAD6atYdCTX9gUNKlj8wZAKUsAOzZz+UMAOsJAP/Z2ccMDA8PD/95eX5NWvsJCOVNQPtfX/8zM8+QePLl38MGBr8JCP+zs9myn/8GBqwpAP/GxgwJCPny78lzYLgjAJ8vAP9fX/+MjMUcAN8zM/9wcM8ZGcATEL+QePdZWf/29uc/P9cmJu9MTDImIN+/r7+/vz8/P8VNQGNugV8AAF9fX8swMNgTAFlDOICAgPNSUnNWSMQ5MBAQEJE3QPIGAM9AQMqGcG9vb6MhJsEdGM8vLx8fH98AANIWAMuQeL8fABkTEPPQ0OM5OSYdGFl5jo+Pj/+pqcsTE78wMFNGQLYmID4dGPvd3UBAQJmTkP+8vH9QUK+vr8ZWSHpzcJMmILdwcLOGcHRQUHxwcK9PT9DQ0O/v70w5MLypoG8wKOuwsP/g4P/Q0IcwKEswKMl8aJ9fX2xjdOtGRs/Pz+Dg4GImIP8gIH0sKEAwKKmTiKZ8aB/f39Wsl+LFt8dgUE9PT5x5aHBwcP+AgP+WltdgYMyZfyywz78AAAAAAAD///8AAP9mZv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAKgALAAAAAA9AEQAAAj/AFEJHEiwoMGDCBMqXMiwocAbBww4nEhxoYkUpzJGrMixogkfGUNqlNixJEIDB0SqHGmyJSojM1bKZOmyop0gM3Oe2liTISKMOoPy7GnwY9CjIYcSRYm0aVKSLmE6nfq05QycVLPuhDrxBlCtYJUqNAq2bNWEBj6ZXRuyxZyDRtqwnXvkhACDV+euTeJm1Ki7A73qNWtFiF+/gA95Gly2CJLDhwEHMOUAAuOpLYDEgBxZ4GRTlC1fDnpkM+fOqD6DDj1aZpITp0dtGCDhr+fVuCu3zlg49ijaokTZTo27uG7Gjn2P+hI8+PDPERoUB318bWbfAJ5sUNFcuGRTYUqV/3ogfXp1rWlMc6awJjiAAd2fm4ogXjz56aypOoIde4OE5u/F9x199dlXnnGiHZWEYbGpsAEA3QXYnHwEFliKAgswgJ8LPeiUXGwedCAKABACCN+EA1pYIIYaFlcDhytd51sGAJbo3onOpajiihlO92KHGaUXGwWjUBChjSPiWJuOO/LYIm4v1tXfE6J4gCSJEZ7YgRYUNrkji9P55sF/ogxw5ZkSqIDaZBV6aSGYq/lGZplndkckZ98xoICbTcIJGQAZcNmdmUc210hs35nCyJ58fgmIKX5RQGOZowxaZwYA+JaoKQwswGijBV4C6SiTUmpphMspJx9unX4KaimjDv9aaXOEBteBqmuuxgEHoLX6Kqx+yXqqBANsgCtit4FWQAEkrNbpq7HSOmtwag5w57GrmlJBASEU18ADjUYb3ADTinIttsgSB1oJFfA63bduimuqKB1keqwUhoCSK374wbujvOSu4QG6UvxBRydcpKsav++Ca6G8A6Pr1x2kVMyHwsVxUALDq/krnrhPSOzXG1lUTIoffqGR7Goi2MAxbv6O2kEG56I7CSlRsEFKFVyovDJoIRTg7sugNRDGqCJzJgcKE0ywc0ELm6KBCCJo8DIPFeCWNGcyqNFE06ToAfV0HBRgxsvLThHn1oddQMrXj5DyAQgjEHSAJMWZwS3HPxT/QMbabI/iBCliMLEJKX2EEkomBAUCxRi42VDADxyTYDVogV+wSChqmKxEKCDAYFDFj4OmwbY7bDGdBhtrnTQYOigeChUmc1K3QTnAUfEgGFgAWt88hKA6aCRIXhxnQ1yg3BCayK44EWdkUQcBByEQChFXfCB776aQsG0BIlQgQgE8qO26X1h8cEUep8ngRBnOy74E9QgRgEAC8SvOfQkh7FDBDmS43PmGoIiKUUEGkMEC/PJHgxw0xH74yx/3XnaYRJgMB8obxQW6kL9QYEJ0FIFgByfIL7/IQAlvQwEpnAC7DtLNJCKUoO/w45c44GwCXiAFB/OXAATQryUxdN4LfFiwgjCNYg+kYMIEFkCKDs6PKAIJouyGWMS1FSKJOMRB/BoIxYJIUXFUxNwoIkEKPAgCBZSQHQ1A2EWDfDEUVLyADj5AChSIQW6gu10bE/JG2VnCZGfo4R4d0sdQoBAHhPjhIB94v/wRoRKQWGRHgrhGSQJxCS+0pCZbEhAAOw=="} + ).then(function (reply, rate, err) { + t.deepEqual( + reply, + { + rate: { + limit: null, remaining: null, reset: null + }, + reply: { + errors: [ + { code: 89, message: "Invalid or expired token." } + ], + httpstatus: 200 + } + } + ) + }); +}); diff --git a/test/oauth_tests.js b/test/oauth_tests.js new file mode 100644 index 0000000..7c611b1 --- /dev/null +++ b/test/oauth_tests.js @@ -0,0 +1,105 @@ +const tape = require("tape"), + _test = require("tape-promise"), + test = _test(tape), // decorate tape + CodebirdM = require("./codebirdm"); + +function getCB() { + var cb = new CodebirdM.default; + cb.setConsumerKey("123", "456"); + + return cb; +} + +test("Tests oauth_authenticate Promise", function (t) { + const cb = getCB(); + t.plan(1); + + cb.setToken("123", "456"); + return cb.oauth_authenticate().then(function (a) { + t.deepEqual( + a, + {reply: "https://api.twitter.com/oauth/authenticate?oauth_token=123"} + ) + }); +}); + +test("Tests oauth_authenticate callback", function (t) { + const cb = getCB(); + t.plan(4); + + cb.setToken("123", "456"); + cb.oauth_authenticate({}, function (a) { + t.equal( + a, "https://api.twitter.com/oauth/authenticate?oauth_token=123" + ) + }); + cb.oauth_authenticate({force_login: true}, function (a) { + t.equal( + a, "https://api.twitter.com/oauth/authenticate?oauth_token=123&force_login=1" + ) + }); + cb.oauth_authenticate({force_login: true, screen_name: "TwitterAPI"}, function (a) { + t.equal( + a, "https://api.twitter.com/oauth/authenticate?oauth_token=123&force_login=1&screen_name=TwitterAPI" + ) + }); + cb.oauth_authenticate({screen_name: "TwitterAPI"}, function (a) { + t.equal( + a, "https://api.twitter.com/oauth/authenticate?oauth_token=123&screen_name=TwitterAPI" + ) + }); +}); + +test("Tests oauth_authorize callback", function (t) { + const cb = getCB(); + t.plan(4); + + cb.setToken("123", "456"); + cb.oauth_authorize({}, function (a) { + t.equal( + a, "https://api.twitter.com/oauth/authorize?oauth_token=123" + ) + }); + cb.oauth_authorize({force_login: true}, function (a) { + t.equal( + a, "https://api.twitter.com/oauth/authorize?oauth_token=123&force_login=1" + ) + }); + cb.oauth_authorize({force_login: true, screen_name: "TwitterAPI"}, function (a) { + t.equal( + a, "https://api.twitter.com/oauth/authorize?oauth_token=123&force_login=1&screen_name=TwitterAPI" + ) + }); + cb.oauth_authorize({screen_name: "TwitterAPI"}, function (a) { + t.equal( + a, "https://api.twitter.com/oauth/authorize?oauth_token=123&screen_name=TwitterAPI" + ) + }); +}); + +test("Tests oauth2_token", function (t) { + const cb = getCB(); + t.plan(1); + + cb.oauth2_token( + function (a) { + t.deepEqual( + a, { + token_type: "bearer", + access_token: "VqiO0n2HrKE", + httpstatus: 200 + } + ); + }); +}); + +test("Tests signing of boolean parameters", function (t) { + const cb = getCB(); + + t.equal( + cb.call("_getSignature", ["GET", "friends/ids", ["stringify_ids"], [true]]), + "OFNuMTEnE82pfI0cAdJPgtO4xzY=" + ); + + t.end(); +});