Repository: pagekit/vue-resource Branch: develop Commit: 1b2d0c94e0b5 Files: 64 Total size: 174.9 KB Directory structure: gitextract_idl7migu/ ├── .babelrc.js ├── .circleci/ │ └── config.yml ├── .eslintignore ├── .eslintrc.js ├── .github/ │ └── ISSUE_TEMPLATE.md ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── bower.json ├── build/ │ ├── build.js │ └── release.js ├── dist/ │ ├── README.md │ ├── vue-resource.common.js │ ├── vue-resource.esm.js │ └── vue-resource.js ├── docs/ │ ├── README.md │ ├── api.md │ ├── config.md │ ├── http.md │ ├── recipes.md │ └── resource.md ├── package.json ├── src/ │ ├── http/ │ │ ├── client/ │ │ │ ├── index.js │ │ │ ├── jsonp.js │ │ │ ├── node.js │ │ │ ├── xdr.js │ │ │ └── xhr.js │ │ ├── headers.js │ │ ├── index.js │ │ ├── interceptor/ │ │ │ ├── before.js │ │ │ ├── cors.js │ │ │ ├── form.js │ │ │ ├── header.js │ │ │ ├── json.js │ │ │ ├── jsonp.js │ │ │ └── method.js │ │ ├── request.js │ │ └── response.js │ ├── index.js │ ├── lib/ │ │ ├── promise.js │ │ └── url-template.js │ ├── promise.js │ ├── resource.js │ ├── url/ │ │ ├── index.js │ │ ├── query.js │ │ ├── root.js │ │ └── template.js │ └── util.js ├── test/ │ ├── data/ │ │ ├── invalid.json │ │ ├── text.txt │ │ └── valid.json │ ├── http.js │ ├── http.test.js │ ├── index.html │ ├── index.js │ ├── karma.conf.js │ ├── promise.js │ ├── resource.js │ ├── url.js │ └── webpack.config.js └── types/ ├── index.d.ts ├── vue.d.ts └── vue_resource.ts ================================================ FILE CONTENTS ================================================ ================================================ FILE: .babelrc.js ================================================ module.exports = { presets: [ ['@babel/preset-env', { loose: true, modules: false }] ] }; ================================================ FILE: .circleci/config.yml ================================================ version: 2 defaults: &defaults docker: - image: circleci/node:14-browsers environment: CHROME_BIN: /usr/bin/google-chrome working_directory: ~/vue-resource jobs: build: <<: *defaults steps: - checkout - restore_cache: key: yarn-{{ checksum "yarn.lock" }} - run: name: Install Dependencies command: yarn --pure-lockfile - run: name: Run Tests command: | yarn test yarn karma --browsers Chrome - run: name: Build Release command: yarn build - save_cache: key: yarn-{{ checksum "yarn.lock" }} paths: - ./node_modules ================================================ FILE: .eslintignore ================================================ /node_modules /dist /test ================================================ FILE: .eslintrc.js ================================================ module.exports = { "root":true, "env": { "es6": true, "browser": true, "commonjs": true, }, "extends": [ "eslint:recommended" ], "parserOptions": { "sourceType": "module" }, "rules": { "brace-style": ["error", "1tbs", {"allowSingleLine": true}], "comma-style": "error", "comma-spacing": "error", "eqeqeq": ["off", "smart"], "indent": "off", "indent-legacy": ["error", 4, {"SwitchCase": 1}], "key-spacing": "error", "keyword-spacing": "error", "linebreak-style": ["error", "unix"], "no-multi-spaces": "error", "no-trailing-spaces": "error", "no-lone-blocks": "error", "no-extend-native": "error", "no-unused-vars": ["error", {"vars": "local", "args": "none"}], "no-empty": ["error", {"allowEmptyCatch": true}], "no-duplicate-imports": "error", "no-array-constructor": "error", "no-multiple-empty-lines": "error", "no-template-curly-in-string": "error", "no-console": "off", "object-curly-spacing": "error", "quotes": ["error", "single", {"avoidEscape": true}], "semi": ["error", "always"], "space-infix-ops": "error", "space-unary-ops": "error", "space-in-parens": "error", "space-before-blocks": "error", "template-curly-spacing": "error" } }; ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ ### Reproduction Link ### Steps to reproduce ### What is Expected? ### What is actually happening? ================================================ FILE: .gitignore ================================================ /node_modules /test/specs.js .DS_Store ================================================ FILE: .npmignore ================================================ build docs bower.json ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015-2017 steffans Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # vue-resource [![Build](https://circleci.com/gh/pagekit/vue-resource.svg?style=shield)](https://circleci.com/gh/pagekit/vue-resource) [![Downloads](https://img.shields.io/npm/dm/vue-resource.svg)](https://www.npmjs.com/package/vue-resource) [![jsdelivr](https://data.jsdelivr.com/v1/package/npm/vue-resource/badge?style=rounded)](https://www.jsdelivr.com/package/npm/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. ## Features - 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+ - Supports Vue 1.0 & Vue 2.0 - Compact size 14KB (5.3KB gzipped) ## Installation You can install it via [yarn](https://yarnpkg.com/) or [NPM](http://npmjs.org/). ``` $ yarn add vue-resource $ npm install vue-resource ``` ### CDN Available on [jsdelivr](https://cdn.jsdelivr.net/npm/vue-resource@1.5.3), [unpkg](https://unpkg.com/vue-resource@1.5.3) or [cdnjs](https://cdnjs.com/libraries/vue-resource). ```html ``` ## Example ```js { // GET /someUrl this.$http.get('/someUrl').then(response => { // get body data this.someData = response.body; }, response => { // error callback }); } ``` ## Documentation - [Configuration](docs/config.md) - [HTTP Requests/Response](docs/http.md) - [Creating Resources](docs/resource.md) - [Code Recipes](docs/recipes.md) - [API Reference](docs/api.md) ## Changelog Details changes for each release are documented in the [release notes](https://github.com/pagekit/vue-resource/releases). ## Contribution If you find a bug or want to contribute to the code or documentation, you can help by submitting an [issue](https://github.com/pagekit/vue-resource/issues) or a [pull request](https://github.com/pagekit/vue-resource/pulls). ## License [MIT](http://opensource.org/licenses/MIT) ================================================ FILE: bower.json ================================================ { "name": "vue-resource", "main": "dist/vue-resource.js", "version": "1.5.3", "description": "The HTTP client for Vue.js", "homepage": "https://github.com/pagekit/vue-resource", "license": "MIT", "keywords": [ "vue", "xhr", "http", "ajax" ], "ignore": [ ".*", "build", "docs", "package.json" ] } ================================================ FILE: build/build.js ================================================ /* eslint-env node */ const fs = require('fs'); const zlib = require('zlib'); const rollup = require('rollup'); const uglify = require('uglify-js'); const babel = require('rollup-plugin-babel'); const replace = require('rollup-plugin-replace'); const {name, version, homepage} = require('../package.json'); const banner = `/*!\n * ${name} v${version}\n * ${homepage}\n * Released under the MIT License.\n */\n`; rollup.rollup({ input: 'src/index.js', plugins: [babel(), replace({__VERSION__: version})] }) .then(bundle => bundle.generate({ banner, format: 'umd', name: 'VueResource' }).then(({code}) => write(`dist/${name}.js`, code, bundle)) ) .then(bundle => write(`dist/${name}.min.js`, banner + '\n' + uglify.minify(read(`dist/${name}.js`)).code, bundle, true) ) .then(bundle => bundle.generate({ banner, format: 'es', footer: 'export { Url, Http, Resource };' }).then(({code}) => write(`dist/${name}.esm.js`, code, bundle)) ) .then(bundle => bundle.generate({ banner, format: 'cjs' }).then(({code}) => write(`dist/${name}.common.js`, code, bundle)) ) .catch(logError); function read(path) { return fs.readFileSync(path, 'utf8'); } function write(dest, code, bundle, zip) { return new Promise((resolve, reject) => { fs.writeFile(dest, code, err => { if (err) return reject(err); if (zip) { zlib.gzip(code, (err, zipped) => { if (err) return reject(err); console.log(blue(dest) + ' ' + getSize(code) + ' (' + getSize(zipped) + ' gzipped)'); }); } else { console.log(blue(dest) + ' ' + getSize(code)); } resolve(bundle); }); }); } function getSize(code) { return (code.length / 1024).toFixed(2) + 'kb'; } function logError(e) { console.log(e); } function blue(str) { return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'; } ================================================ FILE: build/release.js ================================================ /* eslint-env node */ var replace = require('replace-in-file'); var version = process.argv[2]; replace({ files: 'bower.json', from: /("version"\s*:\s*")\d+\.\d+\.\d+("\s*,)/g, to: '$1' + version + '$2' }); replace({ files: 'package.json', from: /("version"\s*:\s*")\d+\.\d+\.\d+("\s*,)/g, to: '$1' + version + '$2' }); replace({ files: 'README.md', from: /(\/|@)\d+\.\d+\.\d+/g, to: '$1' + version }); ================================================ FILE: dist/README.md ================================================ # NOTE! The `dist` folder contains the standalone build for vue-resource, however files here are only checked-in when a release happens. If you are on the `dev` branch, files here are **NOT** up to date. Only the `master` branch contains the built files for the latest stable version. ================================================ FILE: dist/vue-resource.common.js ================================================ /*! * vue-resource v1.5.3 * https://github.com/pagekit/vue-resource * Released under the MIT License. */ 'use strict'; /** * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) */ var RESOLVED = 0; var REJECTED = 1; var PENDING = 2; function Promise$1(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$1.reject = function (r) { return new Promise$1(function (resolve, reject) { reject(r); }); }; Promise$1.resolve = function (x) { return new Promise$1(function (resolve, reject) { resolve(x); }); }; Promise$1.all = function all(iterable) { return new Promise$1(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$1.resolve(iterable[i]).then(resolver(i), reject); } }); }; Promise$1.race = function race(iterable) { return new Promise$1(function (resolve, reject) { for (var i = 0; i < iterable.length; i += 1) { Promise$1.resolve(iterable[i]).then(resolve, reject); } }); }; var p = Promise$1.prototype; p.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.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.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.then = function then(onResolved, onRejected) { var promise = this; return new Promise$1(function (resolve, reject) { promise.deferred.push([onResolved, onRejected, resolve, reject]); promise.notify(); }); }; p["catch"] = function (onRejected) { return this.then(undefined, onRejected); }; /** * Promise adapter. */ if (typeof Promise === 'undefined') { window.Promise = Promise$1; } function PromiseObj(executor, context) { if (executor instanceof Promise) { this.promise = executor; } else { this.promise = new Promise(executor.bind(context)); } this.context = context; } PromiseObj.all = function (iterable, context) { return new PromiseObj(Promise.all(iterable), context); }; PromiseObj.resolve = function (value, context) { return new PromiseObj(Promise.resolve(value), context); }; PromiseObj.reject = function (reason, context) { return new PromiseObj(Promise.reject(reason), context); }; PromiseObj.race = function (iterable, context) { return new PromiseObj(Promise.race(iterable), context); }; var p$1 = PromiseObj.prototype; p$1.bind = function (context) { this.context = context; return this; }; p$1.then = function (fulfilled, rejected) { if (fulfilled && fulfilled.bind && this.context) { fulfilled = fulfilled.bind(this.context); } if (rejected && rejected.bind && this.context) { rejected = rejected.bind(this.context); } return new PromiseObj(this.promise.then(fulfilled, rejected), this.context); }; p$1["catch"] = function (rejected) { if (rejected && rejected.bind && this.context) { rejected = rejected.bind(this.context); } return new PromiseObj(this.promise["catch"](rejected), this.context); }; p$1["finally"] = function (callback) { return this.then(function (value) { callback.call(this); return value; }, function (reason) { callback.call(this); return Promise.reject(reason); }); }; /** * Utility functions. */ var _ref = {}, hasOwnProperty = _ref.hasOwnProperty, slice = [].slice, debug = false, ntick; var inBrowser = typeof window !== 'undefined'; function Util (_ref2) { var config = _ref2.config, nextTick = _ref2.nextTick; ntick = nextTick; debug = config.debug || !config.silent; } function warn(msg) { if (typeof console !== 'undefined' && debug) { console.warn('[VueResource warn]: ' + msg); } } function error(msg) { if (typeof console !== 'undefined') { console.error(msg); } } function nextTick(cb, ctx) { return ntick(cb, ctx); } function trim(str) { return str ? str.replace(/^\s*|\s*$/g, '') : ''; } function trimEnd(str, chars) { if (str && chars === undefined) { return str.replace(/\s+$/, ''); } if (!str || !chars) { return str; } return str.replace(new RegExp("[" + chars + "]+$"), ''); } function toLower(str) { return str ? str.toLowerCase() : ''; } function toUpper(str) { return str ? str.toUpperCase() : ''; } var isArray = Array.isArray; function isString(val) { return typeof val === 'string'; } function isFunction(val) { return typeof val === 'function'; } function isObject(obj) { return obj !== null && typeof obj === 'object'; } 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; } function when(value, fulfilled, rejected) { var promise = PromiseObj.resolve(value); if (arguments.length < 2) { return promise; } return promise.then(fulfilled, rejected); } function options(fn, obj, opts) { opts = opts || {}; if (isFunction(opts)) { opts = opts.call(obj); } return merge(fn.bind({ $vm: obj, $options: opts }), fn, { $options: opts }); } function each(obj, iterator) { var i, key; if (isArray(obj)) { for (i = 0; i < obj.length; i++) { iterator.call(obj[i], obj[i], i); } } else if (isObject(obj)) { for (key in obj) { if (hasOwnProperty.call(obj, key)) { iterator.call(obj[key], obj[key], key); } } } return obj; } var assign = Object.assign || _assign; function merge(target) { var args = slice.call(arguments, 1); args.forEach(function (source) { _merge(target, source, true); }); return target; } function defaults(target) { var args = slice.call(arguments, 1); args.forEach(function (source) { for (var key in source) { if (target[key] === undefined) { target[key] = source[key]; } } }); return target; } function _assign(target) { var args = slice.call(arguments, 1); args.forEach(function (source) { _merge(target, source); }); 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]; } } } /** * Root Prefix Transform. */ function root (options$$1, next) { var url = next(options$$1); if (isString(options$$1.root) && !/^(https?:)?\//.test(url)) { url = trimEnd(options$$1.root, '/') + '/' + url; } return url; } /** * Query Parameter Transform. */ function query (options$$1, next) { var urlParams = Object.keys(Url.options.params), query = {}, url = next(options$$1); each(options$$1.params, function (value, key) { if (urlParams.indexOf(key) === -1) { query[key] = value; } }); query = Url.params(query); if (query) { url += (url.indexOf('?') == -1 ? '?' : '&') + query; } return url; } /** * URL Template v2.0.6 (https://github.com/bramstein/url-template) */ function expand(url, params, variables) { var tmpl = parse(url), expanded = tmpl.expand(params); if (variables) { variables.push.apply(variables, tmpl.vars); } return expanded; } function parse(template) { var operators = ['+', '#', '.', '/', ';', '?', '&'], variables = []; return { vars: variables, expand: function expand(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(''); } } return result; } function isDefined(value) { return value !== undefined && value !== null; } function isKeyOperator(operator) { return operator === ';' || operator === '&' || operator === '?'; } function encodeValue(operator, value, key) { value = operator === '+' || operator === '#' ? encodeReserved(value) : encodeURIComponent(value); 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. */ function template (options) { var variables = [], url = expand(options.url, options.params, variables); variables.forEach(function (key) { delete options.params[key]; }); return url; } /** * Service for URL templating. */ function Url(url, params) { var self = this || {}, options$$1 = url, transform; if (isString(url)) { options$$1 = { url: url, params: params }; } options$$1 = merge({}, Url.options, self.$options, options$$1); Url.transforms.forEach(function (handler) { if (isString(handler)) { handler = Url.transform[handler]; } if (isFunction(handler)) { transform = factory(handler, transform, self.$vm); } }); return transform(options$$1); } /** * Url options. */ Url.options = { url: '', root: null, params: {} }; /** * Url transforms. */ Url.transform = { template: template, query: query, root: root }; Url.transforms = ['template', 'query', 'root']; /** * Encodes a Url parameter string. * * @param {Object} obj */ Url.params = function (obj) { var params = [], escape = encodeURIComponent; params.add = function (key, value) { if (isFunction(value)) { value = value(); } if (value === null) { value = ''; } this.push(escape(key) + '=' + escape(value)); }; serialize(params, obj); return params.join('&').replace(/%20/g, '+'); }; /** * Parse a URL and return its components. * * @param {String} url */ Url.parse = function (url) { var el = document.createElement('a'); if (document.documentMode) { el.href = url; url = el.href; } 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$$1) { return handler.call(vm, options$$1, 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). */ function xdrClient (request) { return new PromiseObj(function (resolve) { var xdr = new XDomainRequest(), handler = function handler(_ref) { var type = _ref.type; var status = 0; if (type === 'load') { status = 200; } else if (type === 'error') { status = 500; } resolve(request.respondWith(xdr.responseText, { status: status })); }; request.abort = function () { return xdr.abort(); }; xdr.open(request.method, request.getUrl()); if (request.timeout) { xdr.timeout = request.timeout; } xdr.onload = handler; xdr.onabort = handler; xdr.onerror = handler; xdr.ontimeout = handler; xdr.onprogress = function () {}; xdr.send(request.getBody()); }); } /** * CORS Interceptor. */ var SUPPORTS_CORS = inBrowser && 'withCredentials' in new XMLHttpRequest(); function cors (request) { if (inBrowser) { var orgUrl = Url.parse(location.href); var reqUrl = Url.parse(request.getUrl()); if (reqUrl.protocol !== orgUrl.protocol || reqUrl.host !== orgUrl.host) { request.crossOrigin = true; request.emulateHTTP = false; if (!SUPPORTS_CORS) { request.client = xdrClient; } } } } /** * Form data Interceptor. */ function form (request) { if (isFormData(request.body)) { request.headers["delete"]('Content-Type'); } else if (isObject(request.body) && request.emulateJSON) { request.body = Url.params(request.body); request.headers.set('Content-Type', 'application/x-www-form-urlencoded'); } } /** * JSON Interceptor. */ function json (request) { var type = request.headers.get('Content-Type') || ''; if (isObject(request.body) && type.indexOf('application/json') === 0) { request.body = JSON.stringify(request.body); } return function (response) { return response.bodyText ? when(response.text(), function (text) { var type = response.headers.get('Content-Type') || ''; if (type.indexOf('application/json') === 0 || isJson(text)) { try { response.body = JSON.parse(text); } catch (e) { response.body = null; } } else { response.body = text; } return response; }) : response; }; } function isJson(str) { var start = str.match(/^\s*(\[|\{)/); var end = { '[': /]\s*$/, '{': /}\s*$/ }; return start && end[start[1]].test(str); } /** * JSONP client (Browser). */ function jsonpClient (request) { return new PromiseObj(function (resolve) { var name = request.jsonp || 'callback', callback = request.jsonpCallback || '_jsonp' + Math.random().toString(36).substr(2), body = null, handler, script; handler = function handler(_ref) { var type = _ref.type; var status = 0; if (type === 'load' && body !== null) { status = 200; } else if (type === 'error') { status = 500; } if (status && window[callback]) { delete window[callback]; document.body.removeChild(script); } resolve(request.respondWith(body, { status: status })); }; window[callback] = function (result) { body = JSON.stringify(result); }; request.abort = function () { handler({ type: 'abort' }); }; request.params[name] = callback; if (request.timeout) { setTimeout(request.abort, request.timeout); } script = document.createElement('script'); script.src = request.getUrl(); script.type = 'text/javascript'; script.async = true; script.onload = handler; script.onerror = handler; document.body.appendChild(script); }); } /** * JSONP Interceptor. */ function jsonp (request) { if (request.method == 'JSONP') { request.client = jsonpClient; } } /** * Before Interceptor. */ function before (request) { if (isFunction(request.before)) { request.before.call(this, request); } } /** * HTTP method override Interceptor. */ function method (request) { if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { request.headers.set('X-HTTP-Method-Override', request.method); request.method = 'POST'; } } /** * Header Interceptor. */ function header (request) { 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); } }); } /** * XMLHttp client (Browser). */ function xhrClient (request) { return new PromiseObj(function (resolve) { var xhr = new XMLHttpRequest(), handler = function handler(event) { 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) }); each(trim(xhr.getAllResponseHeaders()).split('\n'), function (row) { response.headers.append(row.slice(0, row.indexOf(':')), row.slice(row.indexOf(':') + 1)); }); resolve(response); }; request.abort = function () { return xhr.abort(); }; xhr.open(request.method, request.getUrl(), true); if (request.timeout) { xhr.timeout = request.timeout; } if (request.responseType && 'responseType' in xhr) { xhr.responseType = request.responseType; } if (request.withCredentials || request.credentials) { xhr.withCredentials = true; } if (!request.crossOrigin) { request.headers.set('X-Requested-With', 'XMLHttpRequest'); } // deprecated use downloadProgress if (isFunction(request.progress) && request.method === 'GET') { xhr.addEventListener('progress', request.progress); } if (isFunction(request.downloadProgress)) { xhr.addEventListener('progress', request.downloadProgress); } // deprecated use uploadProgress if (isFunction(request.progress) && /^(POST|PUT)$/i.test(request.method)) { xhr.upload.addEventListener('progress', request.progress); } if (isFunction(request.uploadProgress) && xhr.upload) { xhr.upload.addEventListener('progress', request.uploadProgress); } request.headers.forEach(function (value, name) { xhr.setRequestHeader(name, value); }); xhr.onload = handler; xhr.onabort = handler; xhr.onerror = handler; xhr.ontimeout = handler; xhr.send(request.getBody()); }); } /** * Http client (Node). */ function nodeClient (request) { var client = require('got'); return new PromiseObj(function (resolve) { var url = request.getUrl(); var body = request.getBody(); var method = request.method; var headers = {}, handler; request.headers.forEach(function (value, name) { headers[name] = value; }); client(url, { body: body, method: method, headers: headers }).then(handler = function handler(resp) { var response = request.respondWith(resp.body, { status: resp.statusCode, statusText: trim(resp.statusMessage) }); each(resp.headers, function (value, name) { response.headers.set(name, value); }); resolve(response); }, function (error$$1) { return handler(error$$1.response); }); }); } /** * Base client. */ function Client (context) { var reqHandlers = [sendRequest], resHandlers = []; if (!isObject(context)) { context = null; } function Client(request) { while (reqHandlers.length) { var handler = reqHandlers.pop(); if (isFunction(handler)) { var _ret = function () { var response = void 0, next = void 0; response = handler.call(context, request, function (val) { return next = val; }) || next; if (isObject(response)) { return { v: new PromiseObj(function (resolve, reject) { resHandlers.forEach(function (handler) { response = when(response, function (response) { return handler.call(context, response) || response; }, reject); }); when(response, resolve, reject); }, context) }; } if (isFunction(response)) { resHandlers.unshift(response); } }(); if (typeof _ret === "object") return _ret.v; } else { warn("Invalid interceptor of type " + typeof handler + ", must be a function"); } } } Client.use = function (handler) { reqHandlers.push(handler); }; return Client; } function sendRequest(request) { var client = request.client || (inBrowser ? xhrClient : nodeClient); return client(request); } /** * HTTP Headers. */ var Headers = /*#__PURE__*/function () { function Headers(headers) { var _this = this; this.map = {}; each(headers, function (value, name) { return _this.append(name, value); }); } var _proto = Headers.prototype; _proto.has = function has(name) { return getName(this.map, name) !== null; }; _proto.get = function get(name) { var list = this.map[getName(this.map, name)]; return list ? list.join() : null; }; _proto.getAll = function getAll(name) { return this.map[getName(this.map, name)] || []; }; _proto.set = function set(name, value) { this.map[normalizeName(getName(this.map, name) || name)] = [trim(value)]; }; _proto.append = function append(name, value) { var list = this.map[getName(this.map, name)]; if (list) { list.push(trim(value)); } else { this.set(name, value); } }; _proto["delete"] = function _delete(name) { delete this.map[getName(this.map, name)]; }; _proto.deleteAll = function deleteAll() { this.map = {}; }; _proto.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 getName(map, name) { return Object.keys(map).reduce(function (prev, curr) { return toLower(name) === toLower(curr) ? curr : prev; }, null); } function normalizeName(name) { if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name)) { throw new TypeError('Invalid character in header field name'); } return trim(name); } /** * HTTP Response. */ var Response = /*#__PURE__*/function () { function Response(body, _ref) { var url = _ref.url, headers = _ref.headers, status = _ref.status, statusText = _ref.statusText; this.url = url; this.ok = status >= 200 && status < 300; this.status = status || 0; this.statusText = statusText || ''; 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); } } } var _proto = Response.prototype; _proto.blob = function blob() { return when(this.bodyBlob); }; _proto.text = function text() { return when(this.bodyText); }; _proto.json = function json() { return when(this.text(), function (text) { return JSON.parse(text); }); }; return Response; }(); Object.defineProperty(Response.prototype, 'data', { get: function get() { return this.body; }, set: function set(body) { this.body = body; } }); function blobText(body) { return new PromiseObj(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 = /*#__PURE__*/function () { function Request(options$$1) { this.body = null; this.params = {}; assign(this, options$$1, { method: toUpper(options$$1.method || 'GET') }); if (!(this.headers instanceof Headers)) { this.headers = new Headers(this.headers); } } var _proto = Request.prototype; _proto.getUrl = function getUrl() { return Url(this); }; _proto.getBody = function getBody() { return this.body; }; _proto.respondWith = function respondWith(body, options$$1) { return new Response(body, assign(options$$1 || {}, { url: this.getUrl() })); }; return Request; }(); /** * Service for sending network requests. */ var COMMON_HEADERS = { 'Accept': 'application/json, text/plain, */*' }; var JSON_CONTENT_TYPE = { 'Content-Type': 'application/json;charset=utf-8' }; function Http(options$$1) { var self = this || {}, client = Client(self.$vm); defaults(options$$1 || {}, self.$options, Http.options); Http.interceptors.forEach(function (handler) { if (isString(handler)) { handler = Http.interceptor[handler]; } if (isFunction(handler)) { client.use(handler); } }); return client(new Request(options$$1)).then(function (response) { return response.ok ? response : PromiseObj.reject(response); }, function (response) { if (response instanceof Error) { error(response); } return PromiseObj.reject(response); }); } Http.options = {}; Http.headers = { put: JSON_CONTENT_TYPE, post: JSON_CONTENT_TYPE, patch: JSON_CONTENT_TYPE, "delete": JSON_CONTENT_TYPE, common: COMMON_HEADERS, custom: {} }; Http.interceptor = { before: before, method: method, jsonp: jsonp, json: json, form: form, header: header, cors: cors }; Http.interceptors = ['before', 'method', 'jsonp', 'json', 'form', 'header', 'cors']; ['get', 'delete', 'head', 'jsonp'].forEach(function (method$$1) { Http[method$$1] = function (url, options$$1) { return this(assign(options$$1 || {}, { url: url, method: method$$1 })); }; }); ['post', 'put', 'patch'].forEach(function (method$$1) { Http[method$$1] = function (url, body, options$$1) { return this(assign(options$$1 || {}, { url: url, method: method$$1, body: body })); }; }); /** * Service for interacting with RESTful services. */ function Resource(url, params, actions, options$$1) { var self = this || {}, resource = {}; actions = assign({}, Resource.actions, actions); each(actions, function (action, name) { action = merge({ url: url, params: assign({}, params) }, options$$1, action); resource[name] = function () { return (self.$http || Http)(opts(action, arguments)); }; }); return resource; } function opts(action, args) { var options$$1 = 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$$1.method)) { body = args[0]; } else { params = args[0]; } break; case 0: break; default: throw 'Expected up to 2 arguments [params, body], got ' + args.length + ' arguments'; } options$$1.body = body; options$$1.params = assign({}, options$$1.params, params); return options$$1; } 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 = PromiseObj; Object.defineProperties(Vue.prototype, { $url: { get: function get() { return options(Vue.url, this, this.$options.url); } }, $http: { get: function get() { return options(Vue.http, this, this.$options.http); } }, $resource: { get: function get() { return Vue.resource.bind(this); } }, $promise: { get: function get() { var _this = this; return function (executor) { return new Vue.Promise(executor, _this); }; } } }); } if (typeof window !== 'undefined' && window.Vue && !window.Vue.resource) { window.Vue.use(plugin); } module.exports = plugin; ================================================ FILE: dist/vue-resource.esm.js ================================================ /*! * vue-resource v1.5.3 * https://github.com/pagekit/vue-resource * Released under the MIT License. */ /** * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) */ var RESOLVED = 0; var REJECTED = 1; var PENDING = 2; function Promise$1(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$1.reject = function (r) { return new Promise$1(function (resolve, reject) { reject(r); }); }; Promise$1.resolve = function (x) { return new Promise$1(function (resolve, reject) { resolve(x); }); }; Promise$1.all = function all(iterable) { return new Promise$1(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$1.resolve(iterable[i]).then(resolver(i), reject); } }); }; Promise$1.race = function race(iterable) { return new Promise$1(function (resolve, reject) { for (var i = 0; i < iterable.length; i += 1) { Promise$1.resolve(iterable[i]).then(resolve, reject); } }); }; var p = Promise$1.prototype; p.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.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.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.then = function then(onResolved, onRejected) { var promise = this; return new Promise$1(function (resolve, reject) { promise.deferred.push([onResolved, onRejected, resolve, reject]); promise.notify(); }); }; p["catch"] = function (onRejected) { return this.then(undefined, onRejected); }; /** * Promise adapter. */ if (typeof Promise === 'undefined') { window.Promise = Promise$1; } function PromiseObj(executor, context) { if (executor instanceof Promise) { this.promise = executor; } else { this.promise = new Promise(executor.bind(context)); } this.context = context; } PromiseObj.all = function (iterable, context) { return new PromiseObj(Promise.all(iterable), context); }; PromiseObj.resolve = function (value, context) { return new PromiseObj(Promise.resolve(value), context); }; PromiseObj.reject = function (reason, context) { return new PromiseObj(Promise.reject(reason), context); }; PromiseObj.race = function (iterable, context) { return new PromiseObj(Promise.race(iterable), context); }; var p$1 = PromiseObj.prototype; p$1.bind = function (context) { this.context = context; return this; }; p$1.then = function (fulfilled, rejected) { if (fulfilled && fulfilled.bind && this.context) { fulfilled = fulfilled.bind(this.context); } if (rejected && rejected.bind && this.context) { rejected = rejected.bind(this.context); } return new PromiseObj(this.promise.then(fulfilled, rejected), this.context); }; p$1["catch"] = function (rejected) { if (rejected && rejected.bind && this.context) { rejected = rejected.bind(this.context); } return new PromiseObj(this.promise["catch"](rejected), this.context); }; p$1["finally"] = function (callback) { return this.then(function (value) { callback.call(this); return value; }, function (reason) { callback.call(this); return Promise.reject(reason); }); }; /** * Utility functions. */ var _ref = {}, hasOwnProperty = _ref.hasOwnProperty, slice = [].slice, debug = false, ntick; var inBrowser = typeof window !== 'undefined'; function Util (_ref2) { var config = _ref2.config, nextTick = _ref2.nextTick; ntick = nextTick; debug = config.debug || !config.silent; } function warn(msg) { if (typeof console !== 'undefined' && debug) { console.warn('[VueResource warn]: ' + msg); } } function error(msg) { if (typeof console !== 'undefined') { console.error(msg); } } function nextTick(cb, ctx) { return ntick(cb, ctx); } function trim(str) { return str ? str.replace(/^\s*|\s*$/g, '') : ''; } function trimEnd(str, chars) { if (str && chars === undefined) { return str.replace(/\s+$/, ''); } if (!str || !chars) { return str; } return str.replace(new RegExp("[" + chars + "]+$"), ''); } function toLower(str) { return str ? str.toLowerCase() : ''; } function toUpper(str) { return str ? str.toUpperCase() : ''; } var isArray = Array.isArray; function isString(val) { return typeof val === 'string'; } function isFunction(val) { return typeof val === 'function'; } function isObject(obj) { return obj !== null && typeof obj === 'object'; } 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; } function when(value, fulfilled, rejected) { var promise = PromiseObj.resolve(value); if (arguments.length < 2) { return promise; } return promise.then(fulfilled, rejected); } function options(fn, obj, opts) { opts = opts || {}; if (isFunction(opts)) { opts = opts.call(obj); } return merge(fn.bind({ $vm: obj, $options: opts }), fn, { $options: opts }); } function each(obj, iterator) { var i, key; if (isArray(obj)) { for (i = 0; i < obj.length; i++) { iterator.call(obj[i], obj[i], i); } } else if (isObject(obj)) { for (key in obj) { if (hasOwnProperty.call(obj, key)) { iterator.call(obj[key], obj[key], key); } } } return obj; } var assign = Object.assign || _assign; function merge(target) { var args = slice.call(arguments, 1); args.forEach(function (source) { _merge(target, source, true); }); return target; } function defaults(target) { var args = slice.call(arguments, 1); args.forEach(function (source) { for (var key in source) { if (target[key] === undefined) { target[key] = source[key]; } } }); return target; } function _assign(target) { var args = slice.call(arguments, 1); args.forEach(function (source) { _merge(target, source); }); 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]; } } } /** * Root Prefix Transform. */ function root (options$$1, next) { var url = next(options$$1); if (isString(options$$1.root) && !/^(https?:)?\//.test(url)) { url = trimEnd(options$$1.root, '/') + '/' + url; } return url; } /** * Query Parameter Transform. */ function query (options$$1, next) { var urlParams = Object.keys(Url.options.params), query = {}, url = next(options$$1); each(options$$1.params, function (value, key) { if (urlParams.indexOf(key) === -1) { query[key] = value; } }); query = Url.params(query); if (query) { url += (url.indexOf('?') == -1 ? '?' : '&') + query; } return url; } /** * URL Template v2.0.6 (https://github.com/bramstein/url-template) */ function expand(url, params, variables) { var tmpl = parse(url), expanded = tmpl.expand(params); if (variables) { variables.push.apply(variables, tmpl.vars); } return expanded; } function parse(template) { var operators = ['+', '#', '.', '/', ';', '?', '&'], variables = []; return { vars: variables, expand: function expand(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(''); } } return result; } function isDefined(value) { return value !== undefined && value !== null; } function isKeyOperator(operator) { return operator === ';' || operator === '&' || operator === '?'; } function encodeValue(operator, value, key) { value = operator === '+' || operator === '#' ? encodeReserved(value) : encodeURIComponent(value); 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. */ function template (options) { var variables = [], url = expand(options.url, options.params, variables); variables.forEach(function (key) { delete options.params[key]; }); return url; } /** * Service for URL templating. */ function Url(url, params) { var self = this || {}, options$$1 = url, transform; if (isString(url)) { options$$1 = { url: url, params: params }; } options$$1 = merge({}, Url.options, self.$options, options$$1); Url.transforms.forEach(function (handler) { if (isString(handler)) { handler = Url.transform[handler]; } if (isFunction(handler)) { transform = factory(handler, transform, self.$vm); } }); return transform(options$$1); } /** * Url options. */ Url.options = { url: '', root: null, params: {} }; /** * Url transforms. */ Url.transform = { template: template, query: query, root: root }; Url.transforms = ['template', 'query', 'root']; /** * Encodes a Url parameter string. * * @param {Object} obj */ Url.params = function (obj) { var params = [], escape = encodeURIComponent; params.add = function (key, value) { if (isFunction(value)) { value = value(); } if (value === null) { value = ''; } this.push(escape(key) + '=' + escape(value)); }; serialize(params, obj); return params.join('&').replace(/%20/g, '+'); }; /** * Parse a URL and return its components. * * @param {String} url */ Url.parse = function (url) { var el = document.createElement('a'); if (document.documentMode) { el.href = url; url = el.href; } 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$$1) { return handler.call(vm, options$$1, 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). */ function xdrClient (request) { return new PromiseObj(function (resolve) { var xdr = new XDomainRequest(), handler = function handler(_ref) { var type = _ref.type; var status = 0; if (type === 'load') { status = 200; } else if (type === 'error') { status = 500; } resolve(request.respondWith(xdr.responseText, { status: status })); }; request.abort = function () { return xdr.abort(); }; xdr.open(request.method, request.getUrl()); if (request.timeout) { xdr.timeout = request.timeout; } xdr.onload = handler; xdr.onabort = handler; xdr.onerror = handler; xdr.ontimeout = handler; xdr.onprogress = function () {}; xdr.send(request.getBody()); }); } /** * CORS Interceptor. */ var SUPPORTS_CORS = inBrowser && 'withCredentials' in new XMLHttpRequest(); function cors (request) { if (inBrowser) { var orgUrl = Url.parse(location.href); var reqUrl = Url.parse(request.getUrl()); if (reqUrl.protocol !== orgUrl.protocol || reqUrl.host !== orgUrl.host) { request.crossOrigin = true; request.emulateHTTP = false; if (!SUPPORTS_CORS) { request.client = xdrClient; } } } } /** * Form data Interceptor. */ function form (request) { if (isFormData(request.body)) { request.headers["delete"]('Content-Type'); } else if (isObject(request.body) && request.emulateJSON) { request.body = Url.params(request.body); request.headers.set('Content-Type', 'application/x-www-form-urlencoded'); } } /** * JSON Interceptor. */ function json (request) { var type = request.headers.get('Content-Type') || ''; if (isObject(request.body) && type.indexOf('application/json') === 0) { request.body = JSON.stringify(request.body); } return function (response) { return response.bodyText ? when(response.text(), function (text) { var type = response.headers.get('Content-Type') || ''; if (type.indexOf('application/json') === 0 || isJson(text)) { try { response.body = JSON.parse(text); } catch (e) { response.body = null; } } else { response.body = text; } return response; }) : response; }; } function isJson(str) { var start = str.match(/^\s*(\[|\{)/); var end = { '[': /]\s*$/, '{': /}\s*$/ }; return start && end[start[1]].test(str); } /** * JSONP client (Browser). */ function jsonpClient (request) { return new PromiseObj(function (resolve) { var name = request.jsonp || 'callback', callback = request.jsonpCallback || '_jsonp' + Math.random().toString(36).substr(2), body = null, handler, script; handler = function handler(_ref) { var type = _ref.type; var status = 0; if (type === 'load' && body !== null) { status = 200; } else if (type === 'error') { status = 500; } if (status && window[callback]) { delete window[callback]; document.body.removeChild(script); } resolve(request.respondWith(body, { status: status })); }; window[callback] = function (result) { body = JSON.stringify(result); }; request.abort = function () { handler({ type: 'abort' }); }; request.params[name] = callback; if (request.timeout) { setTimeout(request.abort, request.timeout); } script = document.createElement('script'); script.src = request.getUrl(); script.type = 'text/javascript'; script.async = true; script.onload = handler; script.onerror = handler; document.body.appendChild(script); }); } /** * JSONP Interceptor. */ function jsonp (request) { if (request.method == 'JSONP') { request.client = jsonpClient; } } /** * Before Interceptor. */ function before (request) { if (isFunction(request.before)) { request.before.call(this, request); } } /** * HTTP method override Interceptor. */ function method (request) { if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { request.headers.set('X-HTTP-Method-Override', request.method); request.method = 'POST'; } } /** * Header Interceptor. */ function header (request) { 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); } }); } /** * XMLHttp client (Browser). */ function xhrClient (request) { return new PromiseObj(function (resolve) { var xhr = new XMLHttpRequest(), handler = function handler(event) { 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) }); each(trim(xhr.getAllResponseHeaders()).split('\n'), function (row) { response.headers.append(row.slice(0, row.indexOf(':')), row.slice(row.indexOf(':') + 1)); }); resolve(response); }; request.abort = function () { return xhr.abort(); }; xhr.open(request.method, request.getUrl(), true); if (request.timeout) { xhr.timeout = request.timeout; } if (request.responseType && 'responseType' in xhr) { xhr.responseType = request.responseType; } if (request.withCredentials || request.credentials) { xhr.withCredentials = true; } if (!request.crossOrigin) { request.headers.set('X-Requested-With', 'XMLHttpRequest'); } // deprecated use downloadProgress if (isFunction(request.progress) && request.method === 'GET') { xhr.addEventListener('progress', request.progress); } if (isFunction(request.downloadProgress)) { xhr.addEventListener('progress', request.downloadProgress); } // deprecated use uploadProgress if (isFunction(request.progress) && /^(POST|PUT)$/i.test(request.method)) { xhr.upload.addEventListener('progress', request.progress); } if (isFunction(request.uploadProgress) && xhr.upload) { xhr.upload.addEventListener('progress', request.uploadProgress); } request.headers.forEach(function (value, name) { xhr.setRequestHeader(name, value); }); xhr.onload = handler; xhr.onabort = handler; xhr.onerror = handler; xhr.ontimeout = handler; xhr.send(request.getBody()); }); } /** * Http client (Node). */ function nodeClient (request) { var client = require('got'); return new PromiseObj(function (resolve) { var url = request.getUrl(); var body = request.getBody(); var method = request.method; var headers = {}, handler; request.headers.forEach(function (value, name) { headers[name] = value; }); client(url, { body: body, method: method, headers: headers }).then(handler = function handler(resp) { var response = request.respondWith(resp.body, { status: resp.statusCode, statusText: trim(resp.statusMessage) }); each(resp.headers, function (value, name) { response.headers.set(name, value); }); resolve(response); }, function (error$$1) { return handler(error$$1.response); }); }); } /** * Base client. */ function Client (context) { var reqHandlers = [sendRequest], resHandlers = []; if (!isObject(context)) { context = null; } function Client(request) { while (reqHandlers.length) { var handler = reqHandlers.pop(); if (isFunction(handler)) { var _ret = function () { var response = void 0, next = void 0; response = handler.call(context, request, function (val) { return next = val; }) || next; if (isObject(response)) { return { v: new PromiseObj(function (resolve, reject) { resHandlers.forEach(function (handler) { response = when(response, function (response) { return handler.call(context, response) || response; }, reject); }); when(response, resolve, reject); }, context) }; } if (isFunction(response)) { resHandlers.unshift(response); } }(); if (typeof _ret === "object") return _ret.v; } else { warn("Invalid interceptor of type " + typeof handler + ", must be a function"); } } } Client.use = function (handler) { reqHandlers.push(handler); }; return Client; } function sendRequest(request) { var client = request.client || (inBrowser ? xhrClient : nodeClient); return client(request); } /** * HTTP Headers. */ var Headers = /*#__PURE__*/function () { function Headers(headers) { var _this = this; this.map = {}; each(headers, function (value, name) { return _this.append(name, value); }); } var _proto = Headers.prototype; _proto.has = function has(name) { return getName(this.map, name) !== null; }; _proto.get = function get(name) { var list = this.map[getName(this.map, name)]; return list ? list.join() : null; }; _proto.getAll = function getAll(name) { return this.map[getName(this.map, name)] || []; }; _proto.set = function set(name, value) { this.map[normalizeName(getName(this.map, name) || name)] = [trim(value)]; }; _proto.append = function append(name, value) { var list = this.map[getName(this.map, name)]; if (list) { list.push(trim(value)); } else { this.set(name, value); } }; _proto["delete"] = function _delete(name) { delete this.map[getName(this.map, name)]; }; _proto.deleteAll = function deleteAll() { this.map = {}; }; _proto.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 getName(map, name) { return Object.keys(map).reduce(function (prev, curr) { return toLower(name) === toLower(curr) ? curr : prev; }, null); } function normalizeName(name) { if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name)) { throw new TypeError('Invalid character in header field name'); } return trim(name); } /** * HTTP Response. */ var Response = /*#__PURE__*/function () { function Response(body, _ref) { var url = _ref.url, headers = _ref.headers, status = _ref.status, statusText = _ref.statusText; this.url = url; this.ok = status >= 200 && status < 300; this.status = status || 0; this.statusText = statusText || ''; 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); } } } var _proto = Response.prototype; _proto.blob = function blob() { return when(this.bodyBlob); }; _proto.text = function text() { return when(this.bodyText); }; _proto.json = function json() { return when(this.text(), function (text) { return JSON.parse(text); }); }; return Response; }(); Object.defineProperty(Response.prototype, 'data', { get: function get() { return this.body; }, set: function set(body) { this.body = body; } }); function blobText(body) { return new PromiseObj(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 = /*#__PURE__*/function () { function Request(options$$1) { this.body = null; this.params = {}; assign(this, options$$1, { method: toUpper(options$$1.method || 'GET') }); if (!(this.headers instanceof Headers)) { this.headers = new Headers(this.headers); } } var _proto = Request.prototype; _proto.getUrl = function getUrl() { return Url(this); }; _proto.getBody = function getBody() { return this.body; }; _proto.respondWith = function respondWith(body, options$$1) { return new Response(body, assign(options$$1 || {}, { url: this.getUrl() })); }; return Request; }(); /** * Service for sending network requests. */ var COMMON_HEADERS = { 'Accept': 'application/json, text/plain, */*' }; var JSON_CONTENT_TYPE = { 'Content-Type': 'application/json;charset=utf-8' }; function Http(options$$1) { var self = this || {}, client = Client(self.$vm); defaults(options$$1 || {}, self.$options, Http.options); Http.interceptors.forEach(function (handler) { if (isString(handler)) { handler = Http.interceptor[handler]; } if (isFunction(handler)) { client.use(handler); } }); return client(new Request(options$$1)).then(function (response) { return response.ok ? response : PromiseObj.reject(response); }, function (response) { if (response instanceof Error) { error(response); } return PromiseObj.reject(response); }); } Http.options = {}; Http.headers = { put: JSON_CONTENT_TYPE, post: JSON_CONTENT_TYPE, patch: JSON_CONTENT_TYPE, "delete": JSON_CONTENT_TYPE, common: COMMON_HEADERS, custom: {} }; Http.interceptor = { before: before, method: method, jsonp: jsonp, json: json, form: form, header: header, cors: cors }; Http.interceptors = ['before', 'method', 'jsonp', 'json', 'form', 'header', 'cors']; ['get', 'delete', 'head', 'jsonp'].forEach(function (method$$1) { Http[method$$1] = function (url, options$$1) { return this(assign(options$$1 || {}, { url: url, method: method$$1 })); }; }); ['post', 'put', 'patch'].forEach(function (method$$1) { Http[method$$1] = function (url, body, options$$1) { return this(assign(options$$1 || {}, { url: url, method: method$$1, body: body })); }; }); /** * Service for interacting with RESTful services. */ function Resource(url, params, actions, options$$1) { var self = this || {}, resource = {}; actions = assign({}, Resource.actions, actions); each(actions, function (action, name) { action = merge({ url: url, params: assign({}, params) }, options$$1, action); resource[name] = function () { return (self.$http || Http)(opts(action, arguments)); }; }); return resource; } function opts(action, args) { var options$$1 = 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$$1.method)) { body = args[0]; } else { params = args[0]; } break; case 0: break; default: throw 'Expected up to 2 arguments [params, body], got ' + args.length + ' arguments'; } options$$1.body = body; options$$1.params = assign({}, options$$1.params, params); return options$$1; } 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 = PromiseObj; Object.defineProperties(Vue.prototype, { $url: { get: function get() { return options(Vue.url, this, this.$options.url); } }, $http: { get: function get() { return options(Vue.http, this, this.$options.http); } }, $resource: { get: function get() { return Vue.resource.bind(this); } }, $promise: { get: function get() { var _this = this; return function (executor) { return new Vue.Promise(executor, _this); }; } } }); } if (typeof window !== 'undefined' && window.Vue && !window.Vue.resource) { window.Vue.use(plugin); } export default plugin; export { Url, Http, Resource }; ================================================ FILE: dist/vue-resource.js ================================================ /*! * vue-resource v1.5.3 * https://github.com/pagekit/vue-resource * Released under the MIT License. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.VueResource = factory()); }(this, (function () { 'use strict'; /** * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) */ var RESOLVED = 0; var REJECTED = 1; var PENDING = 2; function Promise$1(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$1.reject = function (r) { return new Promise$1(function (resolve, reject) { reject(r); }); }; Promise$1.resolve = function (x) { return new Promise$1(function (resolve, reject) { resolve(x); }); }; Promise$1.all = function all(iterable) { return new Promise$1(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$1.resolve(iterable[i]).then(resolver(i), reject); } }); }; Promise$1.race = function race(iterable) { return new Promise$1(function (resolve, reject) { for (var i = 0; i < iterable.length; i += 1) { Promise$1.resolve(iterable[i]).then(resolve, reject); } }); }; var p = Promise$1.prototype; p.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.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.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.then = function then(onResolved, onRejected) { var promise = this; return new Promise$1(function (resolve, reject) { promise.deferred.push([onResolved, onRejected, resolve, reject]); promise.notify(); }); }; p["catch"] = function (onRejected) { return this.then(undefined, onRejected); }; /** * Promise adapter. */ if (typeof Promise === 'undefined') { window.Promise = Promise$1; } function PromiseObj(executor, context) { if (executor instanceof Promise) { this.promise = executor; } else { this.promise = new Promise(executor.bind(context)); } this.context = context; } PromiseObj.all = function (iterable, context) { return new PromiseObj(Promise.all(iterable), context); }; PromiseObj.resolve = function (value, context) { return new PromiseObj(Promise.resolve(value), context); }; PromiseObj.reject = function (reason, context) { return new PromiseObj(Promise.reject(reason), context); }; PromiseObj.race = function (iterable, context) { return new PromiseObj(Promise.race(iterable), context); }; var p$1 = PromiseObj.prototype; p$1.bind = function (context) { this.context = context; return this; }; p$1.then = function (fulfilled, rejected) { if (fulfilled && fulfilled.bind && this.context) { fulfilled = fulfilled.bind(this.context); } if (rejected && rejected.bind && this.context) { rejected = rejected.bind(this.context); } return new PromiseObj(this.promise.then(fulfilled, rejected), this.context); }; p$1["catch"] = function (rejected) { if (rejected && rejected.bind && this.context) { rejected = rejected.bind(this.context); } return new PromiseObj(this.promise["catch"](rejected), this.context); }; p$1["finally"] = function (callback) { return this.then(function (value) { callback.call(this); return value; }, function (reason) { callback.call(this); return Promise.reject(reason); }); }; /** * Utility functions. */ var _ref = {}, hasOwnProperty = _ref.hasOwnProperty, slice = [].slice, debug = false, ntick; var inBrowser = typeof window !== 'undefined'; function Util (_ref2) { var config = _ref2.config, nextTick = _ref2.nextTick; ntick = nextTick; debug = config.debug || !config.silent; } function warn(msg) { if (typeof console !== 'undefined' && debug) { console.warn('[VueResource warn]: ' + msg); } } function error(msg) { if (typeof console !== 'undefined') { console.error(msg); } } function nextTick(cb, ctx) { return ntick(cb, ctx); } function trim(str) { return str ? str.replace(/^\s*|\s*$/g, '') : ''; } function trimEnd(str, chars) { if (str && chars === undefined) { return str.replace(/\s+$/, ''); } if (!str || !chars) { return str; } return str.replace(new RegExp("[" + chars + "]+$"), ''); } function toLower(str) { return str ? str.toLowerCase() : ''; } function toUpper(str) { return str ? str.toUpperCase() : ''; } var isArray = Array.isArray; function isString(val) { return typeof val === 'string'; } function isFunction(val) { return typeof val === 'function'; } function isObject(obj) { return obj !== null && typeof obj === 'object'; } 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; } function when(value, fulfilled, rejected) { var promise = PromiseObj.resolve(value); if (arguments.length < 2) { return promise; } return promise.then(fulfilled, rejected); } function options(fn, obj, opts) { opts = opts || {}; if (isFunction(opts)) { opts = opts.call(obj); } return merge(fn.bind({ $vm: obj, $options: opts }), fn, { $options: opts }); } function each(obj, iterator) { var i, key; if (isArray(obj)) { for (i = 0; i < obj.length; i++) { iterator.call(obj[i], obj[i], i); } } else if (isObject(obj)) { for (key in obj) { if (hasOwnProperty.call(obj, key)) { iterator.call(obj[key], obj[key], key); } } } return obj; } var assign = Object.assign || _assign; function merge(target) { var args = slice.call(arguments, 1); args.forEach(function (source) { _merge(target, source, true); }); return target; } function defaults(target) { var args = slice.call(arguments, 1); args.forEach(function (source) { for (var key in source) { if (target[key] === undefined) { target[key] = source[key]; } } }); return target; } function _assign(target) { var args = slice.call(arguments, 1); args.forEach(function (source) { _merge(target, source); }); 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]; } } } /** * Root Prefix Transform. */ function root (options$$1, next) { var url = next(options$$1); if (isString(options$$1.root) && !/^(https?:)?\//.test(url)) { url = trimEnd(options$$1.root, '/') + '/' + url; } return url; } /** * Query Parameter Transform. */ function query (options$$1, next) { var urlParams = Object.keys(Url.options.params), query = {}, url = next(options$$1); each(options$$1.params, function (value, key) { if (urlParams.indexOf(key) === -1) { query[key] = value; } }); query = Url.params(query); if (query) { url += (url.indexOf('?') == -1 ? '?' : '&') + query; } return url; } /** * URL Template v2.0.6 (https://github.com/bramstein/url-template) */ function expand(url, params, variables) { var tmpl = parse(url), expanded = tmpl.expand(params); if (variables) { variables.push.apply(variables, tmpl.vars); } return expanded; } function parse(template) { var operators = ['+', '#', '.', '/', ';', '?', '&'], variables = []; return { vars: variables, expand: function expand(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(''); } } return result; } function isDefined(value) { return value !== undefined && value !== null; } function isKeyOperator(operator) { return operator === ';' || operator === '&' || operator === '?'; } function encodeValue(operator, value, key) { value = operator === '+' || operator === '#' ? encodeReserved(value) : encodeURIComponent(value); 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. */ function template (options) { var variables = [], url = expand(options.url, options.params, variables); variables.forEach(function (key) { delete options.params[key]; }); return url; } /** * Service for URL templating. */ function Url(url, params) { var self = this || {}, options$$1 = url, transform; if (isString(url)) { options$$1 = { url: url, params: params }; } options$$1 = merge({}, Url.options, self.$options, options$$1); Url.transforms.forEach(function (handler) { if (isString(handler)) { handler = Url.transform[handler]; } if (isFunction(handler)) { transform = factory(handler, transform, self.$vm); } }); return transform(options$$1); } /** * Url options. */ Url.options = { url: '', root: null, params: {} }; /** * Url transforms. */ Url.transform = { template: template, query: query, root: root }; Url.transforms = ['template', 'query', 'root']; /** * Encodes a Url parameter string. * * @param {Object} obj */ Url.params = function (obj) { var params = [], escape = encodeURIComponent; params.add = function (key, value) { if (isFunction(value)) { value = value(); } if (value === null) { value = ''; } this.push(escape(key) + '=' + escape(value)); }; serialize(params, obj); return params.join('&').replace(/%20/g, '+'); }; /** * Parse a URL and return its components. * * @param {String} url */ Url.parse = function (url) { var el = document.createElement('a'); if (document.documentMode) { el.href = url; url = el.href; } 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$$1) { return handler.call(vm, options$$1, 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). */ function xdrClient (request) { return new PromiseObj(function (resolve) { var xdr = new XDomainRequest(), handler = function handler(_ref) { var type = _ref.type; var status = 0; if (type === 'load') { status = 200; } else if (type === 'error') { status = 500; } resolve(request.respondWith(xdr.responseText, { status: status })); }; request.abort = function () { return xdr.abort(); }; xdr.open(request.method, request.getUrl()); if (request.timeout) { xdr.timeout = request.timeout; } xdr.onload = handler; xdr.onabort = handler; xdr.onerror = handler; xdr.ontimeout = handler; xdr.onprogress = function () {}; xdr.send(request.getBody()); }); } /** * CORS Interceptor. */ var SUPPORTS_CORS = inBrowser && 'withCredentials' in new XMLHttpRequest(); function cors (request) { if (inBrowser) { var orgUrl = Url.parse(location.href); var reqUrl = Url.parse(request.getUrl()); if (reqUrl.protocol !== orgUrl.protocol || reqUrl.host !== orgUrl.host) { request.crossOrigin = true; request.emulateHTTP = false; if (!SUPPORTS_CORS) { request.client = xdrClient; } } } } /** * Form data Interceptor. */ function form (request) { if (isFormData(request.body)) { request.headers["delete"]('Content-Type'); } else if (isObject(request.body) && request.emulateJSON) { request.body = Url.params(request.body); request.headers.set('Content-Type', 'application/x-www-form-urlencoded'); } } /** * JSON Interceptor. */ function json (request) { var type = request.headers.get('Content-Type') || ''; if (isObject(request.body) && type.indexOf('application/json') === 0) { request.body = JSON.stringify(request.body); } return function (response) { return response.bodyText ? when(response.text(), function (text) { var type = response.headers.get('Content-Type') || ''; if (type.indexOf('application/json') === 0 || isJson(text)) { try { response.body = JSON.parse(text); } catch (e) { response.body = null; } } else { response.body = text; } return response; }) : response; }; } function isJson(str) { var start = str.match(/^\s*(\[|\{)/); var end = { '[': /]\s*$/, '{': /}\s*$/ }; return start && end[start[1]].test(str); } /** * JSONP client (Browser). */ function jsonpClient (request) { return new PromiseObj(function (resolve) { var name = request.jsonp || 'callback', callback = request.jsonpCallback || '_jsonp' + Math.random().toString(36).substr(2), body = null, handler, script; handler = function handler(_ref) { var type = _ref.type; var status = 0; if (type === 'load' && body !== null) { status = 200; } else if (type === 'error') { status = 500; } if (status && window[callback]) { delete window[callback]; document.body.removeChild(script); } resolve(request.respondWith(body, { status: status })); }; window[callback] = function (result) { body = JSON.stringify(result); }; request.abort = function () { handler({ type: 'abort' }); }; request.params[name] = callback; if (request.timeout) { setTimeout(request.abort, request.timeout); } script = document.createElement('script'); script.src = request.getUrl(); script.type = 'text/javascript'; script.async = true; script.onload = handler; script.onerror = handler; document.body.appendChild(script); }); } /** * JSONP Interceptor. */ function jsonp (request) { if (request.method == 'JSONP') { request.client = jsonpClient; } } /** * Before Interceptor. */ function before (request) { if (isFunction(request.before)) { request.before.call(this, request); } } /** * HTTP method override Interceptor. */ function method (request) { if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { request.headers.set('X-HTTP-Method-Override', request.method); request.method = 'POST'; } } /** * Header Interceptor. */ function header (request) { 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); } }); } /** * XMLHttp client (Browser). */ function xhrClient (request) { return new PromiseObj(function (resolve) { var xhr = new XMLHttpRequest(), handler = function handler(event) { 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) }); each(trim(xhr.getAllResponseHeaders()).split('\n'), function (row) { response.headers.append(row.slice(0, row.indexOf(':')), row.slice(row.indexOf(':') + 1)); }); resolve(response); }; request.abort = function () { return xhr.abort(); }; xhr.open(request.method, request.getUrl(), true); if (request.timeout) { xhr.timeout = request.timeout; } if (request.responseType && 'responseType' in xhr) { xhr.responseType = request.responseType; } if (request.withCredentials || request.credentials) { xhr.withCredentials = true; } if (!request.crossOrigin) { request.headers.set('X-Requested-With', 'XMLHttpRequest'); } // deprecated use downloadProgress if (isFunction(request.progress) && request.method === 'GET') { xhr.addEventListener('progress', request.progress); } if (isFunction(request.downloadProgress)) { xhr.addEventListener('progress', request.downloadProgress); } // deprecated use uploadProgress if (isFunction(request.progress) && /^(POST|PUT)$/i.test(request.method)) { xhr.upload.addEventListener('progress', request.progress); } if (isFunction(request.uploadProgress) && xhr.upload) { xhr.upload.addEventListener('progress', request.uploadProgress); } request.headers.forEach(function (value, name) { xhr.setRequestHeader(name, value); }); xhr.onload = handler; xhr.onabort = handler; xhr.onerror = handler; xhr.ontimeout = handler; xhr.send(request.getBody()); }); } /** * Http client (Node). */ function nodeClient (request) { var client = require('got'); return new PromiseObj(function (resolve) { var url = request.getUrl(); var body = request.getBody(); var method = request.method; var headers = {}, handler; request.headers.forEach(function (value, name) { headers[name] = value; }); client(url, { body: body, method: method, headers: headers }).then(handler = function handler(resp) { var response = request.respondWith(resp.body, { status: resp.statusCode, statusText: trim(resp.statusMessage) }); each(resp.headers, function (value, name) { response.headers.set(name, value); }); resolve(response); }, function (error$$1) { return handler(error$$1.response); }); }); } /** * Base client. */ function Client (context) { var reqHandlers = [sendRequest], resHandlers = []; if (!isObject(context)) { context = null; } function Client(request) { while (reqHandlers.length) { var handler = reqHandlers.pop(); if (isFunction(handler)) { var _ret = function () { var response = void 0, next = void 0; response = handler.call(context, request, function (val) { return next = val; }) || next; if (isObject(response)) { return { v: new PromiseObj(function (resolve, reject) { resHandlers.forEach(function (handler) { response = when(response, function (response) { return handler.call(context, response) || response; }, reject); }); when(response, resolve, reject); }, context) }; } if (isFunction(response)) { resHandlers.unshift(response); } }(); if (typeof _ret === "object") return _ret.v; } else { warn("Invalid interceptor of type " + typeof handler + ", must be a function"); } } } Client.use = function (handler) { reqHandlers.push(handler); }; return Client; } function sendRequest(request) { var client = request.client || (inBrowser ? xhrClient : nodeClient); return client(request); } /** * HTTP Headers. */ var Headers = /*#__PURE__*/function () { function Headers(headers) { var _this = this; this.map = {}; each(headers, function (value, name) { return _this.append(name, value); }); } var _proto = Headers.prototype; _proto.has = function has(name) { return getName(this.map, name) !== null; }; _proto.get = function get(name) { var list = this.map[getName(this.map, name)]; return list ? list.join() : null; }; _proto.getAll = function getAll(name) { return this.map[getName(this.map, name)] || []; }; _proto.set = function set(name, value) { this.map[normalizeName(getName(this.map, name) || name)] = [trim(value)]; }; _proto.append = function append(name, value) { var list = this.map[getName(this.map, name)]; if (list) { list.push(trim(value)); } else { this.set(name, value); } }; _proto["delete"] = function _delete(name) { delete this.map[getName(this.map, name)]; }; _proto.deleteAll = function deleteAll() { this.map = {}; }; _proto.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 getName(map, name) { return Object.keys(map).reduce(function (prev, curr) { return toLower(name) === toLower(curr) ? curr : prev; }, null); } function normalizeName(name) { if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name)) { throw new TypeError('Invalid character in header field name'); } return trim(name); } /** * HTTP Response. */ var Response = /*#__PURE__*/function () { function Response(body, _ref) { var url = _ref.url, headers = _ref.headers, status = _ref.status, statusText = _ref.statusText; this.url = url; this.ok = status >= 200 && status < 300; this.status = status || 0; this.statusText = statusText || ''; 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); } } } var _proto = Response.prototype; _proto.blob = function blob() { return when(this.bodyBlob); }; _proto.text = function text() { return when(this.bodyText); }; _proto.json = function json() { return when(this.text(), function (text) { return JSON.parse(text); }); }; return Response; }(); Object.defineProperty(Response.prototype, 'data', { get: function get() { return this.body; }, set: function set(body) { this.body = body; } }); function blobText(body) { return new PromiseObj(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 = /*#__PURE__*/function () { function Request(options$$1) { this.body = null; this.params = {}; assign(this, options$$1, { method: toUpper(options$$1.method || 'GET') }); if (!(this.headers instanceof Headers)) { this.headers = new Headers(this.headers); } } var _proto = Request.prototype; _proto.getUrl = function getUrl() { return Url(this); }; _proto.getBody = function getBody() { return this.body; }; _proto.respondWith = function respondWith(body, options$$1) { return new Response(body, assign(options$$1 || {}, { url: this.getUrl() })); }; return Request; }(); /** * Service for sending network requests. */ var COMMON_HEADERS = { 'Accept': 'application/json, text/plain, */*' }; var JSON_CONTENT_TYPE = { 'Content-Type': 'application/json;charset=utf-8' }; function Http(options$$1) { var self = this || {}, client = Client(self.$vm); defaults(options$$1 || {}, self.$options, Http.options); Http.interceptors.forEach(function (handler) { if (isString(handler)) { handler = Http.interceptor[handler]; } if (isFunction(handler)) { client.use(handler); } }); return client(new Request(options$$1)).then(function (response) { return response.ok ? response : PromiseObj.reject(response); }, function (response) { if (response instanceof Error) { error(response); } return PromiseObj.reject(response); }); } Http.options = {}; Http.headers = { put: JSON_CONTENT_TYPE, post: JSON_CONTENT_TYPE, patch: JSON_CONTENT_TYPE, "delete": JSON_CONTENT_TYPE, common: COMMON_HEADERS, custom: {} }; Http.interceptor = { before: before, method: method, jsonp: jsonp, json: json, form: form, header: header, cors: cors }; Http.interceptors = ['before', 'method', 'jsonp', 'json', 'form', 'header', 'cors']; ['get', 'delete', 'head', 'jsonp'].forEach(function (method$$1) { Http[method$$1] = function (url, options$$1) { return this(assign(options$$1 || {}, { url: url, method: method$$1 })); }; }); ['post', 'put', 'patch'].forEach(function (method$$1) { Http[method$$1] = function (url, body, options$$1) { return this(assign(options$$1 || {}, { url: url, method: method$$1, body: body })); }; }); /** * Service for interacting with RESTful services. */ function Resource(url, params, actions, options$$1) { var self = this || {}, resource = {}; actions = assign({}, Resource.actions, actions); each(actions, function (action, name) { action = merge({ url: url, params: assign({}, params) }, options$$1, action); resource[name] = function () { return (self.$http || Http)(opts(action, arguments)); }; }); return resource; } function opts(action, args) { var options$$1 = 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$$1.method)) { body = args[0]; } else { params = args[0]; } break; case 0: break; default: throw 'Expected up to 2 arguments [params, body], got ' + args.length + ' arguments'; } options$$1.body = body; options$$1.params = assign({}, options$$1.params, params); return options$$1; } 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 = PromiseObj; Object.defineProperties(Vue.prototype, { $url: { get: function get() { return options(Vue.url, this, this.$options.url); } }, $http: { get: function get() { return options(Vue.http, this, this.$options.http); } }, $resource: { get: function get() { return Vue.resource.bind(this); } }, $promise: { get: function get() { var _this = this; return function (executor) { return new Vue.Promise(executor, _this); }; } } }); } if (typeof window !== 'undefined' && window.Vue && !window.Vue.resource) { window.Vue.use(plugin); } return plugin; }))); ================================================ FILE: docs/README.md ================================================ # Documentation - [Configuration](config.md) - [HTTP Requests/Response](http.md) - [Creating Resources](resource.md) - [Code Recipes](recipes.md) - [API Reference](api.md) ================================================ FILE: docs/api.md ================================================ # API Reference ## Request ```js { // Constructor constructor(object: config) // Properties url (string) body (any) headers (Headers) method (string) params (object) timeout (number) credentials (boolean) emulateHTTP (boolean) emulateJSON (boolean) before (function(Request)) progress (function(Event)) // Methods getUrl() (string) getBody() (any) respondWith(any: body, object: config) (Response) abort() } ``` ## Response ```js { // Constructor constructor(any: body, object: {string: url, object: headers, number: status, string: statusText}) // Properties url (string) body (any) headers (Headers) ok (boolean) status (number) statusText (string) // Methods blob() (Promise) text() (Promise) json() (Promise) } ``` ## Headers ```js { // Constructor constructor(object: headers) // Properties map (object) // Methods has(string: name) (boolean) get(string: name) (string) getAll() (string[]) set(string: name, string: value) (void) append(string: name, string: value) (void) delete(string: name) (void) forEach(function: callback, any: thisArg) (void) } ``` ================================================ FILE: docs/config.md ================================================ # Configuration Set default values using the global configuration. ```js Vue.http.options.root = '/root'; Vue.http.headers.common['Authorization'] = 'Basic YXBpOnBhc3N3b3Jk'; ``` Set default values inside your Vue component options. ```js new Vue({ http: { root: '/root', headers: { Authorization: 'Basic YXBpOnBhc3N3b3Jk' } } }) ``` Note that for the root option to work, the path of the request must be relative. This will use this the root option: `Vue.http.get('someUrl')` while this will not: `Vue.http.get('/someUrl')`. ## Webpack/Browserify Add `vue` and `vue-resource` to your `package.json`, then `npm install`, then add these lines in your code: ```js var Vue = require('vue'); var VueResource = require('vue-resource'); Vue.use(VueResource); ``` ## Legacy web servers If your web server can't handle requests encoded as `application/json`, you can enable the `emulateJSON` option. This will send the request as `application/x-www-form-urlencoded` MIME type, as if from an normal HTML form. ```js Vue.http.options.emulateJSON = true; ``` If your web server can't handle REST/HTTP requests like `PUT`, `PATCH` and `DELETE`, you can enable the `emulateHTTP` option. This will set the `X-HTTP-Method-Override` header with the actual HTTP method and use a normal `POST` request. ```js Vue.http.options.emulateHTTP = true; ``` ## Typescript Support Typescript for vue-resource should work out of the box since the type definition files are included within the npm package. ================================================ FILE: docs/http.md ================================================ # HTTP The http service can be used globally `Vue.http` or in a Vue instance `this.$http`. ## Usage A Vue instance provides the `this.$http` service which can send HTTP requests. A request method call returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that resolves to the response. Also the Vue instance will be automatically bound to `this` in all function callbacks. ```js { // GET /someUrl this.$http.get('/someUrl').then(response => { // success callback }, response => { // error callback }); } ``` ## Methods Shortcut methods are available for all request types. These methods work globally or in a Vue instance. ```js // global Vue object Vue.http.get('/someUrl', [config]).then(successCallback, errorCallback); Vue.http.post('/someUrl', [body], [config]).then(successCallback, errorCallback); // in a Vue instance this.$http.get('/someUrl', [config]).then(successCallback, errorCallback); this.$http.post('/someUrl', [body], [config]).then(successCallback, errorCallback); ``` List of shortcut methods: * `get(url, [config])` * `head(url, [config])` * `delete(url, [config])` * `jsonp(url, [config])` * `post(url, [body], [config])` * `put(url, [body], [config])` * `patch(url, [body], [config])` ## Config Parameter | Type | Description --------- | ---- | ----------- url | `string` | URL to which the request is sent 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, ...) responseType | `string` | Type of the response body (e.g. text, blob, json, ...) timeout | `number` | Request timeout in milliseconds (`0` means no timeout) credentials | `boolean` | Indicates whether or not cross-site Access-Control requests should be made using credentials emulateHTTP | `boolean` | Send PUT, PATCH and DELETE requests with a HTTP POST and set the `X-HTTP-Method-Override` header emulateJSON | `boolean` | Send request body as `application/x-www-form-urlencoded` content type before | `function(request)` | Callback function to modify the request object before it is sent uploadProgress | `function(event)` | Callback function to handle the [ProgressEvent](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent) of uploads downloadProgress | `function(event)` | Callback function to handle the [ProgressEvent](https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent) of downloads ## Response A request resolves to a response object with the following properties and methods: Property | Type | Description -------- | ---- | ----------- url | `string` | Response URL origin body | `Object`, `Blob`, `string` | Response body 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 **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 { // POST /someUrl this.$http.post('/someUrl', {foo: 'bar'}).then(response => { // get status response.status; // get status text response.statusText; // get 'Expires' header response.headers.get('Expires'); // get body data this.someData = response.body; }, response => { // error callback }); } ``` Send a get request with URL query parameters and a custom headers. ```js { // GET /someUrl?foo=bar this.$http.get('/someUrl', {params: {foo: 'bar'}, headers: {'X-Custom': '...'}}).then(response => { // success callback }, response => { // error callback }); } ``` Fetch an image and use the blob() method to extract the image body content from the response. ```js { // GET /image.jpg this.$http.get('/image.jpg', {responseType: 'blob'}).then(response => { // resolve to Blob return response.blob(); }).then(blob => { // use image Blob }); } ``` ## Interceptors Interceptors can be defined globally and are used for pre- and postprocessing of a request. If a request is sent using `this.$http` or `this.$resource` the current Vue instance is available as `this` in a interceptor callback. ### Request processing ```js Vue.http.interceptors.push(function(request) { // modify method request.method = 'POST'; // modify headers request.headers.set('X-CSRF-TOKEN', 'TOKEN'); request.headers.set('Authorization', 'Bearer TOKEN'); }); ``` ### Request and Response processing ```js Vue.http.interceptors.push(function(request) { // modify request request.method = 'POST'; // return response callback return function(response) { // modify response response.body = '...'; }; }); ``` ### Return a Response and stop processing ```js Vue.http.interceptors.push(function(request) { // modify request ... // stop and return response return request.respondWith(body, { status: 404, statusText: 'Not found' }); }); ``` ### Overriding default interceptors All default interceptors callbacks can be overriden to change their behavior. All interceptors are exposed through the `Vue.http.interceptor` object with their names `before`, `method`, `jsonp`, `json`, `form`, `header` and `cors`. ```js Vue.http.interceptor.before = function(request) { // override before interceptor }; ================================================ FILE: docs/recipes.md ================================================ # Code Recipes The Recipes provide code examples to common use-cases. If you want to share your recipe feel free to send a [pull request](https://github.com/pagekit/vue-resource/pulls). ## Forms Sending forms using [FormData](https://developer.mozilla.org/en-US/docs/Web/API/FormData). ```js { var formData = new FormData(); // append string formData.append('foo', 'bar'); // append Blob/File object formData.append('pic', fileInput, 'mypic.jpg'); // POST /someUrl this.$http.post('/someUrl', formData).then(response => { // success callback }, response => { // error callback }); } ``` ## Abort a request Abort a previous request when a new request is about to be sent. For example when typing in a autocomplete input. ```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 }); } ``` ================================================ FILE: docs/resource.md ================================================ # Resource The resource service can be used globally `Vue.resource` or in a Vue instance `this.$resource`. ## Methods * `resource(url, [params], [actions], [options])` ## Default Actions ```js get: {method: 'GET'}, save: {method: 'POST'}, query: {method: 'GET'}, update: {method: 'PUT'}, remove: {method: 'DELETE'}, delete: {method: 'DELETE'} ``` ## Example ```js { var resource = this.$resource('someItem{/id}'); // GET someItem/1 resource.get({id: 1}).then(response => { this.item = response.body; }); // 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 { 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.item = response.body; }); // POST someItem/bar/1 resource.bar({id: 1}, {item: this.item}).then(response => { // success callback }, response => { // error callback }); } ``` **Note:** When passing only one single object (for POST, PUT and PATCH custom actions), it will defaults to body param. If you need set url params you will have to pass an empty object as second argument. ```js { var resource = this.$resource('someItem{/id}', {}, { baz: {method: 'POST', url: 'someItem/baz{/id}'} }); // POST someItem/baz resource.baz({id: 1}).then(response => { // success callback }, response => { // error callback }); // POST someItem/baz/1 resource.baz({id: 1}, {}).then(response => { // success callback }, response => { // error callback }); ``` ================================================ FILE: package.json ================================================ { "name": "vue-resource", "version": "1.5.3", "main": "dist/vue-resource.common.js", "module": "dist/vue-resource.esm.js", "unpkg": "dist/vue-resource.min.js", "jsdelivr": "dist/vue-resource.min.js", "typings": "types/index.d.ts", "description": "The HTTP client for Vue.js", "homepage": "https://github.com/pagekit/vue-resource", "license": "MIT", "keywords": [ "vue", "xhr", "http", "ajax" ], "bugs": { "url": "https://github.com/pagekit/vue-resource/issues" }, "repository": { "type": "git", "url": "git+https://github.com/pagekit/vue-resource.git" }, "scripts": { "up": "yarn upgrade-interactive --latest", "test": "jest --env=node", "karma": "karma start test/karma.conf.js --single-run", "build": "node build/build.js", "release": "node build/release.js", "webpack": "webpack --config test/webpack.config.js" }, "browser": { "got": false }, "dependencies": { "got": ">=8.0 <12.0" }, "devDependencies": { "@babel/core": "^7.2.2", "@babel/preset-env": "^7.2.0", "babel-loader": "^8.0.4", "eslint": "^5.11.1", "generate-release": "^1.1.1", "jasmine": "^3.3.1", "jasmine-core": "^3.3.0", "jest": "^23.6.0", "karma": "^3.1.4", "karma-chrome-launcher": "^2.2.0", "karma-firefox-launcher": "^1.1.0", "karma-jasmine": "^2.0.1", "karma-safari-launcher": "^1.0.0", "karma-webpack": "^3.0.5", "replace-in-file": "^3.4.2", "rollup": "^0.66.0", "rollup-plugin-babel": "^4.1.0", "rollup-plugin-replace": "^2.1.0", "uglify-js": "^3.4.9", "vue": "^2.5.21", "webpack": "^4.28.3", "webpack-cli": "^3.1.2" } } ================================================ FILE: src/http/client/index.js ================================================ /** * Base client. */ import Promise from '../../promise'; import xhrClient from './xhr'; import nodeClient from './node'; import {warn, when, isObject, isFunction, inBrowser} from '../../util'; export default function (context) { const reqHandlers = [sendRequest], resHandlers = []; if (!isObject(context)) { context = null; } function Client(request) { while (reqHandlers.length) { const handler = reqHandlers.pop(); if (isFunction(handler)) { let response, next; response = handler.call(context, request, val => next = val) || next; if (isObject(response)) { return new Promise((resolve, reject) => { resHandlers.forEach(handler => { response = when(response, response => { return handler.call(context, response) || response; }, reject); }); when(response, resolve, reject); }, context); } if (isFunction(response)) { resHandlers.unshift(response); } } else { warn(`Invalid interceptor of type ${typeof handler}, must be a function`); } } } Client.use = handler => { reqHandlers.push(handler); }; return Client; } function sendRequest(request) { const client = request.client || (inBrowser ? xhrClient : nodeClient); return client(request); } ================================================ FILE: src/http/client/jsonp.js ================================================ /** * JSONP client (Browser). */ import Promise from '../../promise'; export default function (request) { return new Promise(resolve => { var name = request.jsonp || 'callback', callback = request.jsonpCallback || '_jsonp' + Math.random().toString(36).substr(2), body = null, handler, script; handler = ({type}) => { var status = 0; if (type === 'load' && body !== null) { status = 200; } else if (type === 'error') { status = 500; } if (status && window[callback]) { delete window[callback]; document.body.removeChild(script); } resolve(request.respondWith(body, {status})); }; window[callback] = result => { body = JSON.stringify(result); }; request.abort = () => { handler({type: 'abort'}); }; request.params[name] = callback; if (request.timeout) { setTimeout(request.abort, request.timeout); } script = document.createElement('script'); script.src = request.getUrl(); script.type = 'text/javascript'; script.async = true; script.onload = handler; script.onerror = handler; document.body.appendChild(script); }); } ================================================ FILE: src/http/client/node.js ================================================ /** * Http client (Node). */ import Promise from '../../promise'; import {each, trim} from '../../util'; export default function (request) { const client = require('got'); return new Promise(resolve => { var url = request.getUrl(); var body = request.getBody(); var method = request.method; var headers = {}, handler; request.headers.forEach((value, name) => { headers[name] = value; }); client(url, {body, method, headers}).then(handler = (resp) => { var response = request.respondWith(resp.body, { status: resp.statusCode, statusText: trim(resp.statusMessage) }); each(resp.headers, (value, name) => { response.headers.set(name, value); }); resolve(response); }, error => handler(error.response)); }); } ================================================ FILE: src/http/client/xdr.js ================================================ /** * XDomain client (Internet Explorer). */ import Promise from '../../promise'; export default function (request) { return new Promise(resolve => { var xdr = new XDomainRequest(), handler = ({type}) => { var status = 0; if (type === 'load') { status = 200; } else if (type === 'error') { status = 500; } resolve(request.respondWith(xdr.responseText, {status})); }; request.abort = () => xdr.abort(); xdr.open(request.method, request.getUrl()); if (request.timeout) { xdr.timeout = request.timeout; } xdr.onload = handler; xdr.onabort = handler; xdr.onerror = handler; xdr.ontimeout = handler; xdr.onprogress = () => {}; xdr.send(request.getBody()); }); } ================================================ FILE: src/http/client/xhr.js ================================================ /** * XMLHttp client (Browser). */ import Promise from '../../promise'; import {each, trim, isFunction} from '../../util'; export default function (request) { return new Promise(resolve => { var xhr = new XMLHttpRequest(), handler = (event) => { 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) }); each(trim(xhr.getAllResponseHeaders()).split('\n'), row => { response.headers.append(row.slice(0, row.indexOf(':')), row.slice(row.indexOf(':') + 1)); }); resolve(response); }; request.abort = () => xhr.abort(); xhr.open(request.method, request.getUrl(), true); if (request.timeout) { xhr.timeout = request.timeout; } if (request.responseType && 'responseType' in xhr) { xhr.responseType = request.responseType; } if (request.withCredentials || request.credentials) { xhr.withCredentials = true; } if (!request.crossOrigin) { request.headers.set('X-Requested-With', 'XMLHttpRequest'); } // deprecated use downloadProgress if (isFunction(request.progress) && request.method === 'GET') { xhr.addEventListener('progress', request.progress); } if (isFunction(request.downloadProgress)) { xhr.addEventListener('progress', request.downloadProgress); } // deprecated use uploadProgress if (isFunction(request.progress) && /^(POST|PUT)$/i.test(request.method)) { xhr.upload.addEventListener('progress', request.progress); } if (isFunction(request.uploadProgress) && xhr.upload) { xhr.upload.addEventListener('progress', request.uploadProgress); } request.headers.forEach((value, name) => { xhr.setRequestHeader(name, value); }); xhr.onload = handler; xhr.onabort = handler; xhr.onerror = handler; xhr.ontimeout = handler; xhr.send(request.getBody()); }); } ================================================ FILE: src/http/headers.js ================================================ /** * 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 getName(this.map, name) !== null; } get(name) { var list = this.map[getName(this.map, name)]; return list ? list.join() : null; } getAll(name) { return this.map[getName(this.map, name)] || []; } set(name, value) { this.map[normalizeName(getName(this.map, name) || name)] = [trim(value)]; } append(name, value) { var list = this.map[getName(this.map, name)]; if (list) { list.push(trim(value)); } else { this.set(name, value); } } delete(name) { delete this.map[getName(this.map, name)]; } deleteAll() { this.map = {}; } forEach(callback, thisArg) { each(this.map, (list, name) => { each(list, value => callback.call(thisArg, value, name, this)); }); } } function getName(map, name) { return Object.keys(map).reduce((prev, curr) => { return toLower(name) === toLower(curr) ? curr : prev; }, null); } function normalizeName(name) { if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name)) { throw new TypeError('Invalid character in header field name'); } return trim(name); } ================================================ FILE: src/http/index.js ================================================ /** * Service for sending network requests. */ const COMMON_HEADERS = {'Accept': 'application/json, text/plain, */*'}; const JSON_CONTENT_TYPE = {'Content-Type': 'application/json;charset=utf-8'}; import cors from './interceptor/cors'; import form from './interceptor/form'; import json from './interceptor/json'; import jsonp from './interceptor/jsonp'; import before from './interceptor/before'; import method from './interceptor/method'; import header from './interceptor/header'; import Client from './client/index'; import Request from './request'; import Promise from '../promise'; import {assign, defaults, error, isString, isFunction} from '../util'; export default function Http(options) { var self = this || {}, client = Client(self.$vm); defaults(options || {}, self.$options, Http.options); Http.interceptors.forEach(handler => { if (isString(handler)) { handler = Http.interceptor[handler]; } if (isFunction(handler)) { client.use(handler); } }); return client(new Request(options)).then(response => { return response.ok ? response : Promise.reject(response); }, response => { if (response instanceof Error) { error(response); } return Promise.reject(response); }); } Http.options = {}; Http.headers = { put: JSON_CONTENT_TYPE, post: JSON_CONTENT_TYPE, patch: JSON_CONTENT_TYPE, delete: JSON_CONTENT_TYPE, common: COMMON_HEADERS, custom: {} }; Http.interceptor = {before, method, jsonp, json, form, header, cors}; Http.interceptors = ['before', 'method', 'jsonp', 'json', 'form', 'header', 'cors']; ['get', 'delete', 'head', 'jsonp'].forEach(method => { Http[method] = function (url, options) { return this(assign(options || {}, {url, method})); }; }); ['post', 'put', 'patch'].forEach(method => { Http[method] = function (url, body, options) { return this(assign(options || {}, {url, method, body})); }; }); ================================================ FILE: src/http/interceptor/before.js ================================================ /** * Before Interceptor. */ import {isFunction} from '../../util'; export default function (request) { if (isFunction(request.before)) { request.before.call(this, request); } } ================================================ FILE: src/http/interceptor/cors.js ================================================ /** * CORS Interceptor. */ import Url from '../../url/index'; import xdrClient from '../client/xdr'; import {inBrowser} from '../../util'; const SUPPORTS_CORS = inBrowser && 'withCredentials' in new XMLHttpRequest(); export default function (request) { if (inBrowser) { const orgUrl = Url.parse(location.href); const reqUrl = Url.parse(request.getUrl()); if (reqUrl.protocol !== orgUrl.protocol || reqUrl.host !== orgUrl.host) { request.crossOrigin = true; request.emulateHTTP = false; if (!SUPPORTS_CORS) { request.client = xdrClient; } } } } ================================================ FILE: src/http/interceptor/form.js ================================================ /** * Form data Interceptor. */ import Url from '../../url/index'; import {isObject, isFormData} from '../../util'; export default function (request) { if (isFormData(request.body)) { request.headers.delete('Content-Type'); } else if (isObject(request.body) && request.emulateJSON) { request.body = Url.params(request.body); request.headers.set('Content-Type', 'application/x-www-form-urlencoded'); } } ================================================ FILE: src/http/interceptor/header.js ================================================ /** * Header Interceptor. */ import Http from '../index'; import {assign, each, toLower} from '../../util'; export default function (request) { const headers = assign({}, Http.headers.common, !request.crossOrigin ? Http.headers.custom : {}, Http.headers[toLower(request.method)] ); each(headers, (value, name) => { if (!request.headers.has(name)) { request.headers.set(name, value); } }); } ================================================ FILE: src/http/interceptor/json.js ================================================ /** * JSON Interceptor. */ import {when, isObject} from '../../util'; export default function (request) { const type = request.headers.get('Content-Type') || ''; if (isObject(request.body) && type.indexOf('application/json') === 0) { request.body = JSON.stringify(request.body); } return response => { return response.bodyText ? when(response.text(), text => { const type = response.headers.get('Content-Type') || ''; if (type.indexOf('application/json') === 0 || isJson(text)) { try { response.body = JSON.parse(text); } catch (e) { response.body = null; } } else { response.body = text; } return response; }) : response; }; } function isJson(str) { const start = str.match(/^\s*(\[|\{)/); const end = {'[': /]\s*$/, '{': /}\s*$/}; return start && end[start[1]].test(str); } ================================================ FILE: src/http/interceptor/jsonp.js ================================================ /** * JSONP Interceptor. */ import jsonpClient from '../client/jsonp'; export default function (request) { if (request.method == 'JSONP') { request.client = jsonpClient; } } ================================================ FILE: src/http/interceptor/method.js ================================================ /** * HTTP method override Interceptor. */ export default function (request) { if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) { request.headers.set('X-HTTP-Method-Override', request.method); request.method = 'POST'; } } ================================================ FILE: src/http/request.js ================================================ /** * HTTP Request. */ import Url from '../url/index'; import Headers from './headers'; import Response from './response'; import {assign, toUpper} from '../util'; export default class Request { constructor(options) { this.body = null; this.params = {}; assign(this, options, { method: toUpper(options.method || 'GET') }); if (!(this.headers instanceof Headers)) { this.headers = new Headers(this.headers); } } getUrl() { return Url(this); } getBody() { return this.body; } respondWith(body, options) { return new Response(body, assign(options || {}, {url: this.getUrl()})); } } ================================================ FILE: src/http/response.js ================================================ /** * 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.ok = status >= 200 && status < 300; this.status = status || 0; this.statusText = statusText || ''; 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); } } } blob() { return when(this.bodyBlob); } text() { return when(this.bodyText); } json() { return when(this.text(), text => JSON.parse(text)); } } Object.defineProperty(Response.prototype, 'data', { get() { return this.body; }, set(body) { this.body = body; } }); 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; } ================================================ FILE: src/index.js ================================================ /** * Install plugin. */ import Url from './url/index'; import Http from './http/index'; import Promise from './promise'; import Resource from './resource'; import Util, {options} from './util'; function plugin(Vue) { if (plugin.installed) { return; } Util(Vue); Vue.url = Url; Vue.http = Http; Vue.resource = Resource; Vue.Promise = Promise; Object.defineProperties(Vue.prototype, { $url: { get() { return options(Vue.url, this, this.$options.url); } }, $http: { get() { return options(Vue.http, this, this.$options.http); } }, $resource: { get() { return Vue.resource.bind(this); } }, $promise: { get() { return (executor) => new Vue.Promise(executor, this); } } }); } if (typeof window !== 'undefined' && window.Vue && !window.Vue.resource) { window.Vue.use(plugin); } export default plugin; ================================================ FILE: src/lib/promise.js ================================================ /** * Promises/A+ polyfill v1.1.4 (https://github.com/bramstein/promis) */ const RESOLVED = 0; const REJECTED = 1; const PENDING = 2; import {nextTick} from '../util'; export default function Promise(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.reject = function (r) { return new Promise(function (resolve, reject) { reject(r); }); }; Promise.resolve = function (x) { return new Promise(function (resolve, reject) { resolve(x); }); }; Promise.all = function all(iterable) { return new Promise(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.resolve(iterable[i]).then(resolver(i), reject); } }); }; Promise.race = function race(iterable) { return new Promise(function (resolve, reject) { for (var i = 0; i < iterable.length; i += 1) { Promise.resolve(iterable[i]).then(resolve, reject); } }); }; var p = Promise.prototype; p.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.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.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.then = function then(onResolved, onRejected) { var promise = this; return new Promise(function (resolve, reject) { promise.deferred.push([onResolved, onRejected, resolve, reject]); promise.notify(); }); }; p.catch = function (onRejected) { return this.then(undefined, onRejected); }; ================================================ FILE: src/lib/url-template.js ================================================ /** * URL Template v2.0.6 (https://github.com/bramstein/url-template) */ export function expand(url, params, variables) { var tmpl = parse(url), expanded = tmpl.expand(params); if (variables) { variables.push.apply(variables, tmpl.vars); } return expanded; } export function parse(template) { var operators = ['+', '#', '.', '/', ';', '?', '&'], variables = []; return { vars: variables, expand(context) { return template.replace(/\{([^{}]+)\}|([^{}]+)/g, (_, 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((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((value) => { result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : null)); }); } else { Object.keys(value).forEach((k) => { if (isDefined(value[k])) { result.push(encodeValue(operator, value[k], k)); } }); } } else { var tmp = []; if (Array.isArray(value)) { value.filter(isDefined).forEach((value) => { tmp.push(encodeValue(operator, value)); }); } else { Object.keys(value).forEach((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; } function isDefined(value) { return value !== undefined && value !== null; } function isKeyOperator(operator) { return operator === ';' || operator === '&' || operator === '?'; } function encodeValue(operator, value, key) { value = (operator === '+' || operator === '#') ? encodeReserved(value) : encodeURIComponent(value); if (key) { return encodeURIComponent(key) + '=' + value; } else { return value; } } function encodeReserved(str) { return str.split(/(%[0-9A-Fa-f]{2})/g).map((part) => { if (!/%[0-9A-Fa-f]/.test(part)) { part = encodeURI(part); } return part; }).join(''); } ================================================ FILE: src/promise.js ================================================ /** * Promise adapter. */ import PromiseLib from './lib/promise'; if (typeof Promise === 'undefined') { window.Promise = PromiseLib; } export default function PromiseObj(executor, context) { if (executor instanceof Promise) { this.promise = executor; } else { this.promise = new Promise(executor.bind(context)); } this.context = context; } PromiseObj.all = function (iterable, context) { return new PromiseObj(Promise.all(iterable), context); }; PromiseObj.resolve = function (value, context) { return new PromiseObj(Promise.resolve(value), context); }; PromiseObj.reject = function (reason, context) { return new PromiseObj(Promise.reject(reason), context); }; PromiseObj.race = function (iterable, context) { return new PromiseObj(Promise.race(iterable), context); }; var p = PromiseObj.prototype; p.bind = function (context) { this.context = context; return this; }; p.then = function (fulfilled, rejected) { if (fulfilled && fulfilled.bind && this.context) { fulfilled = fulfilled.bind(this.context); } if (rejected && rejected.bind && this.context) { rejected = rejected.bind(this.context); } return new PromiseObj(this.promise.then(fulfilled, rejected), this.context); }; p.catch = function (rejected) { if (rejected && rejected.bind && this.context) { rejected = rejected.bind(this.context); } return new PromiseObj(this.promise.catch(rejected), this.context); }; p.finally = function (callback) { return this.then(function (value) { callback.call(this); return value; }, function (reason) { callback.call(this); return Promise.reject(reason); } ); }; ================================================ FILE: src/resource.js ================================================ /** * Service for interacting with RESTful services. */ import Http from './http/index'; import {assign, each, merge} from './util'; export default function Resource(url, params, actions, options) { var self = this || {}, resource = {}; actions = assign({}, Resource.actions, actions ); each(actions, (action, name) => { action = merge({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 2 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'} }; ================================================ FILE: src/url/index.js ================================================ /** * Service for URL templating. */ import root from './root'; import query from './query'; import template from './template'; import {each, merge, isArray, isFunction, isObject, isPlainObject, isString} from '../util'; export default function Url(url, params) { var self = this || {}, options = url, transform; if (isString(url)) { options = {url, params}; } options = merge({}, Url.options, self.$options, options); Url.transforms.forEach(handler => { if (isString(handler)) { handler = Url.transform[handler]; } if (isFunction(handler)) { transform = factory(handler, transform, self.$vm); } }); return transform(options); } /** * Url options. */ Url.options = { url: '', root: null, params: {} }; /** * Url transforms. */ Url.transform = {template, query, root}; Url.transforms = ['template', 'query', 'root']; /** * Encodes a Url parameter string. * * @param {Object} obj */ Url.params = function (obj) { var params = [], escape = encodeURIComponent; params.add = function (key, value) { if (isFunction(value)) { value = value(); } if (value === null) { value = ''; } this.push(escape(key) + '=' + escape(value)); }; serialize(params, obj); return params.join('&').replace(/%20/g, '+'); }; /** * Parse a URL and return its components. * * @param {String} url */ Url.parse = function (url) { var el = document.createElement('a'); if (document.documentMode) { el.href = url; url = el.href; } 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 options => { return handler.call(vm, options, next); }; } function serialize(params, obj, scope) { var array = isArray(obj), plain = isPlainObject(obj), hash; each(obj, (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); } }); } ================================================ FILE: src/url/query.js ================================================ /** * Query Parameter Transform. */ import Url from './index'; import {each} from '../util'; export default function (options, next) { var urlParams = Object.keys(Url.options.params), query = {}, url = next(options); each(options.params, (value, key) => { if (urlParams.indexOf(key) === -1) { query[key] = value; } }); query = Url.params(query); if (query) { url += (url.indexOf('?') == -1 ? '?' : '&') + query; } return url; } ================================================ FILE: src/url/root.js ================================================ /** * Root Prefix Transform. */ import {isString, trimEnd} from '../util'; export default function (options, next) { var url = next(options); if (isString(options.root) && !/^(https?:)?\//.test(url)) { url = trimEnd(options.root, '/') + '/' + url; } return url; } ================================================ FILE: src/url/template.js ================================================ /** * URL Template (RFC 6570) Transform. */ import {expand} from '../lib/url-template'; export default function (options) { var variables = [], url = expand(options.url, options.params, variables); variables.forEach((key) => { delete options.params[key]; }); return url; } ================================================ FILE: src/util.js ================================================ /** * Utility functions. */ import Promise from './promise'; var {hasOwnProperty} = {}, {slice} = [], debug = false, ntick; export const inBrowser = typeof window !== 'undefined'; export default function ({config, nextTick}) { ntick = nextTick; debug = config.debug || !config.silent; } export function warn(msg) { if (typeof console !== 'undefined' && debug) { console.warn('[VueResource warn]: ' + msg); } } export function error(msg) { if (typeof console !== 'undefined') { console.error(msg); } } export function nextTick(cb, ctx) { return ntick(cb, ctx); } export function trim(str) { return str ? str.replace(/^\s*|\s*$/g, '') : ''; } export function trimEnd(str, chars) { if (str && chars === undefined) { return str.replace(/\s+$/, ''); } if (!str || !chars) { return str; } return str.replace(new RegExp(`[${chars}]+$`), ''); } 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) { return typeof val === 'string'; } export function isBoolean(val) { return val === true || val === false; } export function isFunction(val) { return typeof val === 'function'; } export function isObject(obj) { return obj !== null && typeof obj === 'object'; } 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; } export function when(value, fulfilled, rejected) { var promise = Promise.resolve(value); if (arguments.length < 2) { return promise; } return promise.then(fulfilled, rejected); } export function options(fn, obj, opts) { opts = opts || {}; if (isFunction(opts)) { opts = opts.call(obj); } return merge(fn.bind({$vm: obj, $options: opts}), fn, {$options: opts}); } export function each(obj, iterator) { var i, key; if (isArray(obj)) { for (i = 0; i < obj.length; i++) { iterator.call(obj[i], obj[i], i); } } else if (isObject(obj)) { for (key in obj) { if (hasOwnProperty.call(obj, key)) { iterator.call(obj[key], obj[key], key); } } } return obj; } export const assign = Object.assign || _assign; export function merge(target) { var args = slice.call(arguments, 1); args.forEach(source => { _merge(target, source, true); }); return target; } export function defaults(target) { var args = slice.call(arguments, 1); args.forEach(source => { for (var key in source) { if (target[key] === undefined) { target[key] = source[key]; } } }); return target; } function _assign(target) { var args = slice.call(arguments, 1); args.forEach(source => { _merge(target, source); }); 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]; } } } ================================================ FILE: test/data/invalid.json ================================================ invalid ================================================ FILE: test/data/text.txt ================================================ text ================================================ FILE: test/data/valid.json ================================================ {"foo": "bar"} ================================================ FILE: test/http.js ================================================ import Vue from 'vue'; describe('Vue.http', function () { it('get("data/text.txt")', done => { Vue.http.get('data/text.txt').then(res => { expect(res.ok).toBe(true); expect(res.status).toBe(200); expect(res.body).toBe('text'); expect(res.data).toBe(res.body); expect(res.headers.get('Content-Type')).toBe('text/plain'); done(); }); }); it('get("data/valid.json")', done => { Vue.http.get('data/valid.json').then(res => { expect(res.ok).toBe(true); expect(res.status).toBe(200); expect(typeof res.body).toBe('object'); expect(res.body.foo).toBe('bar'); done(); }); }); it('get("data/invalid.json")', done => { Vue.http.get('data/invalid.json').then(res => { expect(res.ok).toBe(true); expect(res.status).toBe(200); expect(res.body).toBeNull(); done(); }); }); it('get("github.com/avatar")', done => { Vue.http.get('https://avatars1.githubusercontent.com/u/6128107', {responseType: 'blob'}).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(); }); }); it('get("cors-api.appspot.com")', done => { Vue.http.get('http://server.cors-api.appspot.com/server?id=1&enable=true').then(res => { expect(res.ok).toBe(true); expect(res.status).toBe(200); expect(typeof res.body).toBe('object'); expect(res.body.shift().requestType).toBe('cors'); if (res.headers.get('Content-Type')) { expect(res.headers.get('Content-Type')).toBe('application/json'); } done(); }); }); it('jsonp("jsfiddle.net/jsonp")', done => { Vue.http.jsonp('http://jsfiddle.net/echo/jsonp/', {params: {foo: 'bar'}}).then(res => { expect(res.ok).toBe(true); expect(res.status).toBe(200); expect(typeof res.body).toBe('object'); expect(res.body.foo).toBe('bar'); done(); }); }); }); describe('this.$http', function () { it('get("data/valid.json")', done => { var vm = new Vue({ created() { this.$http.get('data/valid.json').then(res => { expect(this).toBe(vm); expect(res.ok).toBe(true); expect(res.status).toBe(200); expect(typeof res.body).toBe('object'); expect(res.body.foo).toBe('bar'); done(); }); } }); }); it('get("data/valid.json") with timeout', done => { var vm = new Vue({ created() { var random = Math.random().toString(36).substr(2); this.$http.get(`data/valid.json?${random}`, {timeout: 1}).then(res => { fail('Callback has been called'); }, res => { expect(res.ok).toBe(false); expect(res.status).toBe(0); done(); }); } }); }); it('get("data/valid.json") with abort()', done => { var vm = new Vue({ created() { var random = Math.random().toString(36).substr(2); this.$http.get(`data/valid.json?${random}`, { before(req) { setTimeout(() => { expect(typeof req.abort).toBe('function'); req.abort(); }, 0); } }).then(res => { fail('Callback has been called'); }, res => { done(); }); } }); }); it('get("data/notfound.json") using catch()', done => { var vm = new Vue({ created() { this.$http.get('data/notfound.json').catch(res => { expect(this).toBe(vm); expect(res.ok).toBe(false); expect(res.status).toBe(404); done(); }); } }); }); }); ================================================ FILE: test/http.test.js ================================================ var Vue = require('vue'); var VueResource = require('../dist/vue-resource.common.js'); Vue.use(VueResource); describe('Vue.http', function () { it('post("jsfiddle.net/html")', () => { return Vue.http.post('http://jsfiddle.net/echo/html/', {html: 'text'}, {emulateJSON: true}).then(res => { expect(res.ok).toBe(true); expect(res.status).toBe(200); expect(typeof res.body).toBe('string'); expect(res.body).toBe('text'); }); }); it('post("jsfiddle.net/json")', () => { return Vue.http.post('http://jsfiddle.net/echo/json/', {json: JSON.stringify({foo: 'bar'})}, {emulateJSON: true}).then(res => { expect(res.ok).toBe(true); expect(res.status).toBe(200); expect(typeof res.body).toBe('object'); expect(res.body.foo).toBe('bar'); }); }); }); ================================================ FILE: test/index.html ================================================ Vue Resource - Jasmine ================================================ FILE: test/index.js ================================================ import Vue from 'vue'; import VueResource from '../src/index'; Vue.use(VueResource); require('./url'); require('./http'); require('./resource'); require('./promise'); ================================================ FILE: test/karma.conf.js ================================================ module.exports = config => { config.set({ basePath: __dirname, frameworks: ['jasmine'], browsers: ['Chrome', 'Safari', 'Firefox'], files: [ 'index.js', { pattern: 'data/*', included: false }, ], preprocessors: { 'index.js': ['webpack'] }, proxies: { '/data/': '/base/data/' }, webpack: { mode: 'development' }, }); }; ================================================ FILE: test/promise.js ================================================ import Promise from '../src/promise'; describe('Vue.promise ' + (window.Promise !== undefined ? '(native)' : '(polyfill)'), function () { it('then fulfill', function (done) { Promise.resolve(1).then(function (value) { expect(value).toBe(1); done(); }); }); it('then reject', function (done) { Promise.reject(1).then(undefined, function (value) { expect(value).toBe(1); done(); }); }); it('catch', function (done) { Promise.reject(1).catch(function (value) { expect(value).toBe(1); done(); }); }); it('finally fulfill', function (done) { Promise.resolve(1).finally(function (arg) { expect(arg).toBe(undefined); }).then(function (arg) { expect(arg).toBe(1); done(); }); }); it('finally reject', function (done) { Promise.reject(1).finally(function (arg) { expect(arg).toBe(undefined); }).catch(function (arg) { expect(arg).toBe(1); done(); }); }); it('all', function (done) { Promise.all([ Promise.resolve(1), Promise.resolve(2) ]).then(function (values) { expect(values[0]).toBe(1); expect(values[1]).toBe(2); done(); }); }); it('duplicate', function (done) { Promise.all([ Promise.resolve(1).then(function (value) { expect(value).toBe(1); }), Promise.resolve(2).then(function (value) { expect(value).toBe(2); }) ]).then(done); }); it('context', function (done) { var context = {foo: 'bar'}; Promise.resolve().bind(context).then(function () { expect(this).toBe(context); done(); }); }); it('context chain fulfill', function (done) { var context = {foo: 'bar'}; Promise.resolve().bind(context).catch(undefined).finally(function () { expect(this).toBe(context); }).then(function () { expect(this).toBe(context); done(); }); }); it('context chain reject', function (done) { var context = {foo: 'bar'}; Promise.reject().bind(context).catch(function () { expect(this).toBe(context); return Promise.reject(); }).finally(function () { expect(this).toBe(context); }).catch(function () { expect(this).toBe(context); done(); }); }); }); ================================================ FILE: test/resource.js ================================================ import Vue from 'vue'; describe('this.$resource', function () { it('get({file: "valid.json"})', (done) => { var vm = new Vue({ created() { var resource = this.$resource('data{/file}'); resource.get({file: 'valid.json'}).then((res) => { expect(res.ok).toBe(true); expect(res.status).toBe(200); expect(res.data.foo).toBe('bar'); done(); }); } }); }); it('save({file: "valid.json"}, {foo: "bar"})', (done) => { var vm = new Vue({ created() { var resource = this.$resource('data{/file}'); resource.save({file: 'valid.json'}, {foo: 'bar'}).then((res) => { expect(res.ok).toBe(true); expect(res.status).toBe(200); expect(res.data.foo).toBe('bar'); done(); }); } }); }); }); ================================================ FILE: test/url.js ================================================ import Vue from 'vue'; describe('Vue.url', function () { it('data{/id}', function () { expect(Vue.url('data{/id}')).toBe('data'); expect(Vue.url('data{/id}', {id: 1})).toBe('data/1'); }); it('data{/array}', function () { expect(Vue.url('data{?array}')).toBe('data'); expect(Vue.url('data{?array}', {array: [1,2,3]})).toBe('data?array=1,2,3'); }); it('{+path}data', function () { expect(Vue.url('{+path}data')).toBe('data'); expect(Vue.url('{+path}data', {path: 'path1/path2/'})).toBe('path1/path2/data'); }); it('{+base}data', function () { Vue.url.options.params.base = 'base/path/'; expect(Vue.url('{+base}data')).toBe('base/path/data'); }); }); ================================================ FILE: test/webpack.config.js ================================================ module.exports = { mode: 'development', entry: __dirname + '/index.js', output: { path: __dirname + '/', filename: 'specs.js' }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: 'babel-loader' } ] } }; ================================================ FILE: types/index.d.ts ================================================ import * as VueResource from './vue_resource'; export default VueResource ================================================ FILE: types/vue.d.ts ================================================ /** * Extends interfaces in Vue.js */ import Vue from "vue"; import { HttpHeaders, HttpOptions, HttpResponse, $http, $resource } from "./vue_resource"; declare module "vue/types/options" { interface ComponentOptions { http?: (HttpOptions & { headers?: HttpHeaders } & { [key: string]: any }) } } declare module "vue/types/vue" { interface Vue { $http: { (options: HttpOptions): PromiseLike; get: $http; post: $http; put: $http; patch: $http; delete: $http; jsonp: $http; }; $resource: $resource; } } ================================================ FILE: types/vue_resource.ts ================================================ import _Vue from 'vue'; // augment typings of Vue.js import './vue'; export interface HttpHeaders { put?: { [key: string]: string }; post?: { [key: string]: string }; patch?: { [key: string]: string }; delete?: { [key: string]: string }; common?: { [key: string]: string }; custom?: { [key: string]: string }; [key: string]: any; } export interface HttpResponse { data: any; ok: boolean; status: number; statusText: string; headers: Function; text(): string; json(): any; blob(): Blob; } export interface HttpOptions { url?: string; method?: string; body?: any; params?: any; headers?: any; before?(request: any): any; progress?(event: any): any; credentials?: boolean; emulateHTTP?: boolean; emulateJSON?: boolean; } export interface $http { (url: string, data?: any, options?: HttpOptions): PromiseLike; (url: string, options?: HttpOptions): PromiseLike; } export interface HttpInterceptor { request?(request: HttpOptions): HttpOptions; response?(response: HttpResponse): HttpResponse; } export interface Http { options: HttpOptions & { root: string }; headers: HttpHeaders; interceptors: (HttpInterceptor | (() => HttpInterceptor))[]; get: $http; post: $http; put: $http; patch: $http; delete: $http; jsonp: $http; } export interface ResourceActions { get: { method: string }; save: { method: string }; query: { method: string }; update: { method: string }; remove: { method: string }; delete: { method: string }; } export interface ResourceMethod { (params: any, data?: any, success?: Function, error?: Function): PromiseLike; (params: any, success?: Function, error?: Function): PromiseLike; (success?: Function, error?: Function): PromiseLike; } export interface ResourceMethods { get: ResourceMethod; save: ResourceMethod; query: ResourceMethod; update: ResourceMethod; remove: ResourceMethod; delete: ResourceMethod; } export interface $resource { (url: string, params?: any, actions?: any, options?: HttpOptions): ResourceMethods; } export interface Resource extends $resource { actions: ResourceActions; } export declare function install(vue: typeof _Vue): void;