diff --git a/docs/config/common.md b/docs/config/common.md index a5ae909..f5fdfd9 100644 --- a/docs/config/common.md +++ b/docs/config/common.md @@ -91,6 +91,16 @@ export default { } ``` +::: tip + 后,支持函数模式 + +```js +export default { + commonParams: (params) => ({ t: Date.now(), foo: params.foo }), +} +``` +::: + ## axiosOptions 透传参数配置 由于 tua-api 是依赖于 `axios` 或是 `fetch-jsop` 来发送请求的。所以势必要提供参数透传的功能。 diff --git a/docs/config/self.md b/docs/config/self.md index a2ee314..a155c80 100644 --- a/docs/config/self.md +++ b/docs/config/self.md @@ -63,6 +63,24 @@ export default { } ``` +::: tip + 后,支持函数模式 + +```js +export default { + pathList: [ + { + ... + params: (params) => ({ + t: Date.now(), + foo: params.foo, + }), + }, + ], +} +``` +::: + ## commonParams 覆盖公共参数 有时某个接口正好不需要上一级中 `commonParams` 的参数。那么可以传递 `null` 覆盖上一级中的 `commonParams`。 diff --git a/examples/apis-web/fake-fn.js b/examples/apis-web/fake-fn.js new file mode 100644 index 0000000..9f41b6e --- /dev/null +++ b/examples/apis-web/fake-fn.js @@ -0,0 +1,32 @@ +export default { + // 该参数表示请求的公用服务器地址。 + baseUrl: 'http://example-base.com/', + + // 请求的中间路径,建议与文件同名,以便后期维护。 + prefix: 'fake-fn', + + // 所有请求都需要携带的参数 + commonParams: (args) => ({ + ...args, + c: Math.random(), + }), + + reqType: 'axios', + + // 接口地址数组 + pathList: [ + /** + * fn-params + */ + { + name: 'fp', + path: 'fn-params', + method: 'post', + params: ({ param1, param2 }) => ({ + t: Math.random(), + p1: param1, + p2: param2, + }), + }, + ], +} diff --git a/examples/apis-web/fake-post.js b/examples/apis-web/fake-post.js index 54668b9..bded75d 100644 --- a/examples/apis-web/fake-post.js +++ b/examples/apis-web/fake-post.js @@ -19,10 +19,7 @@ export default { /** * empty-array-params */ - { - name: 'eap', - path: 'empty-array-params', - }, + { name: 'eap', path: 'empty-array-params' }, /** * array-params */ @@ -84,10 +81,7 @@ export default { /** * application/json */ - { - name: 'pj', - path: 'post-json', - }, + { name: 'pj', path: 'post-json' }, /** * raw-data */ diff --git a/examples/apis-web/index.d.ts b/examples/apis-web/index.d.ts index 05b830f..321ea7c 100644 --- a/examples/apis-web/index.d.ts +++ b/examples/apis-web/index.d.ts @@ -58,3 +58,12 @@ export const fakePostApi: { ): Promise } } + +export const fakeFnApi: { + 'fp': ReqFn & { + ( + params: { t?: any }, + options?: RuntimeOptions + ): Promise + } +} diff --git a/examples/apis-web/index.js b/examples/apis-web/index.js index 97b55dd..b1d0714 100644 --- a/examples/apis-web/index.js +++ b/examples/apis-web/index.js @@ -17,5 +17,6 @@ tuaApi.use(async (ctx, next) => { // console.log('after: ', ctx) }) +export const fakeFnApi = tuaApi.getApi(require('./fake-fn').default) export const fakeGetApi = tuaApi.getApi(require('./fake-get').default) export const fakePostApi = tuaApi.getApi(require('./fake-post').default) diff --git a/package.json b/package.json index 11baace..636583a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tua-api", - "version": "1.6.1", + "version": "1.7.0", "description": "🏗 A common tool helps converting configs to api functions", "main": "dist/TuaApi.cjs.js", "module": "dist/TuaApi.esm.js", diff --git a/src/index.d.ts b/src/index.d.ts index 587359b..3612120 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -12,7 +12,7 @@ export type Mock = AnyFunction | any export type ApiConfig = WxApiConfig | WebApiConfig -export type ParamsConfig = string[] | ParamsObject +export type ParamsConfig = string[] | ParamsObject | ((args?: object) => object) export type Middleware = (ctx: T, next: () => Promise) => Promise @@ -96,7 +96,7 @@ export interface BaseApiConfig { beforeFn?: () => Promise middleware?: Middleware[] customFetch?: AnyPromiseFunction - commonParams?: object + commonParams?: object | ((args?: object) => object), axiosOptions?: AxiosOptions jsonpOptions?: JsonpOptions useGlobalMiddleware?: boolean diff --git a/src/index.js b/src/index.js index 396c0ed..c34d86e 100644 --- a/src/index.js +++ b/src/index.js @@ -6,6 +6,7 @@ import { map, pipe, isWx, + runFn, logger, mergeAll, apiConfigToReqFnParams, @@ -145,9 +146,7 @@ class TuaApi { // mock data if (mock) { - const resData = typeof mock === 'function' - ? mock(data) - : { ...mock } + const resData = { ...runFn(mock, data) } return Promise.resolve({ data: resData }) } @@ -255,7 +254,7 @@ class TuaApi { mock, name, path, - params = {}, + params: rawParams = {}, prefix, afterFn = ([x]) => x, beforeFn = Promise.resolve.bind(Promise), @@ -308,6 +307,8 @@ class TuaApi { const apiFn = (args, runtimeOptions = {}) => { args = args || {} + const params = runFn(rawParams, args) + // 最终的运行时配置,runtimeOptions 有最高优先级 const runtimeParams = { type, @@ -361,7 +362,7 @@ class TuaApi { apiFn.key = `${prefix}/${apiName}` apiFn.mock = mock - apiFn.params = params + apiFn.params = rawParams return { [apiName]: apiFn } } diff --git a/src/middlewareFns.js b/src/middlewareFns.js index 31f7095..2e51c93 100644 --- a/src/middlewareFns.js +++ b/src/middlewareFns.js @@ -1,5 +1,6 @@ import { ERROR_STRINGS } from './constants' import { + runFn, isFormData, combineUrls, checkArrayParams, @@ -59,7 +60,7 @@ const formatReqParamsMiddleware = (ctx, next) => { const { args, params, - commonParams, + commonParams: rawCommonParams, } = ctx.req if (typeof args !== 'object') { @@ -74,10 +75,11 @@ const formatReqParamsMiddleware = (ctx, next) => { checkArrayParams(ctx.req) + const commonParams = runFn(rawCommonParams, args) // 根据配置生成请求的参数 ctx.req.reqParams = Array.isArray(params) ? { ...commonParams, ...args } - : { ...getDefaultParamObj(ctx.req), ...args } + : { ...getDefaultParamObj({ ...ctx.req, commonParams }), ...args } return next() } diff --git a/src/utils/judge.js b/src/utils/judge.js index 0274f58..5a3ae22 100644 --- a/src/utils/judge.js +++ b/src/utils/judge.js @@ -8,4 +8,10 @@ export const isFormData = (val) => ( (val instanceof FormData) ) +export const runFn = (fn, ...params) => { + if (typeof fn === 'function') return fn(...params) + + return fn +} + export const isUndefined = val => typeof val === 'undefined' diff --git a/test/__tests__/axios.test.js b/test/__tests__/axios.test.js index 0b4e909..dae56ce 100644 --- a/test/__tests__/axios.test.js +++ b/test/__tests__/axios.test.js @@ -151,7 +151,6 @@ describe('fake post requests', () => { }) test('form-data', async () => { - mock.resetHistory() mock.onPost(reqOHUrl).reply(200, {}) const formData = new FormData() formData.append('a', 'a') @@ -169,7 +168,6 @@ describe('fake post requests', () => { }) test('custom-transformRequest', async () => { - mock.resetHistory() mock.onPost(reqCTUrl).reply(200, {}) await fakePostApi.ct() @@ -180,7 +178,6 @@ describe('fake post requests', () => { }) test('post-json', async () => { - mock.resetHistory() mock.onPost(reqPjUrl).reply(200, {}) await fakePostApi.pj() diff --git a/test/__tests__/fn.test.js b/test/__tests__/fn.test.js new file mode 100644 index 0000000..daafbf1 --- /dev/null +++ b/test/__tests__/fn.test.js @@ -0,0 +1,31 @@ +import axios from 'axios' +import MockAdapter from 'axios-mock-adapter' + +import fakeFnConfig from '@examples/apis-web/fake-fn' +import { fakeFnApi } from '@examples/apis-web/' + +const mock = new MockAdapter(axios) + +const params = { param1: 'steve', param2: 'young' } +const reqFPUrl = 'http://example-base.com/fake-fn/fn-params' + +describe('function params', () => { + beforeEach(() => { + // @ts-ignore + mock.resetHistory() + }) + + test('should support function type params', async () => { + Math.random = jest.fn(() => 'foo') + mock.onPost(reqFPUrl).reply(200, {}) + await fakeFnApi.fp(params) + + const { data } = mock.history.post[0] + expect(data).toEqual(JSON.stringify({ + ...fakeFnConfig.commonParams(params), + t: 'foo', + p1: params.param1, + p2: params.param2, + })) + }); +});