Skip to content

Commit

Permalink
Feature/auto export (#4)
Browse files Browse the repository at this point in the history
* perf: add test for test/

* feat: close #3, add useGlobalMiddleware option
  • Loading branch information
BuptStEve authored Oct 17, 2018
1 parent 68acf66 commit 1e51d4a
Show file tree
Hide file tree
Showing 16 changed files with 124 additions and 53 deletions.
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,6 @@ export default {

```js
import TuaApi from 'tua-api' // 小程序用 dist/mp
import fakeGetConfig from './fake-get'
import fakePostConfig from './fake-post'

// 初始化
const tuaApi = new TuaApi({ ... })
Expand All @@ -195,15 +193,14 @@ tuaApi
// 链式调用
.use(...)

// 生成请求函数对象
const fakeGet = tuaApi.getApi(fakeGetConfig)
const fakePost = tuaApi.getApi(fakePostConfig)
export const fakeGet = tuaApi.getApi(require('./fake-get').default)
export const fakePost = tuaApi.getApi(require('./fake-post').default)
```

export {
fakeGet,
fakePost,
}
小程序端建议使用 [@tua-mp/cli](https://tuateam.github.io/tua-mp/tua-mp-cli/) 一键生成 api。

```bash
$ tuamp add api <api-name>
```

### 配置的构成
Expand Down
2 changes: 1 addition & 1 deletion docs/config/default.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ new TuaApi({
例如 `https://example.com/api/`

## reqType 请求类型
即用哪个库发起请求目前支持:jsonp、axios,不填默认使用 axios。
即在 web 端使用哪个库发起请求目前支持:jsonp、axios,不填默认使用 axios。(小程序端没得选...)

## middleware 中间件函数数组
【所有】请求都会调用的中间件函数数组!适合添加一些通用逻辑,例如接口上报。
Expand Down
5 changes: 5 additions & 0 deletions docs/config/detail.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ const afterFn = ([x]) => x
* 可选值: wx.hideNavigationBarLoading
* 或者调用你自己定义的隐藏 loading 方法...

## useGlobalMiddleware 使用全局中间件
是否使用全局中间件,默认为 true。

适用于某些接口正好不需要调用在 `tua-api` 初始化时定义的全局中间件的情况。

## pathList 各个接口自身配置数组
这个数组中填写的是接口最后的地址。

Expand Down
40 changes: 40 additions & 0 deletions docs/config/own.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,43 @@
# 自身配置
自身配置指的是填写在 `pathList` 中的配置。这部分的配置优先级最高。

以下接口以导出为 `exampleApi` 为例。

## path 接口地址
```js
export default {
pathList: [
{
path: 'foo-bar',
},
],
}
```

即接口地址的最后部分。默认这样调用

```js
exampleApi['foo-bar']({ ... })
```

## name 接口名称(可省略)
```js
export default {
pathList: [
{
path: 'foo-bar',
name: 'fooBar',
},
],
}
```

有时接口地址较长,可以添加 `name` 配置重命名接口,这样就可以这样调用

```js
exampleApi.fooBar({ ... })
```

## params 接口参数

```js
Expand Down Expand Up @@ -28,3 +65,6 @@ export default {

## commonParams 覆盖公共参数
有时某个接口正好不需要上一级中 `commonParams` 的参数。那么可以传递 `null` 覆盖上一级中的 `commonParams`

## 其他参数
其他参数参阅上一节 [详细配置](./detail.md)
18 changes: 9 additions & 9 deletions docs/quick-start/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ export default {

```js
import TuaApi from 'tua-api' // 小程序用 dist/mp
import fakeGetConfig from './fake-get'
import fakePostConfig from './fake-post'

// 初始化
const tuaApi = new TuaApi({ ... })
Expand All @@ -125,14 +123,16 @@ tuaApi
// 链式调用
.use(...)

// 生成请求函数对象
const fakeGet = tuaApi.getApi(fakeGetConfig)
const fakePost = tuaApi.getApi(fakePostConfig)
export const fakeGet = tuaApi.getApi(require('./fake-get').default)
export const fakePost = tuaApi.getApi(require('./fake-post').default)
```

export {
fakeGet,
fakePost,
}
::: tip
小程序端建议使用 [@tua-mp/cli](https://tuateam.github.io/tua-mp/tua-mp-cli/) 一键生成 api。

```bash
$ tuamp add api <api-name>
```
:::

[配置的详细说明点这里](../config/)
2 changes: 1 addition & 1 deletion docs/quick-start/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default {
## 中间件执行顺序
koa 中间件的执行顺序和 redux 的正好相反,例如以上写法会以以下顺序执行:

`请求参数 -> 1 -> 2 -> 3 -> 响应数据 -> 3 -> 2 -> 1`
`请求参数 -> fn1 -> fn2 -> fn3 -> 响应数据 -> fn3 -> fn2 -> fn1`

## 中间件写法

Expand Down
5 changes: 5 additions & 0 deletions examples/apis-mp/fake-wx.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export default {
// 所有请求都需要携带的参数,例如小程序中的所有接口都要携带以下参数 `from=miniprogram`
commonParams: { from: 'miniprogram' },

// 是否使用在 index.js 中定义的全局中间件,默认为 true
useGlobalMiddleware: false,

// 所有请求发起时是否自动展示 loading(默认为 true)
// isShowLoading: true,

Expand All @@ -27,12 +30,14 @@ export default {
beforeFn: () => Promise.resolve({
header: { cookie: '123' },
}),
useGlobalMiddleware: true,
},
/**
* array-data
*/
{
path: 'array-data',
name: 'arrayData',
type: 'get',
params: ['param1', 'param2'],
},
Expand Down
7 changes: 1 addition & 6 deletions examples/apis-mp/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import TuaApi from '../../src/TuaApiMp'
import fakeWxConfig from './fake-wx'

const tuaApi = new TuaApi()

Expand All @@ -14,8 +13,4 @@ tuaApi.use(async (ctx, next) => {
// console.log('after: ', ctx)
})

const fakeWx = tuaApi.getApi(fakeWxConfig)

export {
fakeWx,
}
export const fakeWx = tuaApi.getApi(require('./fake-wx').default)
3 changes: 3 additions & 0 deletions examples/apis-web/fake-get.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export default {
// 透传 `axios` 需要配置的参数。例如需要传递超时时间时可添加:
axiosOptions: { timeout: 10 * 1000 },

// 是否使用在 index.js 中定义的全局中间件,默认为 true
useGlobalMiddleware: false,

// 中间件函数数组
middleware: [
// (ctx, next) => {
Expand Down
25 changes: 9 additions & 16 deletions examples/apis-web/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import TuaApi from '../../src/TuaApiWeb'
import fakeGetConfig from './fake-get'
import fakePostConfig from './fake-post'

const tuaApi = new TuaApi({
host: 'http://example-base.com/',
Expand All @@ -9,20 +7,15 @@ const tuaApi = new TuaApi({
})

// 使用中间件
// tuaApi.use(async (ctx, next) => {
// // 请求发起前
// console.log('before: ', ctx)
tuaApi.use(async (ctx, next) => {
// 请求发起前
// console.log('before: ', ctx)

// await next()
await next()

// // 响应返回后
// console.log('after: ', ctx)
// })

const fakeGet = tuaApi.getApi(fakeGetConfig)
const fakePost = tuaApi.getApi(fakePostConfig)
// 响应返回后
// console.log('after: ', ctx)
})

export {
fakeGet,
fakePost,
}
export const fakeGet = tuaApi.getApi(require('./fake-get').default)
export const fakePost = tuaApi.getApi(require('./fake-post').default)
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tua-api",
"version": "0.1.1",
"version": "0.2.0",
"main": "dist/umd.js",
"module": "dist/es.js",
"jsnext:main": "dist/es.js",
Expand All @@ -11,7 +11,7 @@
"cov": "open coverage/lcov-report/index.html",
"tdd": "cross-env NODE_ENV=test jest --watch",
"test": "cross-env NODE_ENV=test jest && codecov",
"lint": "eslint --fix src/**/*.js",
"lint": "eslint --fix src/ test/",
"deploy": "yarn docs:build && gh-pages -m \"[ci skip]\" -d docs/.vuepress/dist",
"prebuild": "rimraf dist/* & npm run test",
"build": "npm run build:wx & npm run build:web",
Expand All @@ -27,7 +27,7 @@
}
},
"lint-staged": {
"src/**/*.js": [
"{src,test}/**/*.js": [
"eslint --fix",
"git add"
]
Expand Down
13 changes: 10 additions & 3 deletions src/TuaApiCore.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,20 @@ class TuaApiCore {
/**
* 组合生成中间件函数
* @param {Function[]} middleware
* @param {Boolean} useGlobalMiddleware 是否使用全局中间件
*/
_getMiddlewareFn (middleware) {
_getMiddlewareFn (middleware, useGlobalMiddleware) {
const middlewareFns = useGlobalMiddleware
? this.middleware.concat(middleware)
: middleware

return koaCompose([
// 记录时间
recordReqTimeMiddleware,
// 格式化生成请求参数
formatReqParamsMiddleware,
// 业务侧中间件函数数组
...this.middleware.concat(middleware),
...middlewareFns,
// 更新请求参数
updateFullUrlMiddleware,
// 统一转换响应数据为对象
Expand Down Expand Up @@ -125,6 +130,7 @@ class TuaApiCore {
* @param {Function} afterFn 在请求完成后执行的钩子函数(将被废弃)
* @param {Function} beforeFn 在请求发起前执行的钩子函数(将被废弃)
* @param {Function[]} middleware 中间件函数数组
* @param {Boolean} useGlobalMiddleware 是否使用全局中间件
* @return {Object} 以 apiName 为 key,请求函数为值的对象
*/
_getOneReqMap ({
Expand All @@ -136,6 +142,7 @@ class TuaApiCore {
afterFn = ([x]) => x,
beforeFn = Promise.resolve.bind(Promise),
middleware = [],
useGlobalMiddleware = true,
...rest
}) {
// 优先使用 name
Expand Down Expand Up @@ -171,7 +178,7 @@ class TuaApiCore {
}

// 中间件函数
const middlewareFn = this._getMiddlewareFn(middleware)
const middlewareFn = this._getMiddlewareFn(middleware, useGlobalMiddleware)

// 执行完 beforeFn 后执行的函数
const beforeFnCallback = (rArgs = {}) => {
Expand Down
3 changes: 3 additions & 0 deletions test/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
env: { jest: true }
}
29 changes: 26 additions & 3 deletions test/__tests__/core.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
import fakeGet from '../../examples/apis-mp/fake-wx'
import TuaApiMp from '../../src/TuaApiMp'
import TuaApiCore from '../../src/TuaApiCore'

const tuaApi = new TuaApiCore

describe('error handling', () => {
const tuaApiCore = new TuaApiCore()

test('non-function middleware', () => {
expect(() => tuaApi.use('')).toThrow(TypeError('middleware must be a function!'))
expect(() => tuaApiCore.use('')).toThrow(TypeError('middleware must be a function!'))
})

test('unknown reqType', () => {
expect(() => new TuaApiCore({ reqType: '' })).toThrow(TypeError(`invalid reqType`))
})
})

describe('middleware', () => {
const tuaApi = new TuaApiMp()
const globalMiddlewareFn = jest.fn(async (ctx, next) => {
await next()
})
tuaApi.use(globalMiddlewareFn)

const fakeGetApi = tuaApi.getApi(fakeGet)

beforeEach(() => {
wx.__TEST_DATA__ = { testData: {} }
})

test('useGlobalMiddleware', async () => {
await fakeGetApi.arrayData()
expect(globalMiddlewareFn).toBeCalledTimes(0)
await fakeGetApi.fail()
expect(globalMiddlewareFn).toBeCalledTimes(1)
})
})
2 changes: 1 addition & 1 deletion test/__tests__/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ test('checkArrayParams', () => {

test('getDefaultParamObj', () => {
expect(getDefaultParamObj({
commonParams: { a: '1' }
commonParams: { a: '1' },
})).toEqual({ a: '1' })

expect(getDefaultParamObj({
Expand Down
2 changes: 1 addition & 1 deletion test/__tests__/wx.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { fakeWx } from '../../examples/apis-mp/'

const reqF = fakeWx['fail']
const reqAD = fakeWx['array-data']
const reqAD = fakeWx.arrayData
const reqOD = fakeWx['object-data']
const reqNB = fakeWx['no-beforeFn']
const reqHL = fakeWx['hide-loading']
Expand Down

0 comments on commit 1e51d4a

Please sign in to comment.