moved from nuxt-community/modules

master
Pooya Parsa 2017-08-13 15:52:10 +04:30
commit 4c9ff4dddf
11 changed files with 6535 additions and 0 deletions

13
.editorconfig Executable file
View File

@ -0,0 +1,13 @@
# editorconfig.org
root = true
[*]
indent_size = 2
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

28
.eslintrc.js Executable file
View File

@ -0,0 +1,28 @@
module.exports = {
root: true,
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module'
},
env: {
browser: true,
node: true
},
extends: 'standard',
// required to lint *.vue files
plugins: [
'html'
],
// add your custom rules here
rules: {
// allow paren-less arrow functions
'arrow-parens': 0,
// allow async-await
'generator-star-spacing': 0,
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
// do not allow console.logs etc...
'no-console': 2
},
globals: {}
}

8
.gitignore vendored Executable file
View File

@ -0,0 +1,8 @@
node_modules
*.iml
.idea
*.log*
.nuxt
.vscode
.DS_STORE
coverage

189
CHANGELOG.md Normal file
View File

@ -0,0 +1,189 @@
# Change Log
All notable changes to this project will be documented in this file.
See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="3.0.1"></a>
## [3.0.1](https://github.com/nuxt/modules/compare/@nuxtjs/axios@3.0.0...@nuxtjs/axios@3.0.1) (2017-07-25)
### Bug Fixes
* **axios:** typo in default headers ([9697559](https://github.com/nuxt/modules/commit/9697559))
<a name="3.0.0"></a>
# [3.0.0](https://github.com/nuxt/modules/compare/@nuxtjs/axios@2.3.0...@nuxtjs/axios@3.0.0) (2017-07-25)
### Code Refactoring
* **axios:** remove $ shortcut mixins ([1ab2bd6](https://github.com/nuxt/modules/commit/1ab2bd6))
### BREAKING CHANGES
* **axios:** You have to explicitly use `this.$axios.[method]` instead of `this.$[method]`
<a name="2.3.0"></a>
# [2.3.0](https://github.com/nuxt/modules/compare/@nuxtjs/axios@2.2.4...@nuxtjs/axios@2.3.0) (2017-07-24)
### Features
* **axios:** optionally disable error handling (#74) ([a195feb](https://github.com/nuxt/modules/commit/a195feb))
* **axios:** redirectError ([4ce1a1c](https://github.com/nuxt/modules/commit/4ce1a1c))
<a name="2.2.4"></a>
## [2.2.4](https://github.com/nuxt/modules/compare/@nuxtjs/axios@2.2.3...@nuxtjs/axios@2.2.4) (2017-07-20)
### Bug Fixes
* **axios:** temporary fix for nuxt/nuxt.js#1127 ([499b639](https://github.com/nuxt/modules/commit/499b639)), closes [nuxt/nuxt.js#1127](https://github.com/nuxt/nuxt.js/issues/1127)
<a name="2.2.3"></a>
## [2.2.3](https://github.com/nuxt/modules/compare/@nuxtjs/axios@2.2.1...@nuxtjs/axios@2.2.3) (2017-07-19)
### Bug Fixes
* **axios:** don't proxy Host header from request (#72, #39) ([61462ca](https://github.com/nuxt/modules/commit/61462ca))
<a name="2.2.2"></a>
## [2.2.2](https://github.com/nuxt/modules/compare/@nuxtjs/axios@2.2.1...@nuxtjs/axios@2.2.2) (2017-07-19)
### Bug Fixes
* **axios:** don't proxy Host header from request (#72, #39) ([61462ca](https://github.com/nuxt/modules/commit/61462ca))
<a name="2.2.1"></a>
## [2.2.1](https://github.com/nuxt/modules/compare/@nuxtjs/axios@2.2.0...@nuxtjs/axios@2.2.1) (2017-07-15)
### Bug Fixes
* **axios:** problems related to #65 ([4e7dd3f](https://github.com/nuxt/modules/commit/4e7dd3f))
<a name="2.0.3"></a>
## [2.0.3](https://github.com/nuxt/modules/compare/@nuxtjs/axios@2.0.2...@nuxtjs/axios@2.0.3) (2017-06-10)
### Bug Fixes
* **axios:** Handle relative baseURL ([19b8453](https://github.com/nuxt/modules/commit/19b8453))
* handle 0.0.0.0 host ([610e0f5](https://github.com/nuxt/modules/commit/610e0f5))
<a name="2.0.2"></a>
## [2.0.2](https://github.com/nuxt/modules/compare/@nuxtjs/axios@2.0.1...@nuxtjs/axios@2.0.2) (2017-06-09)
### Bug Fixes
* **axios:** Node 6.x support ([54deac0](https://github.com/nuxt/modules/commit/54deac0))
<a name="2.0.1"></a>
## [2.0.1](https://github.com/nuxt/modules/compare/@nuxtjs/axios@2.0.0...@nuxtjs/axios@2.0.1) (2017-06-09)
### Bug Fixes
* **axios:** ensure store exists before injecting ([23ad7b7](https://github.com/nuxt/modules/commit/23ad7b7))
<a name="2.0.0"></a>
# [2.0.0](https://github.com/nuxt/modules/compare/@nuxtjs/axios@1.0.2...@nuxtjs/axios@2.0.0) (2017-06-09)
### Bug Fixes
* **axios:** install using Vue.use ([184651b](https://github.com/nuxt/modules/commit/184651b))
* **axios:** req typo ([16f28b1](https://github.com/nuxt/modules/commit/16f28b1))
* **axios:** use relative `API_URL` if same host and port else `API_URL` ([3421d19](https://github.com/nuxt/modules/commit/3421d19))
### Features
* **axios:** AXIOS_CREDENTIALS, AXIOS_SSR_HEADERS ([4dfdc2d](https://github.com/nuxt/modules/commit/4dfdc2d))
* **axios:** don't append optional config into env ([fe189e8](https://github.com/nuxt/modules/commit/fe189e8))
* **axios:** Easier API ([f54a434](https://github.com/nuxt/modules/commit/f54a434))
* **axios:** New API ([0194226](https://github.com/nuxt/modules/commit/0194226))
* **axios:** nuxt friendly errors for SSR ([65bc50f](https://github.com/nuxt/modules/commit/65bc50f))
### BREAKING CHANGES
* **axios:** API_PREFIX is deprecated.
<a name="1.0.2"></a>
## [1.0.2](https://github.com/nuxt/modules/compare/@nuxtjs/axios@1.0.0...@nuxtjs/axios@1.0.2) (2017-05-29)
### Bug Fixes
* **axios:** remove extra function call on computed prop ([cd9da0b](https://github.com/nuxt/modules/commit/cd9da0b))
<a name="1.0.1"></a>
## [1.0.1](https://github.com/nuxt/modules/compare/@nuxtjs/axios@1.0.0...@nuxtjs/axios@1.0.1) (2017-05-26)
### Bug Fixes
* **axios:** remove extra function call on computed prop ([cd9da0b](https://github.com/nuxt/modules/commit/cd9da0b))
<a name="1.0.0"></a>
# 1.0.0 (2017-05-26)
### Features
* initial migration to 1.0.0-alpha1 ([05c1b7a](https://github.com/nuxt/modules/commit/05c1b7a))
### BREAKING CHANGES
* New modules system is backward incompatible with nuxt-helpers style modules
<a name="0.0.1"></a>
## 0.0.1 (2017-05-10)

259
README.md Executable file
View File

@ -0,0 +1,259 @@
# Axios
[![npm](https://img.shields.io/npm/dt/@nuxtjs/axios.svg?style=flat-square)](https://npmjs.com/package/@nuxtjs/axios)
[![npm (scoped with tag)](https://img.shields.io/npm/v/@nuxtjs/axios/latest.svg?style=flat-square)](https://npmjs.com/package/@nuxtjs/axios)
Secure and Easy [axios](https://github.com/mzabriskie/axios) integration with Nuxt.js
## Features
- Automatically set base URL for client & server side
- Exposes `setToken` function to `$axios` so we can easily and globally set authentication tokens.
- Throws *nuxt-friendly* errors and optionally redirect on specific error codes.
- Automatically enables `withCredentials` when requesting to base URL.
- Proxy request headers in SSR.
- Fetch style requests
- [And more](https://github.com/mzabriskie/axios#features)
## Setup
- Add `@nuxtjs/axios` dependency using yarn or npm to your project
- Add `@nuxtjs/axios` to `modules` section of `nuxt.config.js`
```js
{
modules: [
// Simple usage
'@nuxtjs/axios',
// With options
['@nuxtjs/axios', { credentials: false }],
],
// You can optionally use global options instead of inline form
axios: {
credentials: false
}
}
```
## Usage
### Component `asyncData`
```js
async asyncData({ app }) {
const {data} = await app.axios.get('http://icanhazip.com')
return {
ip: data
}
}
```
### Store `nuxtServerInit`
```js
async nuxtServerInit ({ commit }, { app }) {
const ip = await app.axios.$get('http://icanhazip.com')
commit('SET_IP', ip)
}
```
### Store actions
If you need axios instance in store actions, you may have to pass it when dispatching.
```js
// In components
export default {
methods: {
updateIP() {
this.$store.dispatch('getIP', { axios: this.$axios })
}
}
}
// In store
{
actions: {
async getIP ({ commit }, { axios }) {
const ip = await axios.$get('http://icanhazip.com')
commit('SET_IP', ip)
}
}
}
```
## Options
You can pass options using module options or `axios` section in `nuxt.config.js`
### `baseURL`
- Default: `http://[HOST]:[PORT]/api`
Base URL is required for requests in server-side & SSR and prepended to all requests with relative path.
You can also use environment variable `API_URL` which **overrides** `baseURL`.
### `browserBaseURL`
- Default: `/api`
Base URL which is used in client side prepended to all requests with relative path.
You can also use environment variable `API_URL_BROWSER` which **overrides** `browserBaseURL`.
- If `browserBaseURL` is not provided it defaults to `baseURL` value.
- If hostname & port of `browserbaseURL` are equal to nuxt server, it defaults to relative part of `baseURL`.
So if your nuxt application is being accessed under a different domain, requests go to same origin and prevents Cross-Origin problems.
### `credentials`
- Default: `true`
Adds an interceptor to automatically set `withCredentials` config of axios when requesting to `baseUrl`
which allows passing authentication headers to backend.
### `debug`
- Default: `false`
Adds interceptors to log all responses and requests
### `proxyHeaders`
- Default: `true`
In SSR context, sets client request header as axios default request headers.
This is useful for making requests which need cookie based auth on server side.
Also helps making consistent requests in both SSR and Client Side code.
### `redirectError`
- Default: `{}`
This option is a map from specific error codes to page which they should be redirect.
For example if you want redirecting all `401` errors to `/login` use:
```js
{
axios: {
redirectError: {
401: '/login'
}
}
}
```
### `requestInterceptor`
- Default: `null`
Function for manipulating axios requests. Useful for setting custom headers,
for example based on the store state. The second argument is the nuxt context.
```js
requestInterceptor: (config, { store }) => {
if (store.state.token) {
config.headers.common['Authorization'] = store.state.token
}
return config
}
```
## Helpers
### Fetch Style requests
Axios plugin also supports fetch style requests with `$` prefixed methods:
```js
// Normal usage with axios
let data = (await axios.get('...')).data
// Fetch Style
let data = await axios.$get('...')
```
### `setHeader(name, value, scopes='common')`
Axios instance has a helper to easily set any header.
Parameters:
- **name**: Name of the header
- **value**: Value of the header
- **scopes**: Send only on specific type of requests. Defaults
- Type: *Array* or *String*
- Defaults to `common` meaning all types of requests
- Can be `get`, `post`, `delete`, ...
```js
// Adds header: `Authorization: 123` to all requests
this.$axios.setHeader('Authorization', '123')
// Overrides `Authorization` header with new value
this.$axios.setHeader('Authorization', '456')
// Adds header: `Content-Type: application/x-www-form-urlencoded` to only post requests
this.$axios.setHeader('Content-Type', 'application/x-www-form-urlencoded', ['post'])
// Removes default Content-Type header from `post` scope
this.$axios.setHeader('Content-Type', false, ['post'])
```
### `setToken(token, type, scopes='common')`
Axios instance has an additional helper to easily set global authentication header.
Parameters:
- **token**: Authorization token
- **type**: Authorization token prefix(Usually `Bearer`).
- **scopes**: Send only on specific type of requests. Defaults
- Type: *Array* or *String*
- Defaults to `common` meaning all types of requests
- Can be `get`, `post`, `delete`, ...
```js
// Adds header: `Authorization: 123` to all requests
this.$axios.setToken('123')
// Overrides `Authorization` header with new value
this.$axios.setToken('456')
// Adds header: `Authorization: Bearer 123` to all requests
this.$axios.setToken('123', 'Bearer')
// Adds header: `Authorization: Bearer 123` to only post and delete requests
this.$axios.setToken('123', 'Bearer', ['post', 'delete'])
// Removes default Authorization header from `common` scope (all requests)
this.$axios.setToken(false)
```
## Dynamic API Backend
Please notice that, `API_URL` is saved into bundle on build, CANNOT be changed
on runtime! You may use [proxy](../proxy) module for dynamically route api requests to different backend on test/staging/production.
**Example: (`nuxt.config.js`)**
```js
{
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
proxy: [
['/api', { target: 'http://www.mocky.io', pathRewrite: { '^/api': '/v2' } }]
]
}
```
Start Nuxt
```
[AXIOS] Base URL: http://localhost:3000/api | Browser: /api
[HPM] Proxy created: /api -> http://www.mocky.io
[HPM] Proxy rewrite rule created: "^/api" ~> "/v2"
```
Now you can make requests to backend: (Works fine in both SSR and Browser)
```js
async asyncData({app}) {
// Magically makes request to http://www.mocky.io/v2/59388bb4120000dc00a672e2
const nuxt = await app.axios.$get('59388bb4120000dc00a672e2')
return {
nuxt // -> { nuxt: 'Works!' }
}
}
```
Details
- `'@nuxtjs/axios'`
- By default axios plugin sets base url to `http://[host]:[port]/api` which is `http://localhost:3000/api`
- `'/api': 'http://www.mocky.io/v2'`
- This line creates a server middleware to pass requests from `/api` to `http://www.mocky.io/v2`
- We used `pathRewrite` to remove `/api` from starting of requests and change it to `/v2`
- For more information and advanced usage please refer to [proxy](../proxy) docs.

33
package.json Executable file
View File

@ -0,0 +1,33 @@
{
"name": "@nuxtjs/axios",
"version": "3.1.0",
"license": "MIT",
"main": "src/index.js",
"repository": "https://github.com/nuxt-community/axios-module",
"publishConfig": {
"access": "public"
},
"scripts": {
"test": "jest"
},
"jest": {
"testEnvironment": "node",
"coverageDirectory": "./coverage/",
"collectCoverage": true
},
"dependencies": {
"axios": "^0.16.2",
"chalk": "^2.1.0",
"nuxt": "^1.0.0-rc4",
"whatwg-url": "^6.1.0"
},
"devDependencies": {
"eslint": "^4.4.1",
"eslint-config-standard": "^10.2.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.1.1",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.1",
"jest": "^20.0.4"
}
}

63
src/index.js Executable file
View File

@ -0,0 +1,63 @@
const chalk = require('chalk')
const path = require('path')
const { hostname } = require('os')
const { URL } = require('whatwg-url')
const port = process.env.PORT || process.env.npm_package_config_nuxt_port || 3000
let host = process.env.HOST || process.env.npm_package_config_nuxt_host || 'localhost'
if (host === '0.0.0.0') {
host = hostname()
}
module.exports = function nuxtAxios (moduleOptions) {
// Apply defaults
const defaults = {
baseURL: `http://${host}:${port}/api`,
browserBaseURL: null,
credentials: true,
proxyHeaders: true,
debug: false,
redirectError: {}
}
const options = Object.assign({}, defaults, this.options.axios, moduleOptions)
// Override env
if (process.env.API_URL) {
options.baseURL = process.env.API_URL
}
if (process.env.API_URL_BROWSER) {
options.browserBaseURL = process.env.API_URL_BROWSER
}
const isSchemeLessBaseURL = options.baseURL.substr(0, 2) === '//'
options.baseURL = new URL(options.baseURL, `http://${host}:${port}`)
if (!options.browserBaseURL) {
const sameHost = options.baseURL.host === `${host}:${port}`
options.browserBaseURL = sameHost ? options.baseURL.pathname : isSchemeLessBaseURL ? options.baseURL.toString().substr(5) : options.baseURL // 5 == 'http:'.length
}
// Register plugin
addPlugin.call(this, {
src: path.resolve(__dirname, 'plugin.js'),
fileName: 'axios.js',
options
})
/* eslint-disable no-console */
console.log(`[AXIOS] Base URL: ${chalk.green(options.baseURL)} , Browser: ${chalk.green(options.browserBaseURL)}`)
}
// Temporary fix for nuxt/nuxt.js#1127
function addPlugin (template) {
const { dst } = this.addTemplate(template)
// Add to nuxt plugins
this.options.plugins.unshift({
src: path.join(this.options.buildDir, dst),
ssr: template.ssr
})
}
module.exports.meta = require('../package.json')

180
src/plugin.js Executable file
View File

@ -0,0 +1,180 @@
import Axios from 'axios'
import Vue from 'vue'
const axiosPlugin = {
install() {
if(Vue.__nuxt_axios_installed__) {
return
}
Vue.__nuxt_axios_installed__ = true
if (!Vue.prototype.hasOwnProperty('$axios')) {
Object.defineProperty(Vue.prototype, '$axios', {
get () {
return this.$root.$options.$axios
}
})
}
}
}
Vue.use(axiosPlugin)
// We cannot extend Axios.prototype
const axiosExtraProto = {}
// Sets a common header
axiosExtraProto.setHeader = function setHeader (name, value, scopes = 'common') {
if(!Array.isArray(scopes)) {
scopes = [scopes]
}
scopes.forEach(scope => {
if (!value) {
delete this.defaults.headers[scope][name];
return
}
this.defaults.headers[scope][name] = value
})
}
// Set requests token
axiosExtraProto.setToken = function setToken (token, type, scopes = 'common') {
const value = !token ? null : (type ? type + ' ' : '') + token
this.setHeader('Authorization', value, scopes)
}
// Request helpers
const reqMethods = [
'request', 'delete', 'get', 'head', 'options', // url, config
'post', 'put', 'patch' // url, data, config
]
reqMethods.forEach(method => {
axiosExtraProto['$' + method] = function () {
return this[method].apply(this, arguments).then(res => res.data)
}
})
// Setup all helpers to axios instance (Axios.prototype cannot be modified)
function setupHelpers( axios ) {
for (let key in axiosExtraProto) {
axios[key] = axiosExtraProto[key].bind(axios)
}
}
const redirectError = <%= serialize(options.redirectError) %>
// Set appreciate `statusCode` and `message` to error instance
function errorHandler(error) {
if (error.response) {
// Error from backend (non 2xx status code)
// ...Auto redirect on special status codes
if (redirectError[error.response.status]) {
this.redirect(redirectError[error.response.status])
}
error.statusCode = error.statusCode || parseInt(error.response.status) || 500
error.message = error.message || error.response.statusText || (error.statusCode + ' (Internal Server Error)')
} else if (error.request) {
// Error while making request
error.statusCode = error.statusCode || 500
error.message = error.message || 'request error'
} else {
// Something happened in setting up the request that triggered an Error
error.statusCode = 500
error.message = error.message || 'axios error'
}
return Promise.reject(error)
}
<% if(options.debug) { %>
function debug(level, messages) {
if (!(console[level] instanceof Function)) {
level = 'info'
messages = arguments
} else {
level = arguments[0]
messages = Array.prototype.slice.call(arguments, 1)
}
if (!messages.length) {
console[level].call(null, '[@nuxtjs/axios] <empty debug message>')
} else {
for (var i = 0; i < messages.length; i++) {
console[level].call(null, messages[i])
}
}
}
<% } %>
// Setup BaseURL
const baseURL = process.browser
? (process.env.API_URL_BROWSER || '<%= options.browserBaseURL %>')
: (process.env.API_URL || '<%= options.baseURL %>')
export default (ctx) => {
const { app, store, req } = ctx
<% if(options.proxyHeaders) { %>
// Default headers
const defaultHeaders = (req && req.headers) ? Object.assign({}, req.headers) : {}
delete defaultHeaders.host
<% } %>
// Create new axios instance
const axios = Axios.create({
baseURL,
<% if(options.proxyHeaders) { %>headers: defaultHeaders,<% } %>
})
<% if(options.credentials) { %>
// Send credentials only to relative and API Backend requests
axios.interceptors.request.use(config => {
if (config.withCredentials === undefined) {
if (!/^https?:\/\//i.test(config.url) || config.url.indexOf(baseURL) === 0) {
config.withCredentials = true
}
}
return config
});
<% } %>
<% if(options.debug) { %>
// Debug
axios.interceptors.request.use(config => {
debug('[@nuxtjs/axios] Request:', config)
return config
}, error => {
debug('error', '[@nuxtjs/axios] Error:', error)
return Promise.reject(error)
});
axios.interceptors.response.use(config => {
debug('[@nuxtjs/axios] Response:', config)
return config
}, error => {
debug('error', '[@nuxtjs/axios] Error:', error)
return Promise.reject(error)
});
<% } %>
<% if (options.requestInterceptor) { %>
// Custom request interceptor
const reqInter = <%= serialize(options.requestInterceptor).replace('requestInterceptor(', 'function(').replace('function function', 'function') %>
axios.interceptors.request.use(
(config) => reqInter(config, ctx)
)
<% } %>
// Error handler
axios.interceptors.response.use(undefined, errorHandler.bind(ctx));
// Make accessible using context
app.axios = app.$axios = axios
ctx.axios = ctx.$axios = axios
if (store) {
store.axios = store.$axios = axios
}
// Setup axios helpers
setupHelpers(axios)
}

19
test/axios.test.js Normal file
View File

@ -0,0 +1,19 @@
const { Nuxt, Builder } = require('nuxt')
process.env.NODE_ENV = 'production'
describe('axios module', () => {
let nuxt
beforeAll(async () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000
nuxt = new Nuxt({ srcDir: __dirname + '/fixture', dev: false })
let builder = new Builder(nuxt)
builder.webpackStats = false
await builder.build()
})
test('test', () => {
expect(nuxt.options.dev).toBe(false)
})
})

View File

@ -0,0 +1,11 @@
<template>
<div>
Hello world!
</div>
</template>
<script>
export default {
}
</script>

5732
yarn.lock Normal file

File diff suppressed because it is too large Load Diff