diff --git a/README.md b/README.md index 700916bc..03372e32 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# vue-resource [![npm package](https://img.shields.io/npm/v/vue-resource.svg)](https://www.npmjs.com/package/vue-resource) +# vue-resource [![Downloads](https://img.shields.io/npm/dt/vue-resource.svg)](https://www.npmjs.com/package/vue-resource) [![Version](https://img.shields.io/npm/v/vue-resource.svg)](https://www.npmjs.com/package/vue-resource) [![License](https://img.shields.io/npm/l/vue-resource.svg)](https://www.npmjs.com/package/vue-resource) The plugin for [Vue.js](http://vuejs.org) provides services for making web requests and handle responses using a [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) or JSONP. @@ -7,7 +7,7 @@ The plugin for [Vue.js](http://vuejs.org) provides services for making web reque - Supports the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API and [URI Templates](https://medialize.github.io/URI.js/uri-template.html) - Supports [interceptors](docs/http.md#interceptors) for request and response - Supports latest Firefox, Chrome, Safari, Opera and IE9+ -- Compact size 12KB (4.5KB gzipped) +- Compact size 14KB (5.3KB gzipped) ## Installation @@ -22,9 +22,21 @@ $ bower install vue-resource ``` ### CDN -Available on [jsdelivr](https://cdn.jsdelivr.net/vue.resource/0.9.3/vue-resource.min.js), [cdnjs](https://cdnjs.com/libraries/vue-resource) or [npmcdn](https://npmcdn.com/vue-resource@0.9.3/dist/vue-resource.min.js). +Available on [jsdelivr](https://cdn.jsdelivr.net/vue.resource/1.0.0/vue-resource.min.js), [cdnjs](https://cdnjs.com/libraries/vue-resource) or [npmcdn](https://npmcdn.com/vue-resource@1.0.0/dist/vue-resource.min.js). ```html - + +``` + +## Example +```js +{ + // GET /someUrl + this.$http.get('/someUrl').then((response) => { + // success callback + }, (response) => { + // error callback + }); +} ``` ## Documentation @@ -33,6 +45,7 @@ Available on [jsdelivr](https://cdn.jsdelivr.net/vue.resource/0.9.3/vue-resource - [HTTP Requests/Response](docs/http.md) - [Creating Resources](docs/resource.md) - [Code Recipes](docs/recipes.md) +- [API Reference](docs/api.md) ## Changelog diff --git a/bower.json b/bower.json index cd073e2c..035cef1f 100644 --- a/bower.json +++ b/bower.json @@ -1,10 +1,16 @@ { "name": "vue-resource", "main": "dist/vue-resource.js", - "description": "A web request service for Vue.js", - "version": "0.9.3", + "version": "1.0.0", + "description": "The HTTP client for Vue.js", "homepage": "https://github.com/vuejs/vue-resource", "license": "MIT", + "keywords": [ + "vue", + "xhr", + "http", + "ajax" + ], "ignore": [ ".*", "build", diff --git a/dist/vue-resource.common.js b/dist/vue-resource.common.js index 51e4d79e..97a08f12 100644 --- a/dist/vue-resource.common.js +++ b/dist/vue-resource.common.js @@ -1,5 +1,5 @@ /*! - * vue-resource v0.9.3 + * vue-resource v1.0.0 * https://github.com/vuejs/vue-resource * Released under the MIT License. */ @@ -7,182 +7,10 @@ 'use strict'; /** - * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) + * Promise adapter. */ -var RESOLVED = 0; -var REJECTED = 1; -var PENDING = 2; - -function Promise$2(executor) { - - this.state = PENDING; - this.value = undefined; - this.deferred = []; - - var promise = this; - - try { - executor(function (x) { - promise.resolve(x); - }, function (r) { - promise.reject(r); - }); - } catch (e) { - promise.reject(e); - } -} - -Promise$2.reject = function (r) { - return new Promise$2(function (resolve, reject) { - reject(r); - }); -}; - -Promise$2.resolve = function (x) { - return new Promise$2(function (resolve, reject) { - resolve(x); - }); -}; - -Promise$2.all = function all(iterable) { - return new Promise$2(function (resolve, reject) { - var count = 0, - result = []; - - if (iterable.length === 0) { - resolve(result); - } - - function resolver(i) { - return function (x) { - result[i] = x; - count += 1; - - if (count === iterable.length) { - resolve(result); - } - }; - } - - for (var i = 0; i < iterable.length; i += 1) { - Promise$2.resolve(iterable[i]).then(resolver(i), reject); - } - }); -}; - -Promise$2.race = function race(iterable) { - return new Promise$2(function (resolve, reject) { - for (var i = 0; i < iterable.length; i += 1) { - Promise$2.resolve(iterable[i]).then(resolve, reject); - } - }); -}; - -var p$1 = Promise$2.prototype; - -p$1.resolve = function resolve(x) { - var promise = this; - - if (promise.state === PENDING) { - if (x === promise) { - throw new TypeError('Promise settled with itself.'); - } - - var called = false; - - try { - var then = x && x['then']; - - if (x !== null && typeof x === 'object' && typeof then === 'function') { - then.call(x, function (x) { - if (!called) { - promise.resolve(x); - } - called = true; - }, function (r) { - if (!called) { - promise.reject(r); - } - called = true; - }); - return; - } - } catch (e) { - if (!called) { - promise.reject(e); - } - return; - } - - promise.state = RESOLVED; - promise.value = x; - promise.notify(); - } -}; - -p$1.reject = function reject(reason) { - var promise = this; - - if (promise.state === PENDING) { - if (reason === promise) { - throw new TypeError('Promise settled with itself.'); - } - - promise.state = REJECTED; - promise.value = reason; - promise.notify(); - } -}; - -p$1.notify = function notify() { - var promise = this; - - nextTick(function () { - if (promise.state !== PENDING) { - while (promise.deferred.length) { - var deferred = promise.deferred.shift(), - onResolved = deferred[0], - onRejected = deferred[1], - resolve = deferred[2], - reject = deferred[3]; - - try { - if (promise.state === RESOLVED) { - if (typeof onResolved === 'function') { - resolve(onResolved.call(undefined, promise.value)); - } else { - resolve(promise.value); - } - } else if (promise.state === REJECTED) { - if (typeof onRejected === 'function') { - resolve(onRejected.call(undefined, promise.value)); - } else { - reject(promise.value); - } - } - } catch (e) { - reject(e); - } - } - } - }); -}; - -p$1.then = function then(onResolved, onRejected) { - var promise = this; - - return new Promise$2(function (resolve, reject) { - promise.deferred.push([onResolved, onRejected, resolve, reject]); - promise.notify(); - }); -}; - -p$1.catch = function (onRejected) { - return this.then(undefined, onRejected); -}; - -var PromiseObj = window.Promise || Promise$2; +var PromiseObj = window.Promise; function Promise$1(executor, context) { @@ -251,9 +79,13 @@ p.finally = function (callback) { }); }; -var debug = false; -var util = {}; -var array = []; +/** + * Utility functions. + */ + +var debug = false;var util = {};var slice = [].slice; + + function Util (Vue) { util = Vue.util; debug = Vue.config.debug || !Vue.config.silent; @@ -279,6 +111,14 @@ function trim(str) { return str.replace(/^\s*|\s*$/g, ''); } +function toLower(str) { + return str ? str.toLowerCase() : ''; +} + +function toUpper(str) { + return str ? str.toUpperCase() : ''; +} + var isArray = Array.isArray; function isString(val) { @@ -301,6 +141,10 @@ function isPlainObject(obj) { return isObject(obj) && Object.getPrototypeOf(obj) == Object.prototype; } +function isBlob(obj) { + return typeof Blob !== 'undefined' && obj instanceof Blob; +} + function isFormData(obj) { return typeof FormData !== 'undefined' && obj instanceof FormData; } @@ -331,7 +175,7 @@ function each(obj, iterator) { var i, key; - if (typeof obj.length == 'number') { + if (obj && typeof obj.length == 'number') { for (i = 0; i < obj.length; i++) { iterator.call(obj[i], obj[i], i); } @@ -350,7 +194,7 @@ var assign = Object.assign || _assign; function merge(target) { - var args = array.slice.call(arguments, 1); + var args = slice.call(arguments, 1); args.forEach(function (source) { _merge(target, source, true); @@ -361,7 +205,7 @@ function merge(target) { function defaults(target) { - var args = array.slice.call(arguments, 1); + var args = slice.call(arguments, 1); args.forEach(function (source) { @@ -377,7 +221,7 @@ function defaults(target) { function _assign(target) { - var args = array.slice.call(arguments, 1); + var args = slice.call(arguments, 1); args.forEach(function (source) { _merge(target, source); @@ -402,6 +246,10 @@ function _merge(target, source, deep) { } } +/** + * Root Prefix Transform. + */ + function root (options, next) { var url = next(options); @@ -413,6 +261,10 @@ function root (options, next) { return url; } +/** + * Query Parameter Transform. + */ + function query (options, next) { var urlParams = Object.keys(Url.options.params), @@ -588,6 +440,10 @@ function encodeReserved(str) { }).join(''); } +/** + * URL Template (RFC 6570) Transform. + */ + function template (options) { var variables = [], @@ -728,6 +584,10 @@ function serialize(params, obj, scope) { }); } +/** + * XDomain client (Internet Explorer). + */ + function xdrClient (request) { return new Promise$1(function (resolve) { @@ -756,6 +616,10 @@ function xdrClient (request) { }); } +/** + * CORS Interceptor. + */ + var ORIGIN_URL = Url.parse(location.href); var SUPPORTS_CORS = 'withCredentials' in new XMLHttpRequest(); @@ -784,15 +648,19 @@ function crossOrigin(request) { return requestUrl.protocol !== ORIGIN_URL.protocol || requestUrl.host !== ORIGIN_URL.host; } +/** + * Body Interceptor. + */ + function body (request, next) { if (request.emulateJSON && isPlainObject(request.body)) { request.body = Url.params(request.body); - request.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + request.headers.set('Content-Type', 'application/x-www-form-urlencoded'); } if (isFormData(request.body)) { - delete request.headers['Content-Type']; + request.headers.delete('Content-Type'); } if (isPlainObject(request.body)) { @@ -801,21 +669,39 @@ function body (request, next) { next(function (response) { - var contentType = response.headers['Content-Type']; + Object.defineProperty(response, 'data', { + get: function () { + return this.body; + }, + set: function (body) { + this.body = body; + } + }); + + return response.bodyText ? when(response.text(), function (text) { - if (isString(contentType) && contentType.indexOf('application/json') === 0) { + var type = response.headers.get('Content-Type'); - try { - response.data = response.json(); - } catch (e) { - response.data = null; + if (isString(type) && type.indexOf('application/json') === 0) { + + try { + response.body = JSON.parse(text); + } catch (e) { + response.body = null; + } + } else { + response.body = text; } - } else { - response.data = response.text(); - } + + return response; + }) : response; }); } +/** + * JSONP client. + */ + function jsonpClient (request) { return new Promise$1(function (resolve) { @@ -858,6 +744,10 @@ function jsonpClient (request) { }); } +/** + * JSONP Interceptor. + */ + function jsonp (request, next) { if (request.method == 'JSONP') { @@ -867,11 +757,21 @@ function jsonp (request, next) { next(function (response) { if (request.method == 'JSONP') { - response.data = response.json(); + + return when(response.json(), function (json) { + + response.body = json; + + return response; + }); } }); } +/** + * Before Interceptor. + */ + function before (request, next) { if (isFunction(request.before)) { @@ -888,17 +788,26 @@ function before (request, next) { function method (request, next) { if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { - request.headers['X-HTTP-Method-Override'] = request.method; + request.headers.set('X-HTTP-Method-Override', request.method); request.method = 'POST'; } next(); } +/** + * Header Interceptor. + */ + function header (request, next) { - request.method = request.method.toUpperCase(); - request.headers = assign({}, Http.headers.common, !request.crossOrigin ? Http.headers.custom : {}, Http.headers[request.method.toLowerCase()], request.headers); + var headers = assign({}, Http.headers.common, !request.crossOrigin ? Http.headers.custom : {}, Http.headers[toLower(request.method)]); + + each(headers, function (value, name) { + if (!request.headers.has(name)) { + request.headers.set(name, value); + } + }); next(); } @@ -923,6 +832,10 @@ function timeout (request, next) { }); } +/** + * XMLHttp client. + */ + function xhrClient (request) { return new Promise$1(function (resolve) { @@ -931,8 +844,11 @@ function xhrClient (request) { var response = request.respondWith('response' in xhr ? xhr.response : xhr.responseText, { status: xhr.status === 1223 ? 204 : xhr.status, // IE9 status bug - statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText), - headers: parseHeaders(xhr.getAllResponseHeaders()) + statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText) + }); + + each(trim(xhr.getAllResponseHeaders()).split('\n'), function (row) { + response.headers.append(row.slice(0, row.indexOf(':')), row.slice(row.indexOf(':') + 1)); }); resolve(response); @@ -955,46 +871,25 @@ function xhrClient (request) { } } + if ('responseType' in xhr) { + xhr.responseType = 'blob'; + } + if (request.credentials === true) { xhr.withCredentials = true; } - each(request.headers || {}, function (value, header) { - xhr.setRequestHeader(header, value); + request.headers.forEach(function (value, name) { + xhr.setRequestHeader(name, value); }); xhr.send(request.getBody()); }); } -function parseHeaders(str) { - - var headers = {}, - value, - name, - i; - - each(trim(str).split('\n'), function (row) { - - i = row.indexOf(':'); - name = trim(row.slice(0, i)); - value = trim(row.slice(i + 1)); - - if (headers[name]) { - - if (isArray(headers[name])) { - headers[name].push(value); - } else { - headers[name] = [headers[name], value]; - } - } else { - - headers[name] = value; - } - }); - - return headers; -} +/** + * Base client. + */ function Client (context) { @@ -1066,6 +961,80 @@ var classCallCheck = function (instance, Constructor) { } }; +/** + * HTTP Headers. + */ + +var Headers = function () { + function Headers(headers) { + var _this = this; + + classCallCheck(this, Headers); + + + this.map = {}; + + each(headers, function (value, name) { + return _this.append(name, value); + }); + } + + Headers.prototype.has = function has(name) { + return this.map.hasOwnProperty(normalizeName(name)); + }; + + Headers.prototype.get = function get(name) { + + var list = this.map[normalizeName(name)]; + + return list ? list[0] : null; + }; + + Headers.prototype.getAll = function getAll(name) { + return this.map[normalizeName(name)] || []; + }; + + Headers.prototype.set = function set(name, value) { + this.map[normalizeName(name)] = [trim(value)]; + }; + + Headers.prototype.append = function append(name, value) { + + var list = this.map[normalizeName(name)]; + + if (!list) { + list = this.map[normalizeName(name)] = []; + } + + list.push(trim(value)); + }; + + Headers.prototype.delete = function _delete(name) { + delete this.map[normalizeName(name)]; + }; + + Headers.prototype.forEach = function forEach(callback, thisArg) { + var _this2 = this; + + each(this.map, function (list, name) { + each(list, function (value) { + return callback.call(thisArg, value, name, _this2); + }); + }); + }; + + return Headers; +}(); + +function normalizeName(name) { + + if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { + throw new TypeError('Invalid character in header field name'); + } + + return toLower(trim(name)); +} + /** * HTTP Response. */ @@ -1080,39 +1049,74 @@ var Response = function () { this.url = url; - this.body = body; - this.headers = headers || {}; + this.ok = status >= 200 && status < 300; this.status = status || 0; this.statusText = statusText || ''; - this.ok = status >= 200 && status < 300; + this.headers = new Headers(headers); + this.body = body; + + if (isString(body)) { + + this.bodyText = body; + } else if (isBlob(body)) { + + this.bodyBlob = body; + + if (isBlobText(body)) { + this.bodyText = blobText(body); + } + } } - Response.prototype.text = function text() { - return this.body; + Response.prototype.blob = function blob() { + return when(this.bodyBlob); }; - Response.prototype.blob = function blob() { - return new Blob([this.body]); + Response.prototype.text = function text() { + return when(this.bodyText); }; Response.prototype.json = function json() { - return JSON.parse(this.body); + return when(this.text(), function (text) { + return JSON.parse(text); + }); }; return Response; }(); +function blobText(body) { + return new Promise$1(function (resolve) { + + var reader = new FileReader(); + + reader.readAsText(body); + reader.onload = function () { + resolve(reader.result); + }; + }); +} + +function isBlobText(body) { + return body.type.indexOf('text') === 0 || body.type.indexOf('json') !== -1; +} + +/** + * HTTP Request. + */ + var Request = function () { function Request(options) { classCallCheck(this, Request); - this.method = 'GET'; this.body = null; this.params = {}; - this.headers = {}; - assign(this, options); + assign(this, options, { + method: toUpper(options.method || 'GET'), + headers: new Headers(options.headers) + }); } Request.prototype.getUrl = function getUrl() { @@ -1189,6 +1193,186 @@ Http.interceptors = [before, timeout, method, body, jsonp, header, cors]; }; }); +/** + * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) + */ + +var RESOLVED = 0; +var REJECTED = 1; +var PENDING = 2; + +function Promise$2(executor) { + + this.state = PENDING; + this.value = undefined; + this.deferred = []; + + var promise = this; + + try { + executor(function (x) { + promise.resolve(x); + }, function (r) { + promise.reject(r); + }); + } catch (e) { + promise.reject(e); + } +} + +Promise$2.reject = function (r) { + return new Promise$2(function (resolve, reject) { + reject(r); + }); +}; + +Promise$2.resolve = function (x) { + return new Promise$2(function (resolve, reject) { + resolve(x); + }); +}; + +Promise$2.all = function all(iterable) { + return new Promise$2(function (resolve, reject) { + var count = 0, + result = []; + + if (iterable.length === 0) { + resolve(result); + } + + function resolver(i) { + return function (x) { + result[i] = x; + count += 1; + + if (count === iterable.length) { + resolve(result); + } + }; + } + + for (var i = 0; i < iterable.length; i += 1) { + Promise$2.resolve(iterable[i]).then(resolver(i), reject); + } + }); +}; + +Promise$2.race = function race(iterable) { + return new Promise$2(function (resolve, reject) { + for (var i = 0; i < iterable.length; i += 1) { + Promise$2.resolve(iterable[i]).then(resolve, reject); + } + }); +}; + +var p$1 = Promise$2.prototype; + +p$1.resolve = function resolve(x) { + var promise = this; + + if (promise.state === PENDING) { + if (x === promise) { + throw new TypeError('Promise settled with itself.'); + } + + var called = false; + + try { + var then = x && x['then']; + + if (x !== null && typeof x === 'object' && typeof then === 'function') { + then.call(x, function (x) { + if (!called) { + promise.resolve(x); + } + called = true; + }, function (r) { + if (!called) { + promise.reject(r); + } + called = true; + }); + return; + } + } catch (e) { + if (!called) { + promise.reject(e); + } + return; + } + + promise.state = RESOLVED; + promise.value = x; + promise.notify(); + } +}; + +p$1.reject = function reject(reason) { + var promise = this; + + if (promise.state === PENDING) { + if (reason === promise) { + throw new TypeError('Promise settled with itself.'); + } + + promise.state = REJECTED; + promise.value = reason; + promise.notify(); + } +}; + +p$1.notify = function notify() { + var promise = this; + + nextTick(function () { + if (promise.state !== PENDING) { + while (promise.deferred.length) { + var deferred = promise.deferred.shift(), + onResolved = deferred[0], + onRejected = deferred[1], + resolve = deferred[2], + reject = deferred[3]; + + try { + if (promise.state === RESOLVED) { + if (typeof onResolved === 'function') { + resolve(onResolved.call(undefined, promise.value)); + } else { + resolve(promise.value); + } + } else if (promise.state === REJECTED) { + if (typeof onRejected === 'function') { + resolve(onRejected.call(undefined, promise.value)); + } else { + reject(promise.value); + } + } + } catch (e) { + reject(e); + } + } + } + }); +}; + +p$1.then = function then(onResolved, onRejected) { + var promise = this; + + return new Promise$2(function (resolve, reject) { + promise.deferred.push([onResolved, onRejected, resolve, reject]); + promise.notify(); + }); +}; + +p$1.catch = function (onRejected) { + return this.then(undefined, onRejected); +}; + +/** + * Service for interacting with RESTful services. + */ + function Resource(url, params, actions, options) { var self = this || {}, @@ -1198,7 +1382,7 @@ function Resource(url, params, actions, options) { each(actions, function (action, name) { - action = merge({ url: url, params: params || {} }, options, action); + action = merge({ url: url, params: assign({}, params) }, options, action); resource[name] = function () { return (self.$http || Http)(opts(action, arguments)); @@ -1259,6 +1443,10 @@ Resource.actions = { }; +/** + * Install plugin. + */ + function plugin(Vue) { if (plugin.installed) { @@ -1305,8 +1493,15 @@ function plugin(Vue) { }); } -if (typeof window !== 'undefined' && window.Vue) { - window.Vue.use(plugin); +if (typeof window !== 'undefined') { + + if (!window.Promise) { + window.Promise = Promise$2; + } + + if (window.Vue) { + window.Vue.use(plugin); + } } module.exports = plugin; \ No newline at end of file diff --git a/dist/vue-resource.es2015.js b/dist/vue-resource.es2015.js index bfc12498..e2aa1f7b 100644 --- a/dist/vue-resource.es2015.js +++ b/dist/vue-resource.es2015.js @@ -1,186 +1,14 @@ /*! - * vue-resource v0.9.3 + * vue-resource v1.0.0 * https://github.com/vuejs/vue-resource * Released under the MIT License. */ /** - * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) + * Promise adapter. */ -var RESOLVED = 0; -var REJECTED = 1; -var PENDING = 2; - -function Promise$2(executor) { - - this.state = PENDING; - this.value = undefined; - this.deferred = []; - - var promise = this; - - try { - executor(function (x) { - promise.resolve(x); - }, function (r) { - promise.reject(r); - }); - } catch (e) { - promise.reject(e); - } -} - -Promise$2.reject = function (r) { - return new Promise$2(function (resolve, reject) { - reject(r); - }); -}; - -Promise$2.resolve = function (x) { - return new Promise$2(function (resolve, reject) { - resolve(x); - }); -}; - -Promise$2.all = function all(iterable) { - return new Promise$2(function (resolve, reject) { - var count = 0, - result = []; - - if (iterable.length === 0) { - resolve(result); - } - - function resolver(i) { - return function (x) { - result[i] = x; - count += 1; - - if (count === iterable.length) { - resolve(result); - } - }; - } - - for (var i = 0; i < iterable.length; i += 1) { - Promise$2.resolve(iterable[i]).then(resolver(i), reject); - } - }); -}; - -Promise$2.race = function race(iterable) { - return new Promise$2(function (resolve, reject) { - for (var i = 0; i < iterable.length; i += 1) { - Promise$2.resolve(iterable[i]).then(resolve, reject); - } - }); -}; - -var p$1 = Promise$2.prototype; - -p$1.resolve = function resolve(x) { - var promise = this; - - if (promise.state === PENDING) { - if (x === promise) { - throw new TypeError('Promise settled with itself.'); - } - - var called = false; - - try { - var then = x && x['then']; - - if (x !== null && typeof x === 'object' && typeof then === 'function') { - then.call(x, function (x) { - if (!called) { - promise.resolve(x); - } - called = true; - }, function (r) { - if (!called) { - promise.reject(r); - } - called = true; - }); - return; - } - } catch (e) { - if (!called) { - promise.reject(e); - } - return; - } - - promise.state = RESOLVED; - promise.value = x; - promise.notify(); - } -}; - -p$1.reject = function reject(reason) { - var promise = this; - - if (promise.state === PENDING) { - if (reason === promise) { - throw new TypeError('Promise settled with itself.'); - } - - promise.state = REJECTED; - promise.value = reason; - promise.notify(); - } -}; - -p$1.notify = function notify() { - var promise = this; - - nextTick(function () { - if (promise.state !== PENDING) { - while (promise.deferred.length) { - var deferred = promise.deferred.shift(), - onResolved = deferred[0], - onRejected = deferred[1], - resolve = deferred[2], - reject = deferred[3]; - - try { - if (promise.state === RESOLVED) { - if (typeof onResolved === 'function') { - resolve(onResolved.call(undefined, promise.value)); - } else { - resolve(promise.value); - } - } else if (promise.state === REJECTED) { - if (typeof onRejected === 'function') { - resolve(onRejected.call(undefined, promise.value)); - } else { - reject(promise.value); - } - } - } catch (e) { - reject(e); - } - } - } - }); -}; - -p$1.then = function then(onResolved, onRejected) { - var promise = this; - - return new Promise$2(function (resolve, reject) { - promise.deferred.push([onResolved, onRejected, resolve, reject]); - promise.notify(); - }); -}; - -p$1.catch = function (onRejected) { - return this.then(undefined, onRejected); -}; - -var PromiseObj = window.Promise || Promise$2; +var PromiseObj = window.Promise; function Promise$1(executor, context) { @@ -249,9 +77,13 @@ p.finally = function (callback) { }); }; -var debug = false; -var util = {}; -var array = []; +/** + * Utility functions. + */ + +var debug = false;var util = {};var slice = [].slice; + + function Util (Vue) { util = Vue.util; debug = Vue.config.debug || !Vue.config.silent; @@ -277,6 +109,14 @@ function trim(str) { return str.replace(/^\s*|\s*$/g, ''); } +function toLower(str) { + return str ? str.toLowerCase() : ''; +} + +function toUpper(str) { + return str ? str.toUpperCase() : ''; +} + var isArray = Array.isArray; function isString(val) { @@ -299,6 +139,10 @@ function isPlainObject(obj) { return isObject(obj) && Object.getPrototypeOf(obj) == Object.prototype; } +function isBlob(obj) { + return typeof Blob !== 'undefined' && obj instanceof Blob; +} + function isFormData(obj) { return typeof FormData !== 'undefined' && obj instanceof FormData; } @@ -329,7 +173,7 @@ function each(obj, iterator) { var i, key; - if (typeof obj.length == 'number') { + if (obj && typeof obj.length == 'number') { for (i = 0; i < obj.length; i++) { iterator.call(obj[i], obj[i], i); } @@ -348,7 +192,7 @@ var assign = Object.assign || _assign; function merge(target) { - var args = array.slice.call(arguments, 1); + var args = slice.call(arguments, 1); args.forEach(function (source) { _merge(target, source, true); @@ -359,7 +203,7 @@ function merge(target) { function defaults(target) { - var args = array.slice.call(arguments, 1); + var args = slice.call(arguments, 1); args.forEach(function (source) { @@ -375,7 +219,7 @@ function defaults(target) { function _assign(target) { - var args = array.slice.call(arguments, 1); + var args = slice.call(arguments, 1); args.forEach(function (source) { _merge(target, source); @@ -400,6 +244,10 @@ function _merge(target, source, deep) { } } +/** + * Root Prefix Transform. + */ + function root (options, next) { var url = next(options); @@ -411,6 +259,10 @@ function root (options, next) { return url; } +/** + * Query Parameter Transform. + */ + function query (options, next) { var urlParams = Object.keys(Url.options.params), @@ -586,6 +438,10 @@ function encodeReserved(str) { }).join(''); } +/** + * URL Template (RFC 6570) Transform. + */ + function template (options) { var variables = [], @@ -726,6 +582,10 @@ function serialize(params, obj, scope) { }); } +/** + * XDomain client (Internet Explorer). + */ + function xdrClient (request) { return new Promise$1(function (resolve) { @@ -754,6 +614,10 @@ function xdrClient (request) { }); } +/** + * CORS Interceptor. + */ + var ORIGIN_URL = Url.parse(location.href); var SUPPORTS_CORS = 'withCredentials' in new XMLHttpRequest(); @@ -782,15 +646,19 @@ function crossOrigin(request) { return requestUrl.protocol !== ORIGIN_URL.protocol || requestUrl.host !== ORIGIN_URL.host; } +/** + * Body Interceptor. + */ + function body (request, next) { if (request.emulateJSON && isPlainObject(request.body)) { request.body = Url.params(request.body); - request.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + request.headers.set('Content-Type', 'application/x-www-form-urlencoded'); } if (isFormData(request.body)) { - delete request.headers['Content-Type']; + request.headers.delete('Content-Type'); } if (isPlainObject(request.body)) { @@ -799,21 +667,39 @@ function body (request, next) { next(function (response) { - var contentType = response.headers['Content-Type']; + Object.defineProperty(response, 'data', { + get: function () { + return this.body; + }, + set: function (body) { + this.body = body; + } + }); + + return response.bodyText ? when(response.text(), function (text) { - if (isString(contentType) && contentType.indexOf('application/json') === 0) { + var type = response.headers.get('Content-Type'); - try { - response.data = response.json(); - } catch (e) { - response.data = null; + if (isString(type) && type.indexOf('application/json') === 0) { + + try { + response.body = JSON.parse(text); + } catch (e) { + response.body = null; + } + } else { + response.body = text; } - } else { - response.data = response.text(); - } + + return response; + }) : response; }); } +/** + * JSONP client. + */ + function jsonpClient (request) { return new Promise$1(function (resolve) { @@ -856,6 +742,10 @@ function jsonpClient (request) { }); } +/** + * JSONP Interceptor. + */ + function jsonp (request, next) { if (request.method == 'JSONP') { @@ -865,11 +755,21 @@ function jsonp (request, next) { next(function (response) { if (request.method == 'JSONP') { - response.data = response.json(); + + return when(response.json(), function (json) { + + response.body = json; + + return response; + }); } }); } +/** + * Before Interceptor. + */ + function before (request, next) { if (isFunction(request.before)) { @@ -886,17 +786,26 @@ function before (request, next) { function method (request, next) { if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { - request.headers['X-HTTP-Method-Override'] = request.method; + request.headers.set('X-HTTP-Method-Override', request.method); request.method = 'POST'; } next(); } +/** + * Header Interceptor. + */ + function header (request, next) { - request.method = request.method.toUpperCase(); - request.headers = assign({}, Http.headers.common, !request.crossOrigin ? Http.headers.custom : {}, Http.headers[request.method.toLowerCase()], request.headers); + var headers = assign({}, Http.headers.common, !request.crossOrigin ? Http.headers.custom : {}, Http.headers[toLower(request.method)]); + + each(headers, function (value, name) { + if (!request.headers.has(name)) { + request.headers.set(name, value); + } + }); next(); } @@ -921,6 +830,10 @@ function timeout (request, next) { }); } +/** + * XMLHttp client. + */ + function xhrClient (request) { return new Promise$1(function (resolve) { @@ -929,8 +842,11 @@ function xhrClient (request) { var response = request.respondWith('response' in xhr ? xhr.response : xhr.responseText, { status: xhr.status === 1223 ? 204 : xhr.status, // IE9 status bug - statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText), - headers: parseHeaders(xhr.getAllResponseHeaders()) + statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText) + }); + + each(trim(xhr.getAllResponseHeaders()).split('\n'), function (row) { + response.headers.append(row.slice(0, row.indexOf(':')), row.slice(row.indexOf(':') + 1)); }); resolve(response); @@ -953,46 +869,25 @@ function xhrClient (request) { } } + if ('responseType' in xhr) { + xhr.responseType = 'blob'; + } + if (request.credentials === true) { xhr.withCredentials = true; } - each(request.headers || {}, function (value, header) { - xhr.setRequestHeader(header, value); + request.headers.forEach(function (value, name) { + xhr.setRequestHeader(name, value); }); xhr.send(request.getBody()); }); } -function parseHeaders(str) { - - var headers = {}, - value, - name, - i; - - each(trim(str).split('\n'), function (row) { - - i = row.indexOf(':'); - name = trim(row.slice(0, i)); - value = trim(row.slice(i + 1)); - - if (headers[name]) { - - if (isArray(headers[name])) { - headers[name].push(value); - } else { - headers[name] = [headers[name], value]; - } - } else { - - headers[name] = value; - } - }); - - return headers; -} +/** + * Base client. + */ function Client (context) { @@ -1064,6 +959,80 @@ var classCallCheck = function (instance, Constructor) { } }; +/** + * HTTP Headers. + */ + +var Headers = function () { + function Headers(headers) { + var _this = this; + + classCallCheck(this, Headers); + + + this.map = {}; + + each(headers, function (value, name) { + return _this.append(name, value); + }); + } + + Headers.prototype.has = function has(name) { + return this.map.hasOwnProperty(normalizeName(name)); + }; + + Headers.prototype.get = function get(name) { + + var list = this.map[normalizeName(name)]; + + return list ? list[0] : null; + }; + + Headers.prototype.getAll = function getAll(name) { + return this.map[normalizeName(name)] || []; + }; + + Headers.prototype.set = function set(name, value) { + this.map[normalizeName(name)] = [trim(value)]; + }; + + Headers.prototype.append = function append(name, value) { + + var list = this.map[normalizeName(name)]; + + if (!list) { + list = this.map[normalizeName(name)] = []; + } + + list.push(trim(value)); + }; + + Headers.prototype.delete = function _delete(name) { + delete this.map[normalizeName(name)]; + }; + + Headers.prototype.forEach = function forEach(callback, thisArg) { + var _this2 = this; + + each(this.map, function (list, name) { + each(list, function (value) { + return callback.call(thisArg, value, name, _this2); + }); + }); + }; + + return Headers; +}(); + +function normalizeName(name) { + + if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { + throw new TypeError('Invalid character in header field name'); + } + + return toLower(trim(name)); +} + /** * HTTP Response. */ @@ -1078,39 +1047,74 @@ var Response = function () { this.url = url; - this.body = body; - this.headers = headers || {}; + this.ok = status >= 200 && status < 300; this.status = status || 0; this.statusText = statusText || ''; - this.ok = status >= 200 && status < 300; + this.headers = new Headers(headers); + this.body = body; + + if (isString(body)) { + + this.bodyText = body; + } else if (isBlob(body)) { + + this.bodyBlob = body; + + if (isBlobText(body)) { + this.bodyText = blobText(body); + } + } } - Response.prototype.text = function text() { - return this.body; + Response.prototype.blob = function blob() { + return when(this.bodyBlob); }; - Response.prototype.blob = function blob() { - return new Blob([this.body]); + Response.prototype.text = function text() { + return when(this.bodyText); }; Response.prototype.json = function json() { - return JSON.parse(this.body); + return when(this.text(), function (text) { + return JSON.parse(text); + }); }; return Response; }(); +function blobText(body) { + return new Promise$1(function (resolve) { + + var reader = new FileReader(); + + reader.readAsText(body); + reader.onload = function () { + resolve(reader.result); + }; + }); +} + +function isBlobText(body) { + return body.type.indexOf('text') === 0 || body.type.indexOf('json') !== -1; +} + +/** + * HTTP Request. + */ + var Request = function () { function Request(options) { classCallCheck(this, Request); - this.method = 'GET'; this.body = null; this.params = {}; - this.headers = {}; - assign(this, options); + assign(this, options, { + method: toUpper(options.method || 'GET'), + headers: new Headers(options.headers) + }); } Request.prototype.getUrl = function getUrl() { @@ -1187,6 +1191,186 @@ Http.interceptors = [before, timeout, method, body, jsonp, header, cors]; }; }); +/** + * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) + */ + +var RESOLVED = 0; +var REJECTED = 1; +var PENDING = 2; + +function Promise$2(executor) { + + this.state = PENDING; + this.value = undefined; + this.deferred = []; + + var promise = this; + + try { + executor(function (x) { + promise.resolve(x); + }, function (r) { + promise.reject(r); + }); + } catch (e) { + promise.reject(e); + } +} + +Promise$2.reject = function (r) { + return new Promise$2(function (resolve, reject) { + reject(r); + }); +}; + +Promise$2.resolve = function (x) { + return new Promise$2(function (resolve, reject) { + resolve(x); + }); +}; + +Promise$2.all = function all(iterable) { + return new Promise$2(function (resolve, reject) { + var count = 0, + result = []; + + if (iterable.length === 0) { + resolve(result); + } + + function resolver(i) { + return function (x) { + result[i] = x; + count += 1; + + if (count === iterable.length) { + resolve(result); + } + }; + } + + for (var i = 0; i < iterable.length; i += 1) { + Promise$2.resolve(iterable[i]).then(resolver(i), reject); + } + }); +}; + +Promise$2.race = function race(iterable) { + return new Promise$2(function (resolve, reject) { + for (var i = 0; i < iterable.length; i += 1) { + Promise$2.resolve(iterable[i]).then(resolve, reject); + } + }); +}; + +var p$1 = Promise$2.prototype; + +p$1.resolve = function resolve(x) { + var promise = this; + + if (promise.state === PENDING) { + if (x === promise) { + throw new TypeError('Promise settled with itself.'); + } + + var called = false; + + try { + var then = x && x['then']; + + if (x !== null && typeof x === 'object' && typeof then === 'function') { + then.call(x, function (x) { + if (!called) { + promise.resolve(x); + } + called = true; + }, function (r) { + if (!called) { + promise.reject(r); + } + called = true; + }); + return; + } + } catch (e) { + if (!called) { + promise.reject(e); + } + return; + } + + promise.state = RESOLVED; + promise.value = x; + promise.notify(); + } +}; + +p$1.reject = function reject(reason) { + var promise = this; + + if (promise.state === PENDING) { + if (reason === promise) { + throw new TypeError('Promise settled with itself.'); + } + + promise.state = REJECTED; + promise.value = reason; + promise.notify(); + } +}; + +p$1.notify = function notify() { + var promise = this; + + nextTick(function () { + if (promise.state !== PENDING) { + while (promise.deferred.length) { + var deferred = promise.deferred.shift(), + onResolved = deferred[0], + onRejected = deferred[1], + resolve = deferred[2], + reject = deferred[3]; + + try { + if (promise.state === RESOLVED) { + if (typeof onResolved === 'function') { + resolve(onResolved.call(undefined, promise.value)); + } else { + resolve(promise.value); + } + } else if (promise.state === REJECTED) { + if (typeof onRejected === 'function') { + resolve(onRejected.call(undefined, promise.value)); + } else { + reject(promise.value); + } + } + } catch (e) { + reject(e); + } + } + } + }); +}; + +p$1.then = function then(onResolved, onRejected) { + var promise = this; + + return new Promise$2(function (resolve, reject) { + promise.deferred.push([onResolved, onRejected, resolve, reject]); + promise.notify(); + }); +}; + +p$1.catch = function (onRejected) { + return this.then(undefined, onRejected); +}; + +/** + * Service for interacting with RESTful services. + */ + function Resource(url, params, actions, options) { var self = this || {}, @@ -1196,7 +1380,7 @@ function Resource(url, params, actions, options) { each(actions, function (action, name) { - action = merge({ url: url, params: params || {} }, options, action); + action = merge({ url: url, params: assign({}, params) }, options, action); resource[name] = function () { return (self.$http || Http)(opts(action, arguments)); @@ -1257,6 +1441,10 @@ Resource.actions = { }; +/** + * Install plugin. + */ + function plugin(Vue) { if (plugin.installed) { @@ -1303,8 +1491,15 @@ function plugin(Vue) { }); } -if (typeof window !== 'undefined' && window.Vue) { - window.Vue.use(plugin); +if (typeof window !== 'undefined') { + + if (!window.Promise) { + window.Promise = Promise$2; + } + + if (window.Vue) { + window.Vue.use(plugin); + } } export default plugin; diff --git a/dist/vue-resource.js b/dist/vue-resource.js index d7981dbe..0c09255f 100644 --- a/dist/vue-resource.js +++ b/dist/vue-resource.js @@ -1,5 +1,5 @@ /*! - * vue-resource v0.9.3 + * vue-resource v1.0.0 * https://github.com/vuejs/vue-resource * Released under the MIT License. */ @@ -8,1311 +8,1506 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.VueResource = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; - /** - * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) - */ +/** + * Promise adapter. + */ - var RESOLVED = 0; - var REJECTED = 1; - var PENDING = 2; +var PromiseObj = window.Promise; - function Promise$2(executor) { +function Promise$1(executor, context) { - this.state = PENDING; - this.value = undefined; - this.deferred = []; + if (executor instanceof PromiseObj) { + this.promise = executor; + } else { + this.promise = new PromiseObj(executor.bind(context)); + } - var promise = this; + this.context = context; +} - try { - executor(function (x) { - promise.resolve(x); - }, function (r) { - promise.reject(r); - }); - } catch (e) { - promise.reject(e); - } - } +Promise$1.all = function (iterable, context) { + return new Promise$1(PromiseObj.all(iterable), context); +}; - Promise$2.reject = function (r) { - return new Promise$2(function (resolve, reject) { - reject(r); - }); - }; - - Promise$2.resolve = function (x) { - return new Promise$2(function (resolve, reject) { - resolve(x); - }); - }; - - Promise$2.all = function all(iterable) { - return new Promise$2(function (resolve, reject) { - var count = 0, - result = []; - - if (iterable.length === 0) { - resolve(result); - } - - function resolver(i) { - return function (x) { - result[i] = x; - count += 1; - - if (count === iterable.length) { - resolve(result); - } - }; - } - - for (var i = 0; i < iterable.length; i += 1) { - Promise$2.resolve(iterable[i]).then(resolver(i), reject); - } - }); - }; - - Promise$2.race = function race(iterable) { - return new Promise$2(function (resolve, reject) { - for (var i = 0; i < iterable.length; i += 1) { - Promise$2.resolve(iterable[i]).then(resolve, reject); - } - }); - }; - - var p$1 = Promise$2.prototype; - - p$1.resolve = function resolve(x) { - var promise = this; - - if (promise.state === PENDING) { - if (x === promise) { - throw new TypeError('Promise settled with itself.'); - } - - var called = false; - - try { - var then = x && x['then']; - - if (x !== null && typeof x === 'object' && typeof then === 'function') { - then.call(x, function (x) { - if (!called) { - promise.resolve(x); - } - called = true; - }, function (r) { - if (!called) { - promise.reject(r); - } - called = true; - }); - return; - } - } catch (e) { - if (!called) { - promise.reject(e); - } - return; - } - - promise.state = RESOLVED; - promise.value = x; - promise.notify(); - } - }; - - p$1.reject = function reject(reason) { - var promise = this; - - if (promise.state === PENDING) { - if (reason === promise) { - throw new TypeError('Promise settled with itself.'); - } - - promise.state = REJECTED; - promise.value = reason; - promise.notify(); - } - }; - - p$1.notify = function notify() { - var promise = this; - - nextTick(function () { - if (promise.state !== PENDING) { - while (promise.deferred.length) { - var deferred = promise.deferred.shift(), - onResolved = deferred[0], - onRejected = deferred[1], - resolve = deferred[2], - reject = deferred[3]; - - try { - if (promise.state === RESOLVED) { - if (typeof onResolved === 'function') { - resolve(onResolved.call(undefined, promise.value)); - } else { - resolve(promise.value); - } - } else if (promise.state === REJECTED) { - if (typeof onRejected === 'function') { - resolve(onRejected.call(undefined, promise.value)); - } else { - reject(promise.value); - } - } - } catch (e) { - reject(e); - } - } - } - }); - }; - - p$1.then = function then(onResolved, onRejected) { - var promise = this; - - return new Promise$2(function (resolve, reject) { - promise.deferred.push([onResolved, onRejected, resolve, reject]); - promise.notify(); - }); - }; - - p$1.catch = function (onRejected) { - return this.then(undefined, onRejected); - }; - - var PromiseObj = window.Promise || Promise$2; - - function Promise$1(executor, context) { - - if (executor instanceof PromiseObj) { - this.promise = executor; - } else { - this.promise = new PromiseObj(executor.bind(context)); - } - - this.context = context; - } +Promise$1.resolve = function (value, context) { + return new Promise$1(PromiseObj.resolve(value), context); +}; - Promise$1.all = function (iterable, context) { - return new Promise$1(PromiseObj.all(iterable), context); - }; +Promise$1.reject = function (reason, context) { + return new Promise$1(PromiseObj.reject(reason), context); +}; - Promise$1.resolve = function (value, context) { - return new Promise$1(PromiseObj.resolve(value), context); - }; +Promise$1.race = function (iterable, context) { + return new Promise$1(PromiseObj.race(iterable), context); +}; - Promise$1.reject = function (reason, context) { - return new Promise$1(PromiseObj.reject(reason), context); - }; +var p = Promise$1.prototype; - Promise$1.race = function (iterable, context) { - return new Promise$1(PromiseObj.race(iterable), context); - }; +p.bind = function (context) { + this.context = context; + return this; +}; - var p = Promise$1.prototype; +p.then = function (fulfilled, rejected) { - p.bind = function (context) { - this.context = context; - return this; - }; + if (fulfilled && fulfilled.bind && this.context) { + fulfilled = fulfilled.bind(this.context); + } - p.then = function (fulfilled, rejected) { + if (rejected && rejected.bind && this.context) { + rejected = rejected.bind(this.context); + } - if (fulfilled && fulfilled.bind && this.context) { - fulfilled = fulfilled.bind(this.context); - } + return new Promise$1(this.promise.then(fulfilled, rejected), this.context); +}; - if (rejected && rejected.bind && this.context) { - rejected = rejected.bind(this.context); - } +p.catch = function (rejected) { - return new Promise$1(this.promise.then(fulfilled, rejected), this.context); - }; + if (rejected && rejected.bind && this.context) { + rejected = rejected.bind(this.context); + } - p.catch = function (rejected) { + return new Promise$1(this.promise.catch(rejected), this.context); +}; - if (rejected && rejected.bind && this.context) { - rejected = rejected.bind(this.context); - } +p.finally = function (callback) { - return new Promise$1(this.promise.catch(rejected), this.context); - }; + return this.then(function (value) { + callback.call(this); + return value; + }, function (reason) { + callback.call(this); + return PromiseObj.reject(reason); + }); +}; - p.finally = function (callback) { +/** + * Utility functions. + */ - return this.then(function (value) { - callback.call(this); - return value; - }, function (reason) { - callback.call(this); - return PromiseObj.reject(reason); - }); - }; +var debug = false;var util = {};var slice = [].slice; - var debug = false; - var util = {}; - var array = []; - function Util (Vue) { - util = Vue.util; - debug = Vue.config.debug || !Vue.config.silent; - } - function warn(msg) { - if (typeof console !== 'undefined' && debug) { - console.warn('[VueResource warn]: ' + msg); - } - } +function Util (Vue) { + util = Vue.util; + debug = Vue.config.debug || !Vue.config.silent; +} - function error(msg) { - if (typeof console !== 'undefined') { - console.error(msg); - } - } +function warn(msg) { + if (typeof console !== 'undefined' && debug) { + console.warn('[VueResource warn]: ' + msg); + } +} - function nextTick(cb, ctx) { - return util.nextTick(cb, ctx); - } +function error(msg) { + if (typeof console !== 'undefined') { + console.error(msg); + } +} - function trim(str) { - return str.replace(/^\s*|\s*$/g, ''); - } +function nextTick(cb, ctx) { + return util.nextTick(cb, ctx); +} - var isArray = Array.isArray; +function trim(str) { + return str.replace(/^\s*|\s*$/g, ''); +} - function isString(val) { - return typeof val === 'string'; - } +function toLower(str) { + return str ? str.toLowerCase() : ''; +} - function isBoolean(val) { - return val === true || val === false; - } +function toUpper(str) { + return str ? str.toUpperCase() : ''; +} - function isFunction(val) { - return typeof val === 'function'; - } +var isArray = Array.isArray; - function isObject(obj) { - return obj !== null && typeof obj === 'object'; - } +function isString(val) { + return typeof val === 'string'; +} - function isPlainObject(obj) { - return isObject(obj) && Object.getPrototypeOf(obj) == Object.prototype; - } +function isBoolean(val) { + return val === true || val === false; +} - function isFormData(obj) { - return typeof FormData !== 'undefined' && obj instanceof FormData; - } +function isFunction(val) { + return typeof val === 'function'; +} - function when(value, fulfilled, rejected) { +function isObject(obj) { + return obj !== null && typeof obj === 'object'; +} - var promise = Promise$1.resolve(value); +function isPlainObject(obj) { + return isObject(obj) && Object.getPrototypeOf(obj) == Object.prototype; +} - if (arguments.length < 2) { - return promise; - } +function isBlob(obj) { + return typeof Blob !== 'undefined' && obj instanceof Blob; +} - return promise.then(fulfilled, rejected); - } +function isFormData(obj) { + return typeof FormData !== 'undefined' && obj instanceof FormData; +} - function options(fn, obj, opts) { +function when(value, fulfilled, rejected) { - opts = opts || {}; + var promise = Promise$1.resolve(value); - if (isFunction(opts)) { - opts = opts.call(obj); - } + if (arguments.length < 2) { + return promise; + } - return merge(fn.bind({ $vm: obj, $options: opts }), fn, { $options: opts }); - } + return promise.then(fulfilled, rejected); +} - function each(obj, iterator) { +function options(fn, obj, opts) { - var i, key; + opts = opts || {}; - if (typeof obj.length == 'number') { - for (i = 0; i < obj.length; i++) { - iterator.call(obj[i], obj[i], i); - } - } else if (isObject(obj)) { - for (key in obj) { - if (obj.hasOwnProperty(key)) { - iterator.call(obj[key], obj[key], key); - } - } - } + if (isFunction(opts)) { + opts = opts.call(obj); + } - return obj; - } + return merge(fn.bind({ $vm: obj, $options: opts }), fn, { $options: opts }); +} - var assign = Object.assign || _assign; +function each(obj, iterator) { - function merge(target) { + var i, key; - var args = array.slice.call(arguments, 1); + if (obj && typeof obj.length == 'number') { + for (i = 0; i < obj.length; i++) { + iterator.call(obj[i], obj[i], i); + } + } else if (isObject(obj)) { + for (key in obj) { + if (obj.hasOwnProperty(key)) { + iterator.call(obj[key], obj[key], key); + } + } + } - args.forEach(function (source) { - _merge(target, source, true); - }); + return obj; +} - return target; - } +var assign = Object.assign || _assign; - function defaults(target) { +function merge(target) { - var args = array.slice.call(arguments, 1); + var args = slice.call(arguments, 1); - args.forEach(function (source) { + args.forEach(function (source) { + _merge(target, source, true); + }); - for (var key in source) { - if (target[key] === undefined) { - target[key] = source[key]; - } - } - }); + return target; +} - return target; - } +function defaults(target) { - function _assign(target) { + var args = slice.call(arguments, 1); - var args = array.slice.call(arguments, 1); + args.forEach(function (source) { - args.forEach(function (source) { - _merge(target, source); - }); + for (var key in source) { + if (target[key] === undefined) { + target[key] = source[key]; + } + } + }); - return target; - } + return target; +} - function _merge(target, source, deep) { - for (var key in source) { - if (deep && (isPlainObject(source[key]) || isArray(source[key]))) { - if (isPlainObject(source[key]) && !isPlainObject(target[key])) { - target[key] = {}; - } - if (isArray(source[key]) && !isArray(target[key])) { - target[key] = []; - } - _merge(target[key], source[key], deep); - } else if (source[key] !== undefined) { - target[key] = source[key]; - } - } - } +function _assign(target) { - function root (options, next) { + var args = slice.call(arguments, 1); - var url = next(options); + args.forEach(function (source) { + _merge(target, source); + }); - if (isString(options.root) && !url.match(/^(https?:)?\//)) { - url = options.root + '/' + url; - } + return target; +} - return url; - } +function _merge(target, source, deep) { + for (var key in source) { + if (deep && (isPlainObject(source[key]) || isArray(source[key]))) { + if (isPlainObject(source[key]) && !isPlainObject(target[key])) { + target[key] = {}; + } + if (isArray(source[key]) && !isArray(target[key])) { + target[key] = []; + } + _merge(target[key], source[key], deep); + } else if (source[key] !== undefined) { + target[key] = source[key]; + } + } +} - function query (options, next) { +/** + * Root Prefix Transform. + */ - var urlParams = Object.keys(Url.options.params), - query = {}, - url = next(options); +function root (options, next) { - each(options.params, function (value, key) { - if (urlParams.indexOf(key) === -1) { - query[key] = value; - } - }); + var url = next(options); - query = Url.params(query); + if (isString(options.root) && !url.match(/^(https?:)?\//)) { + url = options.root + '/' + url; + } - if (query) { - url += (url.indexOf('?') == -1 ? '?' : '&') + query; - } + return url; +} - return url; - } +/** + * Query Parameter Transform. + */ - /** - * URL Template v2.0.6 (https://github.com/bramstein/url-template) - */ +function query (options, next) { - function expand(url, params, variables) { + var urlParams = Object.keys(Url.options.params), + query = {}, + url = next(options); - var tmpl = parse(url), - expanded = tmpl.expand(params); + each(options.params, function (value, key) { + if (urlParams.indexOf(key) === -1) { + query[key] = value; + } + }); - if (variables) { - variables.push.apply(variables, tmpl.vars); - } + query = Url.params(query); - return expanded; - } + if (query) { + url += (url.indexOf('?') == -1 ? '?' : '&') + query; + } - function parse(template) { - - var operators = ['+', '#', '.', '/', ';', '?', '&'], - variables = []; - - return { - vars: variables, - expand: function (context) { - return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) { - if (expression) { - - var operator = null, - values = []; - - if (operators.indexOf(expression.charAt(0)) !== -1) { - operator = expression.charAt(0); - expression = expression.substr(1); - } - - expression.split(/,/g).forEach(function (variable) { - var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); - values.push.apply(values, getValues(context, operator, tmp[1], tmp[2] || tmp[3])); - variables.push(tmp[1]); - }); - - if (operator && operator !== '+') { - - var separator = ','; - - if (operator === '?') { - separator = '&'; - } else if (operator !== '#') { - separator = operator; - } - - return (values.length !== 0 ? operator : '') + values.join(separator); - } else { - return values.join(','); - } - } else { - return encodeReserved(literal); - } - }); - } - }; - } + return url; +} - function getValues(context, operator, key, modifier) { - - var value = context[key], - result = []; - - if (isDefined(value) && value !== '') { - if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { - value = value.toString(); - - if (modifier && modifier !== '*') { - value = value.substring(0, parseInt(modifier, 10)); - } - - result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null)); - } else { - if (modifier === '*') { - if (Array.isArray(value)) { - value.filter(isDefined).forEach(function (value) { - result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null)); - }); - } else { - Object.keys(value).forEach(function (k) { - if (isDefined(value[k])) { - result.push(encodeValue(operator, value[k], k)); - } - }); - } - } else { - var tmp = []; - - if (Array.isArray(value)) { - value.filter(isDefined).forEach(function (value) { - tmp.push(encodeValue(operator, value)); - }); - } else { - Object.keys(value).forEach(function (k) { - if (isDefined(value[k])) { - tmp.push(encodeURIComponent(k)); - tmp.push(encodeValue(operator, value[k].toString())); - } - }); - } - - if (isKeyOperator(operator)) { - result.push(encodeURIComponent(key) + '=' + tmp.join(',')); - } else if (tmp.length !== 0) { - result.push(tmp.join(',')); - } - } - } - } else { - if (operator === ';') { - result.push(encodeURIComponent(key)); - } else if (value === '' && (operator === '&' || operator === '?')) { - result.push(encodeURIComponent(key) + '='); - } else if (value === '') { - result.push(''); - } - } - - return result; - } +/** + * URL Template v2.0.6 (https://github.com/bramstein/url-template) + */ - function isDefined(value) { - return value !== undefined && value !== null; - } +function expand(url, params, variables) { - function isKeyOperator(operator) { - return operator === ';' || operator === '&' || operator === '?'; - } + var tmpl = parse(url), + expanded = tmpl.expand(params); - function encodeValue(operator, value, key) { + if (variables) { + variables.push.apply(variables, tmpl.vars); + } - value = operator === '+' || operator === '#' ? encodeReserved(value) : encodeURIComponent(value); + return expanded; +} + +function parse(template) { + + var operators = ['+', '#', '.', '/', ';', '?', '&'], + variables = []; + + return { + vars: variables, + expand: function (context) { + return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) { + if (expression) { + + var operator = null, + values = []; + + if (operators.indexOf(expression.charAt(0)) !== -1) { + operator = expression.charAt(0); + expression = expression.substr(1); + } + + expression.split(/,/g).forEach(function (variable) { + var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); + values.push.apply(values, getValues(context, operator, tmp[1], tmp[2] || tmp[3])); + variables.push(tmp[1]); + }); + + if (operator && operator !== '+') { + + var separator = ','; + + if (operator === '?') { + separator = '&'; + } else if (operator !== '#') { + separator = operator; + } + + return (values.length !== 0 ? operator : '') + values.join(separator); + } else { + return values.join(','); + } + } else { + return encodeReserved(literal); + } + }); + } + }; +} + +function getValues(context, operator, key, modifier) { + + var value = context[key], + result = []; + + if (isDefined(value) && value !== '') { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + value = value.toString(); + + if (modifier && modifier !== '*') { + value = value.substring(0, parseInt(modifier, 10)); + } + + result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null)); + } else { + if (modifier === '*') { + if (Array.isArray(value)) { + value.filter(isDefined).forEach(function (value) { + result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null)); + }); + } else { + Object.keys(value).forEach(function (k) { + if (isDefined(value[k])) { + result.push(encodeValue(operator, value[k], k)); + } + }); + } + } else { + var tmp = []; + + if (Array.isArray(value)) { + value.filter(isDefined).forEach(function (value) { + tmp.push(encodeValue(operator, value)); + }); + } else { + Object.keys(value).forEach(function (k) { + if (isDefined(value[k])) { + tmp.push(encodeURIComponent(k)); + tmp.push(encodeValue(operator, value[k].toString())); + } + }); + } + + if (isKeyOperator(operator)) { + result.push(encodeURIComponent(key) + '=' + tmp.join(',')); + } else if (tmp.length !== 0) { + result.push(tmp.join(',')); + } + } + } + } else { + if (operator === ';') { + result.push(encodeURIComponent(key)); + } else if (value === '' && (operator === '&' || operator === '?')) { + result.push(encodeURIComponent(key) + '='); + } else if (value === '') { + result.push(''); + } + } - if (key) { - return encodeURIComponent(key) + '=' + value; - } else { - return value; - } - } + return result; +} - function encodeReserved(str) { - return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) { - if (!/%[0-9A-Fa-f]/.test(part)) { - part = encodeURI(part); - } - return part; - }).join(''); - } +function isDefined(value) { + return value !== undefined && value !== null; +} - function template (options) { +function isKeyOperator(operator) { + return operator === ';' || operator === '&' || operator === '?'; +} - var variables = [], - url = expand(options.url, options.params, variables); +function encodeValue(operator, value, key) { - variables.forEach(function (key) { - delete options.params[key]; - }); + value = operator === '+' || operator === '#' ? encodeReserved(value) : encodeURIComponent(value); - return url; - } + if (key) { + return encodeURIComponent(key) + '=' + value; + } else { + return value; + } +} + +function encodeReserved(str) { + return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) { + if (!/%[0-9A-Fa-f]/.test(part)) { + part = encodeURI(part); + } + return part; + }).join(''); +} + +/** + * URL Template (RFC 6570) Transform. + */ - /** - * Service for URL templating. - */ +function template (options) { - var ie = document.documentMode; - var el = document.createElement('a'); + var variables = [], + url = expand(options.url, options.params, variables); - function Url(url, params) { + variables.forEach(function (key) { + delete options.params[key]; + }); - var self = this || {}, - options = url, - transform; + return url; +} - if (isString(url)) { - options = { url: url, params: params }; - } +/** + * Service for URL templating. + */ - options = merge({}, Url.options, self.$options, options); +var ie = document.documentMode; +var el = document.createElement('a'); - Url.transforms.forEach(function (handler) { - transform = factory(handler, transform, self.$vm); - }); +function Url(url, params) { - return transform(options); - } + var self = this || {}, + options = url, + transform; - /** - * Url options. - */ + if (isString(url)) { + options = { url: url, params: params }; + } - Url.options = { - url: '', - root: null, - params: {} - }; + options = merge({}, Url.options, self.$options, options); - /** - * Url transforms. - */ + Url.transforms.forEach(function (handler) { + transform = factory(handler, transform, self.$vm); + }); - Url.transforms = [template, query, root]; + return transform(options); +} - /** - * Encodes a Url parameter string. - * - * @param {Object} obj - */ +/** + * Url options. + */ - Url.params = function (obj) { +Url.options = { + url: '', + root: null, + params: {} +}; - var params = [], - escape = encodeURIComponent; +/** + * Url transforms. + */ - params.add = function (key, value) { +Url.transforms = [template, query, root]; - if (isFunction(value)) { - value = value(); - } +/** + * Encodes a Url parameter string. + * + * @param {Object} obj + */ - if (value === null) { - value = ''; - } +Url.params = function (obj) { - this.push(escape(key) + '=' + escape(value)); - }; + var params = [], + escape = encodeURIComponent; - serialize(params, obj); + params.add = function (key, value) { - return params.join('&').replace(/%20/g, '+'); - }; + if (isFunction(value)) { + value = value(); + } - /** - * Parse a URL and return its components. - * - * @param {String} url - */ + if (value === null) { + value = ''; + } - Url.parse = function (url) { + this.push(escape(key) + '=' + escape(value)); + }; - if (ie) { - el.href = url; - url = el.href; - } + serialize(params, obj); - el.href = url; + return params.join('&').replace(/%20/g, '+'); +}; - return { - href: el.href, - protocol: el.protocol ? el.protocol.replace(/:$/, '') : '', - port: el.port, - host: el.host, - hostname: el.hostname, - pathname: el.pathname.charAt(0) === '/' ? el.pathname : '/' + el.pathname, - search: el.search ? el.search.replace(/^\?/, '') : '', - hash: el.hash ? el.hash.replace(/^#/, '') : '' - }; - }; +/** + * Parse a URL and return its components. + * + * @param {String} url + */ - function factory(handler, next, vm) { - return function (options) { - return handler.call(vm, options, next); - }; - } +Url.parse = function (url) { - function serialize(params, obj, scope) { + if (ie) { + el.href = url; + url = el.href; + } - var array = isArray(obj), - plain = isPlainObject(obj), - hash; + el.href = url; + + return { + href: el.href, + protocol: el.protocol ? el.protocol.replace(/:$/, '') : '', + port: el.port, + host: el.host, + hostname: el.hostname, + pathname: el.pathname.charAt(0) === '/' ? el.pathname : '/' + el.pathname, + search: el.search ? el.search.replace(/^\?/, '') : '', + hash: el.hash ? el.hash.replace(/^#/, '') : '' + }; +}; + +function factory(handler, next, vm) { + return function (options) { + return handler.call(vm, options, next); + }; +} + +function serialize(params, obj, scope) { + + var array = isArray(obj), + plain = isPlainObject(obj), + hash; + + each(obj, function (value, key) { + + hash = isObject(value) || isArray(value); + + if (scope) { + key = scope + '[' + (plain || hash ? key : '') + ']'; + } + + if (!scope && array) { + params.add(value.name, value.value); + } else if (hash) { + serialize(params, value, key); + } else { + params.add(key, value); + } + }); +} + +/** + * XDomain client (Internet Explorer). + */ - each(obj, function (value, key) { +function xdrClient (request) { + return new Promise$1(function (resolve) { - hash = isObject(value) || isArray(value); + var xdr = new XDomainRequest(), + handler = function (event) { - if (scope) { - key = scope + '[' + (plain || hash ? key : '') + ']'; - } + var response = request.respondWith(xdr.responseText, { + status: xdr.status, + statusText: xdr.statusText + }); - if (!scope && array) { - params.add(value.name, value.value); - } else if (hash) { - serialize(params, value, key); - } else { - params.add(key, value); - } - }); - } + resolve(response); + }; - function xdrClient (request) { - return new Promise$1(function (resolve) { + request.abort = function () { + return xdr.abort(); + }; - var xdr = new XDomainRequest(), - handler = function (event) { + xdr.open(request.method, request.getUrl(), true); + xdr.timeout = 0; + xdr.onload = handler; + xdr.onerror = handler; + xdr.ontimeout = function () {}; + xdr.onprogress = function () {}; + xdr.send(request.getBody()); + }); +} - var response = request.respondWith(xdr.responseText, { - status: xdr.status, - statusText: xdr.statusText - }); +/** + * CORS Interceptor. + */ - resolve(response); - }; +var ORIGIN_URL = Url.parse(location.href); +var SUPPORTS_CORS = 'withCredentials' in new XMLHttpRequest(); - request.abort = function () { - return xdr.abort(); - }; +function cors (request, next) { - xdr.open(request.method, request.getUrl(), true); - xdr.timeout = 0; - xdr.onload = handler; - xdr.onerror = handler; - xdr.ontimeout = function () {}; - xdr.onprogress = function () {}; - xdr.send(request.getBody()); - }); - } + if (!isBoolean(request.crossOrigin) && crossOrigin(request)) { + request.crossOrigin = true; + } - var ORIGIN_URL = Url.parse(location.href); - var SUPPORTS_CORS = 'withCredentials' in new XMLHttpRequest(); + if (request.crossOrigin) { - function cors (request, next) { + if (!SUPPORTS_CORS) { + request.client = xdrClient; + } - if (!isBoolean(request.crossOrigin) && crossOrigin(request)) { - request.crossOrigin = true; - } + delete request.emulateHTTP; + } - if (request.crossOrigin) { + next(); +} - if (!SUPPORTS_CORS) { - request.client = xdrClient; - } +function crossOrigin(request) { - delete request.emulateHTTP; - } + var requestUrl = Url.parse(Url(request)); - next(); - } + return requestUrl.protocol !== ORIGIN_URL.protocol || requestUrl.host !== ORIGIN_URL.host; +} - function crossOrigin(request) { +/** + * Body Interceptor. + */ - var requestUrl = Url.parse(Url(request)); +function body (request, next) { - return requestUrl.protocol !== ORIGIN_URL.protocol || requestUrl.host !== ORIGIN_URL.host; - } + if (request.emulateJSON && isPlainObject(request.body)) { + request.body = Url.params(request.body); + request.headers.set('Content-Type', 'application/x-www-form-urlencoded'); + } - function body (request, next) { + if (isFormData(request.body)) { + request.headers.delete('Content-Type'); + } - if (request.emulateJSON && isPlainObject(request.body)) { - request.body = Url.params(request.body); - request.headers['Content-Type'] = 'application/x-www-form-urlencoded'; - } + if (isPlainObject(request.body)) { + request.body = JSON.stringify(request.body); + } - if (isFormData(request.body)) { - delete request.headers['Content-Type']; - } + next(function (response) { - if (isPlainObject(request.body)) { - request.body = JSON.stringify(request.body); - } + Object.defineProperty(response, 'data', { + get: function () { + return this.body; + }, + set: function (body) { + this.body = body; + } + }); - next(function (response) { + return response.bodyText ? when(response.text(), function (text) { - var contentType = response.headers['Content-Type']; + var type = response.headers.get('Content-Type'); - if (isString(contentType) && contentType.indexOf('application/json') === 0) { + if (isString(type) && type.indexOf('application/json') === 0) { - try { - response.data = response.json(); - } catch (e) { - response.data = null; - } - } else { - response.data = response.text(); - } - }); - } + try { + response.body = JSON.parse(text); + } catch (e) { + response.body = null; + } + } else { + response.body = text; + } - function jsonpClient (request) { - return new Promise$1(function (resolve) { + return response; + }) : response; + }); +} - var name = request.jsonp || 'callback', - callback = '_jsonp' + Math.random().toString(36).substr(2), - body = null, - handler, - script; +/** + * JSONP client. + */ - handler = function (event) { +function jsonpClient (request) { + return new Promise$1(function (resolve) { - var status = 0; + var name = request.jsonp || 'callback', + callback = '_jsonp' + Math.random().toString(36).substr(2), + body = null, + handler, + script; - if (event.type === 'load' && body !== null) { - status = 200; - } else if (event.type === 'error') { - status = 404; - } + handler = function (event) { - resolve(request.respondWith(body, { status: status })); + var status = 0; - delete window[callback]; - document.body.removeChild(script); - }; + if (event.type === 'load' && body !== null) { + status = 200; + } else if (event.type === 'error') { + status = 404; + } - request.params[name] = callback; + resolve(request.respondWith(body, { status: status })); - window[callback] = function (result) { - body = JSON.stringify(result); - }; + delete window[callback]; + document.body.removeChild(script); + }; - script = document.createElement('script'); - script.src = request.getUrl(); - script.type = 'text/javascript'; - script.async = true; - script.onload = handler; - script.onerror = handler; + request.params[name] = callback; - document.body.appendChild(script); - }); - } + window[callback] = function (result) { + body = JSON.stringify(result); + }; - function jsonp (request, next) { + script = document.createElement('script'); + script.src = request.getUrl(); + script.type = 'text/javascript'; + script.async = true; + script.onload = handler; + script.onerror = handler; - if (request.method == 'JSONP') { - request.client = jsonpClient; - } + document.body.appendChild(script); + }); +} - next(function (response) { +/** + * JSONP Interceptor. + */ - if (request.method == 'JSONP') { - response.data = response.json(); - } - }); - } +function jsonp (request, next) { - function before (request, next) { + if (request.method == 'JSONP') { + request.client = jsonpClient; + } - if (isFunction(request.before)) { - request.before.call(this, request); - } + next(function (response) { - next(); - } + if (request.method == 'JSONP') { - /** - * HTTP method override Interceptor. - */ + return when(response.json(), function (json) { - function method (request, next) { + response.body = json; - if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { - request.headers['X-HTTP-Method-Override'] = request.method; - request.method = 'POST'; - } + return response; + }); + } + }); +} - next(); - } +/** + * Before Interceptor. + */ - function header (request, next) { +function before (request, next) { - request.method = request.method.toUpperCase(); - request.headers = assign({}, Http.headers.common, !request.crossOrigin ? Http.headers.custom : {}, Http.headers[request.method.toLowerCase()], request.headers); + if (isFunction(request.before)) { + request.before.call(this, request); + } - next(); - } + next(); +} - /** - * Timeout Interceptor. - */ +/** + * HTTP method override Interceptor. + */ - function timeout (request, next) { +function method (request, next) { - var timeout; + if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { + request.headers.set('X-HTTP-Method-Override', request.method); + request.method = 'POST'; + } - if (request.timeout) { - timeout = setTimeout(function () { - request.abort(); - }, request.timeout); - } + next(); +} - next(function (response) { +/** + * Header Interceptor. + */ - clearTimeout(timeout); - }); - } +function header (request, next) { - function xhrClient (request) { - return new Promise$1(function (resolve) { + var headers = assign({}, Http.headers.common, !request.crossOrigin ? Http.headers.custom : {}, Http.headers[toLower(request.method)]); - var xhr = new XMLHttpRequest(), - handler = function (event) { + each(headers, function (value, name) { + if (!request.headers.has(name)) { + request.headers.set(name, value); + } + }); - var response = request.respondWith('response' in xhr ? xhr.response : xhr.responseText, { - status: xhr.status === 1223 ? 204 : xhr.status, // IE9 status bug - statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText), - headers: parseHeaders(xhr.getAllResponseHeaders()) - }); + next(); +} - resolve(response); - }; +/** + * Timeout Interceptor. + */ - request.abort = function () { - return xhr.abort(); - }; +function timeout (request, next) { - xhr.open(request.method, request.getUrl(), true); - xhr.timeout = 0; - xhr.onload = handler; - xhr.onerror = handler; + var timeout; - if (request.progress) { - if (request.method === 'GET') { - xhr.addEventListener('progress', request.progress); - } else if (/^(POST|PUT)$/i.test(request.method)) { - xhr.upload.addEventListener('progress', request.progress); - } - } + if (request.timeout) { + timeout = setTimeout(function () { + request.abort(); + }, request.timeout); + } - if (request.credentials === true) { - xhr.withCredentials = true; - } + next(function (response) { - each(request.headers || {}, function (value, header) { - xhr.setRequestHeader(header, value); - }); + clearTimeout(timeout); + }); +} - xhr.send(request.getBody()); - }); - } +/** + * XMLHttp client. + */ - function parseHeaders(str) { +function xhrClient (request) { + return new Promise$1(function (resolve) { - var headers = {}, - value, - name, - i; + var xhr = new XMLHttpRequest(), + handler = function (event) { - each(trim(str).split('\n'), function (row) { + var response = request.respondWith('response' in xhr ? xhr.response : xhr.responseText, { + status: xhr.status === 1223 ? 204 : xhr.status, // IE9 status bug + statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText) + }); - i = row.indexOf(':'); - name = trim(row.slice(0, i)); - value = trim(row.slice(i + 1)); + each(trim(xhr.getAllResponseHeaders()).split('\n'), function (row) { + response.headers.append(row.slice(0, row.indexOf(':')), row.slice(row.indexOf(':') + 1)); + }); - if (headers[name]) { + resolve(response); + }; - if (isArray(headers[name])) { - headers[name].push(value); - } else { - headers[name] = [headers[name], value]; - } - } else { + request.abort = function () { + return xhr.abort(); + }; - headers[name] = value; - } - }); + xhr.open(request.method, request.getUrl(), true); + xhr.timeout = 0; + xhr.onload = handler; + xhr.onerror = handler; - return headers; - } + if (request.progress) { + if (request.method === 'GET') { + xhr.addEventListener('progress', request.progress); + } else if (/^(POST|PUT)$/i.test(request.method)) { + xhr.upload.addEventListener('progress', request.progress); + } + } - function Client (context) { + if ('responseType' in xhr) { + xhr.responseType = 'blob'; + } - var reqHandlers = [sendRequest], - resHandlers = [], - handler; + if (request.credentials === true) { + xhr.withCredentials = true; + } - if (!isObject(context)) { - context = null; - } + request.headers.forEach(function (value, name) { + xhr.setRequestHeader(name, value); + }); - function Client(request) { - return new Promise$1(function (resolve) { + xhr.send(request.getBody()); + }); +} - function exec() { +/** + * Base client. + */ - handler = reqHandlers.pop(); +function Client (context) { - if (isFunction(handler)) { - handler.call(context, request, next); - } else { - warn('Invalid interceptor of type ' + typeof handler + ', must be a function'); - next(); - } - } + var reqHandlers = [sendRequest], + resHandlers = [], + handler; - function next(response) { + if (!isObject(context)) { + context = null; + } - if (isFunction(response)) { + function Client(request) { + return new Promise$1(function (resolve) { - resHandlers.unshift(response); - } else if (isObject(response)) { + function exec() { - resHandlers.forEach(function (handler) { - response = when(response, function (response) { - return handler.call(context, response) || response; - }); - }); + handler = reqHandlers.pop(); - when(response, resolve); + if (isFunction(handler)) { + handler.call(context, request, next); + } else { + warn('Invalid interceptor of type ' + typeof handler + ', must be a function'); + next(); + } + } - return; - } + function next(response) { - exec(); - } + if (isFunction(response)) { - exec(); - }, context); - } + resHandlers.unshift(response); + } else if (isObject(response)) { - Client.use = function (handler) { - reqHandlers.push(handler); - }; + resHandlers.forEach(function (handler) { + response = when(response, function (response) { + return handler.call(context, response) || response; + }); + }); - return Client; - } + when(response, resolve); - function sendRequest(request, resolve) { + return; + } - var client = request.client || xhrClient; + exec(); + } - resolve(client(request)); + exec(); + }, context); + } + + Client.use = function (handler) { + reqHandlers.push(handler); + }; + + return Client; +} + +function sendRequest(request, resolve) { + + var client = request.client || xhrClient; + + resolve(client(request)); +} + +var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); } +}; + +/** + * HTTP Headers. + */ + +var Headers = function () { + function Headers(headers) { + var _this = this; - var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); + classCallCheck(this, Headers); + + + this.map = {}; + + each(headers, function (value, name) { + return _this.append(name, value); + }); } - }; - /** - * HTTP Response. - */ + Headers.prototype.has = function has(name) { + return this.map.hasOwnProperty(normalizeName(name)); + }; - var Response = function () { - function Response(body, _ref) { - var url = _ref.url; - var headers = _ref.headers; - var status = _ref.status; - var statusText = _ref.statusText; - classCallCheck(this, Response); + Headers.prototype.get = function get(name) { + var list = this.map[normalizeName(name)]; - this.url = url; - this.body = body; - this.headers = headers || {}; - this.status = status || 0; - this.statusText = statusText || ''; - this.ok = status >= 200 && status < 300; - } + return list ? list[0] : null; + }; - Response.prototype.text = function text() { - return this.body; - }; + Headers.prototype.getAll = function getAll(name) { + return this.map[normalizeName(name)] || []; + }; - Response.prototype.blob = function blob() { - return new Blob([this.body]); - }; + Headers.prototype.set = function set(name, value) { + this.map[normalizeName(name)] = [trim(value)]; + }; - Response.prototype.json = function json() { - return JSON.parse(this.body); - }; + Headers.prototype.append = function append(name, value) { - return Response; - }(); + var list = this.map[normalizeName(name)]; - var Request = function () { - function Request(options) { - classCallCheck(this, Request); + if (!list) { + list = this.map[normalizeName(name)] = []; + } + list.push(trim(value)); + }; - this.method = 'GET'; - this.body = null; - this.params = {}; - this.headers = {}; + Headers.prototype.delete = function _delete(name) { + delete this.map[normalizeName(name)]; + }; - assign(this, options); - } + Headers.prototype.forEach = function forEach(callback, thisArg) { + var _this2 = this; - Request.prototype.getUrl = function getUrl() { - return Url(this); - }; + each(this.map, function (list, name) { + each(list, function (value) { + return callback.call(thisArg, value, name, _this2); + }); + }); + }; - Request.prototype.getBody = function getBody() { - return this.body; - }; + return Headers; +}(); - Request.prototype.respondWith = function respondWith(body, options) { - return new Response(body, assign(options || {}, { url: this.getUrl() })); - }; +function normalizeName(name) { - return Request; - }(); + if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { + throw new TypeError('Invalid character in header field name'); + } - /** - * Service for sending network requests. - */ + return toLower(trim(name)); +} - var CUSTOM_HEADERS = { 'X-Requested-With': 'XMLHttpRequest' }; - var COMMON_HEADERS = { 'Accept': 'application/json, text/plain, */*' }; - var JSON_CONTENT_TYPE = { 'Content-Type': 'application/json;charset=utf-8' }; +/** + * HTTP Response. + */ - function Http(options) { +var Response = function () { + function Response(body, _ref) { + var url = _ref.url; + var headers = _ref.headers; + var status = _ref.status; + var statusText = _ref.statusText; + classCallCheck(this, Response); - var self = this || {}, - client = Client(self.$vm); - defaults(options || {}, self.$options, Http.options); + this.url = url; + this.ok = status >= 200 && status < 300; + this.status = status || 0; + this.statusText = statusText || ''; + this.headers = new Headers(headers); + this.body = body; - Http.interceptors.forEach(function (handler) { - client.use(handler); - }); + if (isString(body)) { - return client(new Request(options)).then(function (response) { + this.bodyText = body; + } else if (isBlob(body)) { - return response.ok ? response : Promise$1.reject(response); - }, function (response) { + this.bodyBlob = body; - if (response instanceof Error) { - error(response); - } + if (isBlobText(body)) { + this.bodyText = blobText(body); + } + } + } - return Promise$1.reject(response); - }); - } + Response.prototype.blob = function blob() { + return when(this.bodyBlob); + }; - Http.options = {}; + Response.prototype.text = function text() { + return when(this.bodyText); + }; - Http.headers = { - put: JSON_CONTENT_TYPE, - post: JSON_CONTENT_TYPE, - patch: JSON_CONTENT_TYPE, - delete: JSON_CONTENT_TYPE, - custom: CUSTOM_HEADERS, - common: COMMON_HEADERS - }; + Response.prototype.json = function json() { + return when(this.text(), function (text) { + return JSON.parse(text); + }); + }; - Http.interceptors = [before, timeout, method, body, jsonp, header, cors]; + return Response; +}(); - ['get', 'delete', 'head', 'jsonp'].forEach(function (method) { +function blobText(body) { + return new Promise$1(function (resolve) { - Http[method] = function (url, options) { - return this(assign(options || {}, { url: url, method: method })); - }; - }); + var reader = new FileReader(); - ['post', 'put', 'patch'].forEach(function (method) { + reader.readAsText(body); + reader.onload = function () { + resolve(reader.result); + }; + }); +} - Http[method] = function (url, body, options) { - return this(assign(options || {}, { url: url, method: method, body: body })); - }; - }); +function isBlobText(body) { + return body.type.indexOf('text') === 0 || body.type.indexOf('json') !== -1; +} - function Resource(url, params, actions, options) { +/** + * HTTP Request. + */ - var self = this || {}, - resource = {}; +var Request = function () { + function Request(options) { + classCallCheck(this, Request); - actions = assign({}, Resource.actions, actions); - each(actions, function (action, name) { + this.body = null; + this.params = {}; - action = merge({ url: url, params: params || {} }, options, action); + assign(this, options, { + method: toUpper(options.method || 'GET'), + headers: new Headers(options.headers) + }); + } - resource[name] = function () { - return (self.$http || Http)(opts(action, arguments)); - }; - }); + Request.prototype.getUrl = function getUrl() { + return Url(this); + }; - return resource; - } + Request.prototype.getBody = function getBody() { + return this.body; + }; - function opts(action, args) { + Request.prototype.respondWith = function respondWith(body, options) { + return new Response(body, assign(options || {}, { url: this.getUrl() })); + }; - var options = assign({}, action), - params = {}, - body; + return Request; +}(); - switch (args.length) { +/** + * Service for sending network requests. + */ - case 2: +var CUSTOM_HEADERS = { 'X-Requested-With': 'XMLHttpRequest' }; +var COMMON_HEADERS = { 'Accept': 'application/json, text/plain, */*' }; +var JSON_CONTENT_TYPE = { 'Content-Type': 'application/json;charset=utf-8' }; - params = args[0]; - body = args[1]; +function Http(options) { - break; + var self = this || {}, + client = Client(self.$vm); - case 1: + defaults(options || {}, self.$options, Http.options); - if (/^(POST|PUT|PATCH)$/i.test(options.method)) { - body = args[0]; - } else { - params = args[0]; - } + Http.interceptors.forEach(function (handler) { + client.use(handler); + }); - break; + return client(new Request(options)).then(function (response) { - case 0: + return response.ok ? response : Promise$1.reject(response); + }, function (response) { - break; + if (response instanceof Error) { + error(response); + } - default: + return Promise$1.reject(response); + }); +} - throw 'Expected up to 4 arguments [params, body], got ' + args.length + ' arguments'; - } +Http.options = {}; - options.body = body; - options.params = assign({}, options.params, params); +Http.headers = { + put: JSON_CONTENT_TYPE, + post: JSON_CONTENT_TYPE, + patch: JSON_CONTENT_TYPE, + delete: JSON_CONTENT_TYPE, + custom: CUSTOM_HEADERS, + common: COMMON_HEADERS +}; - return options; - } +Http.interceptors = [before, timeout, method, body, jsonp, header, cors]; + +['get', 'delete', 'head', 'jsonp'].forEach(function (method) { - Resource.actions = { + Http[method] = function (url, options) { + return this(assign(options || {}, { url: url, method: method })); + }; +}); - get: { method: 'GET' }, - save: { method: 'POST' }, - query: { method: 'GET' }, - update: { method: 'PUT' }, - remove: { method: 'DELETE' }, - delete: { method: 'DELETE' } +['post', 'put', 'patch'].forEach(function (method) { - }; + Http[method] = function (url, body, options) { + return this(assign(options || {}, { url: url, method: method, body: body })); + }; +}); - function plugin(Vue) { +/** + * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) + */ - if (plugin.installed) { - return; - } +var RESOLVED = 0; +var REJECTED = 1; +var PENDING = 2; - Util(Vue); +function Promise$2(executor) { - Vue.url = Url; - Vue.http = Http; - Vue.resource = Resource; - Vue.Promise = Promise$1; + this.state = PENDING; + this.value = undefined; + this.deferred = []; - Object.defineProperties(Vue.prototype, { + var promise = this; + + try { + executor(function (x) { + promise.resolve(x); + }, function (r) { + promise.reject(r); + }); + } catch (e) { + promise.reject(e); + } +} + +Promise$2.reject = function (r) { + return new Promise$2(function (resolve, reject) { + reject(r); + }); +}; + +Promise$2.resolve = function (x) { + return new Promise$2(function (resolve, reject) { + resolve(x); + }); +}; + +Promise$2.all = function all(iterable) { + return new Promise$2(function (resolve, reject) { + var count = 0, + result = []; + + if (iterable.length === 0) { + resolve(result); + } + + function resolver(i) { + return function (x) { + result[i] = x; + count += 1; + + if (count === iterable.length) { + resolve(result); + } + }; + } + + for (var i = 0; i < iterable.length; i += 1) { + Promise$2.resolve(iterable[i]).then(resolver(i), reject); + } + }); +}; + +Promise$2.race = function race(iterable) { + return new Promise$2(function (resolve, reject) { + for (var i = 0; i < iterable.length; i += 1) { + Promise$2.resolve(iterable[i]).then(resolve, reject); + } + }); +}; + +var p$1 = Promise$2.prototype; + +p$1.resolve = function resolve(x) { + var promise = this; + + if (promise.state === PENDING) { + if (x === promise) { + throw new TypeError('Promise settled with itself.'); + } + + var called = false; + + try { + var then = x && x['then']; + + if (x !== null && typeof x === 'object' && typeof then === 'function') { + then.call(x, function (x) { + if (!called) { + promise.resolve(x); + } + called = true; + }, function (r) { + if (!called) { + promise.reject(r); + } + called = true; + }); + return; + } + } catch (e) { + if (!called) { + promise.reject(e); + } + return; + } + + promise.state = RESOLVED; + promise.value = x; + promise.notify(); + } +}; - $url: { - get: function () { - return options(Vue.url, this, this.$options.url); - } - }, +p$1.reject = function reject(reason) { + var promise = this; - $http: { - get: function () { - return options(Vue.http, this, this.$options.http); - } - }, + if (promise.state === PENDING) { + if (reason === promise) { + throw new TypeError('Promise settled with itself.'); + } - $resource: { - get: function () { - return Vue.resource.bind(this); - } - }, + promise.state = REJECTED; + promise.value = reason; + promise.notify(); + } +}; + +p$1.notify = function notify() { + var promise = this; + + nextTick(function () { + if (promise.state !== PENDING) { + while (promise.deferred.length) { + var deferred = promise.deferred.shift(), + onResolved = deferred[0], + onRejected = deferred[1], + resolve = deferred[2], + reject = deferred[3]; + + try { + if (promise.state === RESOLVED) { + if (typeof onResolved === 'function') { + resolve(onResolved.call(undefined, promise.value)); + } else { + resolve(promise.value); + } + } else if (promise.state === REJECTED) { + if (typeof onRejected === 'function') { + resolve(onRejected.call(undefined, promise.value)); + } else { + reject(promise.value); + } + } + } catch (e) { + reject(e); + } + } + } + }); +}; + +p$1.then = function then(onResolved, onRejected) { + var promise = this; + + return new Promise$2(function (resolve, reject) { + promise.deferred.push([onResolved, onRejected, resolve, reject]); + promise.notify(); + }); +}; + +p$1.catch = function (onRejected) { + return this.then(undefined, onRejected); +}; + +/** + * Service for interacting with RESTful services. + */ - $promise: { - get: function () { - var _this = this; +function Resource(url, params, actions, options) { - return function (executor) { - return new Vue.Promise(executor, _this); - }; - } - } + var self = this || {}, + resource = {}; - }); - } + actions = assign({}, Resource.actions, actions); - if (typeof window !== 'undefined' && window.Vue) { - window.Vue.use(plugin); - } + each(actions, function (action, name) { + + action = merge({ url: url, params: assign({}, params) }, options, action); + + resource[name] = function () { + return (self.$http || Http)(opts(action, arguments)); + }; + }); + + return resource; +} + +function opts(action, args) { + + var options = assign({}, action), + params = {}, + body; + + switch (args.length) { + + case 2: + + params = args[0]; + body = args[1]; + + break; + + case 1: + + if (/^(POST|PUT|PATCH)$/i.test(options.method)) { + body = args[0]; + } else { + params = args[0]; + } + + break; + + case 0: + + break; + + default: + + throw 'Expected up to 4 arguments [params, body], got ' + args.length + ' arguments'; + } + + options.body = body; + options.params = assign({}, options.params, params); + + return options; +} + +Resource.actions = { + + get: { method: 'GET' }, + save: { method: 'POST' }, + query: { method: 'GET' }, + update: { method: 'PUT' }, + remove: { method: 'DELETE' }, + delete: { method: 'DELETE' } + +}; + +/** + * Install plugin. + */ + +function plugin(Vue) { + + if (plugin.installed) { + return; + } + + Util(Vue); + + Vue.url = Url; + Vue.http = Http; + Vue.resource = Resource; + Vue.Promise = Promise$1; + + Object.defineProperties(Vue.prototype, { + + $url: { + get: function () { + return options(Vue.url, this, this.$options.url); + } + }, + + $http: { + get: function () { + return options(Vue.http, this, this.$options.http); + } + }, + + $resource: { + get: function () { + return Vue.resource.bind(this); + } + }, + + $promise: { + get: function () { + var _this = this; + + return function (executor) { + return new Vue.Promise(executor, _this); + }; + } + } + + }); +} + +if (typeof window !== 'undefined') { + + if (!window.Promise) { + window.Promise = Promise$2; + } + + if (window.Vue) { + window.Vue.use(plugin); + } +} - return plugin; +return plugin; -})); \ No newline at end of file +}))); \ No newline at end of file diff --git a/dist/vue-resource.min.js b/dist/vue-resource.min.js index 6bff73a2..87766ee7 100644 --- a/dist/vue-resource.min.js +++ b/dist/vue-resource.min.js @@ -1,7 +1,7 @@ /*! - * vue-resource v0.9.3 + * vue-resource v1.0.0 * https://github.com/vuejs/vue-resource * Released under the MIT License. */ -!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):t.VueResource=n()}(this,function(){"use strict";function t(t){this.state=Z,this.value=void 0,this.deferred=[];var n=this;try{t(function(t){n.resolve(t)},function(t){n.reject(t)})}catch(e){n.reject(e)}}function n(t,n){t instanceof nt?this.promise=t:this.promise=new nt(t.bind(n)),this.context=n}function e(t){rt=t.util,ot=t.config.debug||!t.config.silent}function o(t){"undefined"!=typeof console&&ot&&console.warn("[VueResource warn]: "+t)}function r(t){"undefined"!=typeof console&&console.error(t)}function i(t,n){return rt.nextTick(t,n)}function u(t){return t.replace(/^\s*|\s*$/g,"")}function s(t){return"string"==typeof t}function c(t){return t===!0||t===!1}function a(t){return"function"==typeof t}function f(t){return null!==t&&"object"==typeof t}function h(t){return f(t)&&Object.getPrototypeOf(t)==Object.prototype}function p(t){return"undefined"!=typeof FormData&&t instanceof FormData}function l(t,e,o){var r=n.resolve(t);return arguments.length<2?r:r.then(e,o)}function d(t,n,e){return e=e||{},a(e)&&(e=e.call(n)),v(t.bind({$vm:n,$options:e}),t,{$options:e})}function m(t,n){var e,o;if("number"==typeof t.length)for(e=0;e=200&&i<300}return t.prototype.text=function(){return this.body},t.prototype.blob=function(){return new Blob([this.body])},t.prototype.json=function(){return JSON.parse(this.body)},t}(),dt=function(){function t(n){pt(this,t),this.method="GET",this.body=null,this.params={},this.headers={},st(this,n)}return t.prototype.getUrl=function(){return R(this)},t.prototype.getBody=function(){return this.body},t.prototype.respondWith=function(t,n){return new lt(t,st(n||{},{url:this.getUrl()}))},t}(),mt={"X-Requested-With":"XMLHttpRequest"},vt={Accept:"application/json, text/plain, */*"},yt={"Content-Type":"application/json;charset=utf-8"};return V.options={},V.headers={put:yt,post:yt,patch:yt,"delete":yt,custom:mt,common:vt},V.interceptors=[D,X,J,L,N,M,H],["get","delete","head","jsonp"].forEach(function(t){V[t]=function(n,e){return this(st(e||{},{url:n,method:t}))}}),["post","put","patch"].forEach(function(t){V[t]=function(n,e,o){return this(st(o||{},{url:n,method:t,body:e}))}}),_.actions={get:{method:"GET"},save:{method:"POST"},query:{method:"GET"},update:{method:"PUT"},remove:{method:"DELETE"},"delete":{method:"DELETE"}},"undefined"!=typeof window&&window.Vue&&window.Vue.use(K),K}); \ No newline at end of file +!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):t.VueResource=n()}(this,function(){"use strict";function t(t,n){t instanceof et?this.promise=t:this.promise=new et(t.bind(n)),this.context=n}function n(t){it=t.util,rt=t.config.debug||!t.config.silent}function e(t){"undefined"!=typeof console&&rt&&console.warn("[VueResource warn]: "+t)}function o(t){"undefined"!=typeof console&&console.error(t)}function r(t,n){return it.nextTick(t,n)}function i(t){return t.replace(/^\s*|\s*$/g,"")}function u(t){return t?t.toLowerCase():""}function s(t){return t?t.toUpperCase():""}function c(t){return"string"==typeof t}function a(t){return t===!0||t===!1}function f(t){return"function"==typeof t}function p(t){return null!==t&&"object"==typeof t}function h(t){return p(t)&&Object.getPrototypeOf(t)==Object.prototype}function l(t){return"undefined"!=typeof Blob&&t instanceof Blob}function d(t){return"undefined"!=typeof FormData&&t instanceof FormData}function m(n,e,o){var r=t.resolve(n);return arguments.length<2?r:r.then(e,o)}function y(t,n,e){return e=e||{},f(e)&&(e=e.call(n)),b(t.bind({$vm:n,$options:e}),t,{$options:e})}function v(t,n){var e,o;if(t&&"number"==typeof t.length)for(e=0;e=200&&i<300,this.status=i||0,this.statusText=u||"",this.headers=new dt(r),this.body=n,c(n)?this.bodyText=n:l(n)&&(this.bodyBlob=n,K(n)&&(this.bodyText=z(n)))}return t.prototype.blob=function(){return m(this.bodyBlob)},t.prototype.text=function(){return m(this.bodyText)},t.prototype.json=function(){return m(this.text(),function(t){return JSON.parse(t)})},t}(),yt=function(){function t(n){lt(this,t),this.body=null,this.params={},ct(this,n,{method:s(n.method||"GET"),headers:new dt(n.headers)})}return t.prototype.getUrl=function(){return S(this)},t.prototype.getBody=function(){return this.body},t.prototype.respondWith=function(t,n){return new mt(t,ct(n||{},{url:this.getUrl()}))},t}(),vt={"X-Requested-With":"XMLHttpRequest"},bt={Accept:"application/json, text/plain, */*"},wt={"Content-Type":"application/json;charset=utf-8"};Q.options={},Q.headers={put:wt,post:wt,patch:wt,delete:wt,custom:vt,common:bt},Q.interceptors=[D,F,M,q,J,X,L],["get","delete","head","jsonp"].forEach(function(t){Q[t]=function(n,e){return this(ct(e||{},{url:n,method:t}))}}),["post","put","patch"].forEach(function(t){Q[t]=function(n,e,o){return this(ct(o||{},{url:n,method:t,body:e}))}});var gt=0,Tt=1,xt=2;Y.reject=function(t){return new Y(function(n,e){e(t)})},Y.resolve=function(t){return new Y(function(n,e){n(t)})},Y.all=function(t){return new Y(function(n,e){function o(e){return function(o){i[e]=o,r+=1,r===t.length&&n(i)}}var r=0,i=[];0===t.length&&n(i);for(var u=0;u { - // success callback - }, (response) => { - // error callback - }); - - } - -}) +{ + // GET /someUrl + this.$http.get('/someUrl').then((response) => { + // success callback + }, (response) => { + // error callback + }); +} ``` ## Methods @@ -51,10 +45,10 @@ List of shortcut methods: Parameter | Type | Description --------- | ---- | ----------- url | `string` | URL to which the request is sent -method | `string` | HTTP method (e.g. GET, POST, ...) -body | `Object`, `FormData` `string` | Data to be sent as the request body -params | `Object` | Parameters object to be sent as URL parameters +body | `Object`, `FormData`, `string` | Data to be sent as the request body headers | `Object` | Headers object to be sent as HTTP request headers +params | `Object` | Parameters object to be sent as URL parameters +method | `string` | HTTP method (e.g. GET, POST, ...) timeout | `number` | Request timeout in milliseconds (`0` means no timeout) before | `function(request)` | Callback function to modify the request options before it is sent progress | `function(event)` | Callback function to handle the [ProgressEvent](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent) of uploads @@ -66,49 +60,58 @@ emulateJSON | `boolean` | Send request body as `application/x-www-form-urlencode A request resolves to a response object with the following properties and methods: -Method | Type | Description +Property | Type | Description -------- | ---- | ----------- -text() | `string` | Response body as string -json() | `Object` | Response body as parsed JSON object -blob() | `Blob` | Response body as Blob object -**Property** | **Type** | **Description** +url | `string` | Response URL origin +body | `Object`, `Blob`, `string` | Response body data +headers | `Header` | Response Headers object ok | `boolean` | HTTP status code between 200 and 299 status | `number` | HTTP status code of the response statusText | `string` | HTTP status text of the response -headers | `Object` | HTTP headers of the response +**Method** | **Type** | **Description** +text() | `Promise` | Resolves the body as string +json() | `Promise` | Resolves the body as parsed JSON object +blob() | `Promise` | Resolves the body as Blob object ## Example ```js -new Vue({ - - ready() { +{ + // POST /someUrl + this.$http.post('/someUrl', {foo: 'bar'}).then((response) => { - // POST /someUrl - this.$http.post('/someUrl', {foo: 'bar'}).then((response) => { + // get status + response.status; - // get status - response.status; + // get status text + response.statusText; - // get status text - response.statusText; + // get 'Expires' header + response.headers.get('Expires'); - // get all headers - response.headers; + // set data on vm + this.$set('someData', response.body); - // get 'Expires' header - response.headers['Expires']; + }, (response) => { + // error callback + }); +} +``` - // set data on vm - this.$set('someData', response.json()) +Fetch an image and use the blob() method to extract the image body content from the response. - }, (response) => { - // error callback - }); +```js +{ + // GET /image.jpg + this.$http.get('/image.jpg').then((response) => { - } + // resolve to Blob + return response.blob(); -}) + }).then(blob) => { + // use image Blob + }); +} ``` ## Interceptors @@ -119,11 +122,11 @@ Interceptors can be defined globally and are used for pre- and postprocessing of ```js Vue.http.interceptors.push((request, next) => { - // modify request - request.method = 'POST'; + // modify request + request.method = 'POST'; - // continue to next interceptor - next(); + // continue to next interceptor + next(); }); ``` @@ -131,16 +134,16 @@ Vue.http.interceptors.push((request, next) => { ```js Vue.http.interceptors.push((request, next) => { - // modify request - request.method = 'POST'; + // modify request + request.method = 'POST'; - // continue to next interceptor - next((response) => { + // continue to next interceptor + next((response) => { - // modify response - response.body = '...'; + // modify response + response.body = '...'; - }); + }); }); ``` @@ -148,12 +151,12 @@ Vue.http.interceptors.push((request, next) => { ```js Vue.http.interceptors.push((request, next) => { - // modify request ... + // modify request ... - // stop and return response - next(request.respondWith(body, { - status: 404, - statusText: 'Not found' - })); + // stop and return response + next(request.respondWith(body, { + status: 404, + statusText: 'Not found' + })); }); ``` diff --git a/docs/recipes.md b/docs/recipes.md index 0da6c0b5..201692db 100644 --- a/docs/recipes.md +++ b/docs/recipes.md @@ -8,20 +8,20 @@ Sending forms using [FormData](https://developer.mozilla.org/en-US/docs/Web/API/ ```js { - var formData = new FormData(); + var formData = new FormData(); - // append string - formData.append('foo', 'bar'); + // append string + formData.append('foo', 'bar'); - // append Blob/File object - formData.append('pic', fileInput, 'mypic.jpg'); + // append Blob/File object + formData.append('pic', fileInput, 'mypic.jpg'); - // POST /someUrl - this.$http.post('/someUrl', formData).then((response) => { - // success callback - }, (response) => { - // error callback - }); + // POST /someUrl + this.$http.post('/someUrl', formData).then((response) => { + // success callback + }, (response) => { + // error callback + }); } ``` @@ -31,25 +31,25 @@ Abort a previous request when a new request is about to be sent. For example whe ```js { - // GET /someUrl - this.$http.get('/someUrl', { - - // use before callback - before(request) { - - // abort previous request, if exists - if (this.previousRequest) { - this.previousRequest.abort(); - } - - // set previous request on Vue instance - this.previousRequest = request; - } - - }).then((response) => { - // success callback - }, (response) => { - // error callback - }); + // GET /someUrl + this.$http.get('/someUrl', { + + // use before callback + before(request) { + + // abort previous request, if exists + if (this.previousRequest) { + this.previousRequest.abort(); + } + + // set previous request on Vue instance + this.previousRequest = request; + } + + }).then((response) => { + // success callback + }, (response) => { + // error callback + }); } ``` diff --git a/docs/resource.md b/docs/resource.md index 7834f589..cc390fd1 100644 --- a/docs/resource.md +++ b/docs/resource.md @@ -20,63 +20,51 @@ delete: {method: 'DELETE'} ## Example ```js -new Vue({ - - ready() { - - var resource = this.$resource('someItem{/id}'); - - // GET someItem/1 - resource.get({id: 1}).then((response) => { - this.$set('item', response.json()) - }); - - // POST someItem/1 - resource.save({id: 1}, {item: this.item}).then((response) => { - // success callback - }, (response) => { - // error callback - }); - - // DELETE someItem/1 - resource.delete({id: 1}).then((response) => { - // success callback - }, (response) => { - // error callback - }); - - } - -}) +{ + var resource = this.$resource('someItem{/id}'); + + // GET someItem/1 + resource.get({id: 1}).then((response) => { + this.$set('item', response.json()) + }); + + // POST someItem/1 + resource.save({id: 1}, {item: this.item}).then((response) => { + // success callback + }, (response) => { + // error callback + }); + + // DELETE someItem/1 + resource.delete({id: 1}).then((response) => { + // success callback + }, (response) => { + // error callback + }); +} ``` ## Custom Actions ```js -new Vue({ - - ready() { - - var customActions = { - foo: {method: 'GET', url: 'someItem/foo{/id}'}, - bar: {method: 'POST', url: 'someItem/bar{/id}'} - } - - var resource = this.$resource('someItem{/id}', {}, customActions); - - // GET someItem/foo/1 - resource.foo({id: 1}).then((response) => { - this.$set('item', response.json()) - }); - - // POST someItem/bar/1 - resource.bar({id: 1}, {item: this.item}).then((response) => { - // success callback - }, (response) => { - // error callback - }); - - } - -}) +{ + var customActions = { + foo: {method: 'GET', url: 'someItem/foo{/id}'}, + bar: {method: 'POST', url: 'someItem/bar{/id}'} + } + + var resource = this.$resource('someItem{/id}', {}, customActions); + + // GET someItem/foo/1 + resource.foo({id: 1}).then((response) => { + this.$set('item', response.json()) + }); + + // POST someItem/bar/1 + resource.bar({id: 1}, {item: this.item}).then((response) => { + // success callback + }, (response) => { + // error callback + }); +} ``` diff --git a/package.json b/package.json index 6f71c44a..0d393eda 100644 --- a/package.json +++ b/package.json @@ -1,42 +1,42 @@ { "name": "vue-resource", - "version": "0.9.3", - "description": "A web request service for Vue.js", + "version": "1.0.0", "main": "dist/vue-resource.common.js", "jsnext:main": "dist/vue-resource.es2015.js", - "scripts": { - "test": "webpack --config test/webpack.config.js", - "build": "node build/build.js", - "release": "node build/release.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/vuejs/vue-resource.git" - }, + "description": "The HTTP client for Vue.js", + "homepage": "https://github.com/vuejs/vue-resource#readme", + "license": "MIT", "keywords": [ "vue", - "vuejs", - "resource", - "mvvm" + "xhr", + "http", + "ajax" ], - "license": "MIT", "bugs": { "url": "https://github.com/vuejs/vue-resource/issues" }, - "homepage": "https://github.com/vuejs/vue-resource#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/vuejs/vue-resource.git" + }, + "scripts": { + "test": "webpack --config test/webpack.config.js", + "build": "node build/build.js", + "release": "node build/release.js" + }, "devDependencies": { - "babel-core": "^6.10.4", - "babel-loader": "^6.2.4", - "babel-plugin-transform-runtime": "^6.9.0", - "babel-preset-es2015-loose": "^7.0.0", + "babel-core": "^6.14.0", + "babel-loader": "^6.2.5", + "babel-plugin-transform-runtime": "^6.15.0", + "babel-preset-es2015": "^6.14.0", "babel-preset-es2015-loose-rollup": "^7.0.0", - "babel-runtime": "^6.9.2", - "jasmine-core": "^2.3.4", - "replace-in-file": "^1.1.1", - "rollup": "^0.33.0", + "generate-release": "^0.10.1", + "jasmine-core": "^2.5.0", + "replace-in-file": "^2.0.1", + "rollup": "^0.34.13", "rollup-plugin-babel": "^2.6.1", - "uglify-js": "^2.6.4", + "uglify-js": "^2.7.3", "vue": "^1.0.26", - "webpack": "^1.13.1" + "webpack": "2.1.0-beta.21" } } diff --git a/src/http/client/xhr.js b/src/http/client/xhr.js index 61ea7bc0..87ad48ac 100644 --- a/src/http/client/xhr.js +++ b/src/http/client/xhr.js @@ -3,7 +3,7 @@ */ import Promise from '../../promise'; -import { each, trim, isArray } from '../../util'; +import { each, trim } from '../../util'; export default function (request) { return new Promise((resolve) => { @@ -13,11 +13,14 @@ export default function (request) { var response = request.respondWith( 'response' in xhr ? xhr.response : xhr.responseText, { status: xhr.status === 1223 ? 204 : xhr.status, // IE9 status bug - statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText), - headers: parseHeaders(xhr.getAllResponseHeaders()), + statusText: xhr.status === 1223 ? 'No Content' : trim(xhr.statusText) } ); + each(trim(xhr.getAllResponseHeaders()).split('\n'), (row) => { + response.headers.append(row.slice(0, row.indexOf(':')), row.slice(row.indexOf(':') + 1)); + }); + resolve(response); }; @@ -36,42 +39,18 @@ export default function (request) { } } + if ('responseType' in xhr) { + xhr.responseType = 'blob'; + } + if (request.credentials === true) { xhr.withCredentials = true; } - each(request.headers || {}, (value, header) => { - xhr.setRequestHeader(header, value); + request.headers.forEach((value, name) => { + xhr.setRequestHeader(name, value); }); xhr.send(request.getBody()); }); } - -function parseHeaders(str) { - - var headers = {}, value, name, i; - - each(trim(str).split('\n'), (row) => { - - i = row.indexOf(':'); - name = trim(row.slice(0, i)); - value = trim(row.slice(i + 1)); - - if (headers[name]) { - - if (isArray(headers[name])) { - headers[name].push(value); - } else { - headers[name] = [headers[name], value]; - } - - } else { - - headers[name] = value; - } - - }); - - return headers; -} diff --git a/src/http/headers.js b/src/http/headers.js new file mode 100644 index 00000000..b758d0e0 --- /dev/null +++ b/src/http/headers.js @@ -0,0 +1,65 @@ +/** + * HTTP Headers. + */ + +import { each, trim, toLower } from '../util'; + +export default class Headers { + + constructor(headers) { + + this.map = {}; + + each(headers, (value, name) => this.append(name, value)); + } + + has(name) { + return this.map.hasOwnProperty(normalizeName(name)); + } + + get(name) { + + var list = this.map[normalizeName(name)]; + + return list ? list[0] : null; + } + + getAll(name) { + return this.map[normalizeName(name)] || []; + } + + set(name, value) { + this.map[normalizeName(name)] = [trim(value)]; + } + + append(name, value){ + + var list = this.map[normalizeName(name)]; + + if (!list) { + list = this.map[normalizeName(name)] = []; + } + + list.push(trim(value)); + } + + delete(name){ + delete this.map[normalizeName(name)]; + } + + forEach(callback, thisArg) { + each(this.map, (list, name) => { + each(list, value => callback.call(thisArg, value, name, this)); + }); + } + +} + +function normalizeName(name) { + + if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) { + throw new TypeError('Invalid character in header field name'); + } + + return toLower(trim(name)); +} diff --git a/src/http/interceptor/body.js b/src/http/interceptor/body.js index e71c3947..583a0d88 100644 --- a/src/http/interceptor/body.js +++ b/src/http/interceptor/body.js @@ -3,17 +3,17 @@ */ import Url from '../../url/index'; -import { isString, isFormData, isPlainObject } from '../../util'; +import { when, isString, isFormData, isPlainObject } from '../../util'; export default function (request, next) { if (request.emulateJSON && isPlainObject(request.body)) { request.body = Url.params(request.body); - request.headers['Content-Type'] = 'application/x-www-form-urlencoded'; + request.headers.set('Content-Type', 'application/x-www-form-urlencoded'); } if (isFormData(request.body)) { - delete request.headers['Content-Type']; + request.headers.delete('Content-Type'); } if (isPlainObject(request.body)) { @@ -22,19 +22,37 @@ export default function (request, next) { next((response) => { - var contentType = response.headers['Content-Type']; + Object.defineProperty(response, 'data', { - if (isString(contentType) && contentType.indexOf('application/json') === 0) { + get() { + return this.body; + }, - try { - response.data = response.json(); - } catch (e) { - response.data = null; + set(body) { + this.body = body; } - } else { - response.data = response.text(); - } + }); + + return response.bodyText ? when(response.text(), text => { + + var type = response.headers.get('Content-Type'); + + if (isString(type) && type.indexOf('application/json') === 0) { + + try { + response.body = JSON.parse(text); + } catch (e) { + response.body = null; + } + + } else { + response.body = text; + } + + return response; + + }) : response; }); } diff --git a/src/http/interceptor/header.js b/src/http/interceptor/header.js index 8d2e4eb1..193b8db2 100644 --- a/src/http/interceptor/header.js +++ b/src/http/interceptor/header.js @@ -3,16 +3,20 @@ */ import Http from '../index'; -import { assign } from '../../util'; +import { assign, each, toLower } from '../../util'; export default function (request, next) { - request.method = request.method.toUpperCase(); - request.headers = assign({}, Http.headers.common, + var headers = assign({}, Http.headers.common, !request.crossOrigin ? Http.headers.custom : {}, - Http.headers[request.method.toLowerCase()], - request.headers + Http.headers[toLower(request.method)] ); + each(headers, (value, name) => { + if (!request.headers.has(name)) { + request.headers.set(name, value); + } + }); + next(); } diff --git a/src/http/interceptor/jsonp.js b/src/http/interceptor/jsonp.js index ab92da94..160c508a 100644 --- a/src/http/interceptor/jsonp.js +++ b/src/http/interceptor/jsonp.js @@ -3,6 +3,7 @@ */ import jsonpClient from '../client/jsonp'; +import { when } from '../../util'; export default function (request, next) { @@ -13,7 +14,13 @@ export default function (request, next) { next((response) => { if (request.method == 'JSONP') { - response.data = response.json(); + + return when(response.json(), json => { + + response.body = json; + + return response; + }); } }); diff --git a/src/http/interceptor/method.js b/src/http/interceptor/method.js index 8489e98c..ad393ce2 100644 --- a/src/http/interceptor/method.js +++ b/src/http/interceptor/method.js @@ -5,7 +5,7 @@ export default function (request, next) { if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { - request.headers['X-HTTP-Method-Override'] = request.method; + request.headers.set('X-HTTP-Method-Override', request.method); request.method = 'POST'; } diff --git a/src/http/request.js b/src/http/request.js index cd7c41c2..070afa42 100644 --- a/src/http/request.js +++ b/src/http/request.js @@ -3,19 +3,21 @@ */ import Url from '../url/index'; +import Headers from './headers'; import Response from './response'; -import { assign } from '../util'; +import { assign, toUpper } from '../util'; export default class Request { constructor(options) { - this.method = 'GET'; this.body = null; this.params = {}; - this.headers = {}; - assign(this, options); + assign(this, options, { + method: toUpper(options.method || 'GET'), + headers: new Headers(options.headers) + }); } getUrl(){ diff --git a/src/http/response.js b/src/http/response.js index 2de5519b..8c5792d9 100644 --- a/src/http/response.js +++ b/src/http/response.js @@ -2,29 +2,62 @@ * HTTP Response. */ +import Headers from './headers'; +import Promise from '../promise'; +import { when, isBlob, isString } from '../util'; + export default class Response { constructor(body, {url, headers, status, statusText}) { this.url = url; - this.body = body; - this.headers = headers || {}; + this.ok = status >= 200 && status < 300; this.status = status || 0; this.statusText = statusText || ''; - this.ok = status >= 200 && status < 300; + this.headers = new Headers(headers); + this.body = body; - } + if (isString(body)) { - text() { - return this.body; + this.bodyText = body; + + } else if (isBlob(body)) { + + this.bodyBlob = body; + + if (isBlobText(body)) { + this.bodyText = blobText(body); + } + } } blob() { - return new Blob([this.body]); + return when(this.bodyBlob); + } + + text() { + return when(this.bodyText); } json() { - return JSON.parse(this.body); + return when(this.text(), text => JSON.parse(text)); } } + +function blobText(body) { + return new Promise((resolve) => { + + var reader = new FileReader(); + + reader.readAsText(body); + reader.onload = () => { + resolve(reader.result); + }; + + }); +} + +function isBlobText(body) { + return body.type.indexOf('text') === 0 || body.type.indexOf('json') !== -1; +} diff --git a/src/index.js b/src/index.js index fb4a40af..8c68e092 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,7 @@ import Url from './url/index'; import Http from './http/index'; import Promise from './promise'; +import PromiseLib from './lib/promise'; import Resource from './resource'; import Util, { options } from './util'; @@ -50,8 +51,16 @@ function plugin(Vue) { }); } -if (typeof window !== 'undefined' && window.Vue) { - window.Vue.use(plugin); +if (typeof window !== 'undefined') { + + if (!window.Promise) { + window.Promise = PromiseLib; + } + + if (window.Vue) { + window.Vue.use(plugin); + } + } export default plugin; diff --git a/src/promise.js b/src/promise.js index 1286acef..83acdc7d 100644 --- a/src/promise.js +++ b/src/promise.js @@ -2,9 +2,7 @@ * Promise adapter. */ -import PromiseLib from './lib/promise'; - -var PromiseObj = window.Promise || PromiseLib; +var PromiseObj = window.Promise; export default function Promise(executor, context) { diff --git a/src/resource.js b/src/resource.js index a79fdd8b..dd90d8df 100644 --- a/src/resource.js +++ b/src/resource.js @@ -16,7 +16,7 @@ export default function Resource(url, params, actions, options) { each(actions, (action, name) => { - action = merge({url, params: params || {}}, options, action); + action = merge({url, params: assign({}, params)}, options, action); resource[name] = function () { return (self.$http || Http)(opts(action, arguments)); diff --git a/src/util.js b/src/util.js index b252621a..33b4ded6 100644 --- a/src/util.js +++ b/src/util.js @@ -4,7 +4,7 @@ import Promise from './promise'; -var debug = false, util = {}, array = []; +var debug = false, util = {}, { slice } = []; export default function (Vue) { util = Vue.util; @@ -31,6 +31,14 @@ export function trim(str) { return str.replace(/^\s*|\s*$/g, ''); } +export function toLower(str) { + return str ? str.toLowerCase() : ''; +} + +export function toUpper(str) { + return str ? str.toUpperCase() : ''; +} + export const isArray = Array.isArray; export function isString(val) { @@ -53,6 +61,10 @@ export function isPlainObject(obj) { return isObject(obj) && Object.getPrototypeOf(obj) == Object.prototype; } +export function isBlob(obj) { + return typeof Blob !== 'undefined' && obj instanceof Blob; +} + export function isFormData(obj) { return typeof FormData !== 'undefined' && obj instanceof FormData; } @@ -83,7 +95,7 @@ export function each(obj, iterator) { var i, key; - if (typeof obj.length == 'number') { + if (obj && typeof obj.length == 'number') { for (i = 0; i < obj.length; i++) { iterator.call(obj[i], obj[i], i); } @@ -102,7 +114,7 @@ export const assign = Object.assign || _assign; export function merge(target) { - var args = array.slice.call(arguments, 1); + var args = slice.call(arguments, 1); args.forEach((source) => { _merge(target, source, true); @@ -113,7 +125,7 @@ export function merge(target) { export function defaults(target) { - var args = array.slice.call(arguments, 1); + var args = slice.call(arguments, 1); args.forEach((source) => { @@ -130,7 +142,7 @@ export function defaults(target) { function _assign(target) { - var args = array.slice.call(arguments, 1); + var args = slice.call(arguments, 1); args.forEach((source) => { _merge(target, source); diff --git a/test/http.js b/test/http.js index ae201b2f..f0262157 100644 --- a/test/http.js +++ b/test/http.js @@ -8,10 +8,9 @@ describe('Vue.http', function () { expect(res.ok).toBe(true); expect(res.status).toBe(200); - expect(res.data).toBe('text'); - expect(res.blob() instanceof Blob).toBe(true); - expect(res.headers['Content-Type']).toBe('text/plain'); - expect(res.headers['Content-Length']).toBe('4'); + expect(res.body).toBe('text'); + expect(res.headers.get('Content-Type')).toBe('text/plain'); + expect(res.headers.get('Content-Length')).toBe('4'); done(); }); @@ -24,8 +23,8 @@ describe('Vue.http', function () { expect(res.ok).toBe(true); expect(res.status).toBe(200); - expect(res.data.foo).toBe('bar'); - expect(typeof res.json()).toBe('object'); + expect(typeof res.body).toBe('object'); + expect(res.body.foo).toBe('bar'); done(); }); @@ -38,7 +37,21 @@ describe('Vue.http', function () { expect(res.ok).toBe(true); expect(res.status).toBe(200); - expect(res.data).toBeNull(); + expect(res.body).toBeNull(); + + done(); + }); + + }); + + it('get("github.com/avatar")', (done) => { + + Vue.http.get('https://avatars1.githubusercontent.com/u/6128107').then((res) => { + + expect(res.ok).toBe(true); + expect(res.status).toBe(200); + expect(res.body instanceof Blob).toBe(true); + expect(res.body.type).toBe('image/png'); done(); }); @@ -51,9 +64,9 @@ describe('Vue.http', function () { expect(res.ok).toBe(true); expect(res.status).toBe(200); - expect(res.data.shift().requestType).toBe('cors'); - expect(res.headers['Content-Type']).toBe('application/json'); - expect(typeof res.json()).toBe('object'); + expect(typeof res.body).toBe('object'); + expect(res.body.shift().requestType).toBe('cors'); + expect(res.headers.get('Content-Type')).toBe('application/json'); done(); }); @@ -66,8 +79,8 @@ describe('Vue.http', function () { expect(res.ok).toBe(true); expect(res.status).toBe(200); - expect(res.data.foo).toBe('bar'); - expect(typeof res.json()).toBe('object'); + expect(typeof res.body).toBe('object'); + expect(res.body.foo).toBe('bar'); done(); }); @@ -89,8 +102,8 @@ describe('this.$http', function () { expect(this).toBe(vm); expect(res.ok).toBe(true); expect(res.status).toBe(200); - expect(res.data.foo).toBe('bar'); - expect(typeof res.json()).toBe('object'); + expect(typeof res.body).toBe('object'); + expect(res.body.foo).toBe('bar'); done(); diff --git a/test/webpack.config.js b/test/webpack.config.js index e5022a69..a7c5910c 100644 --- a/test/webpack.config.js +++ b/test/webpack.config.js @@ -6,7 +6,7 @@ module.exports = { }, module: { loaders: [ - {test: /.js/, exclude: /node_modules/, loader: 'babel', query: {presets: ['es2015-loose']}} + {test: /.js/, exclude: /node_modules/, loader: 'babel', query: {presets: [['es2015', {modules: false}]]}} ] } };