chore: 修改部分内容

pull/49/head
zjx0905 2023-05-04 10:39:52 +08:00
parent 52037b8794
commit cea4be518c
15 changed files with 1475 additions and 1477 deletions

View File

@ -1,4 +1,4 @@
const { execSync } = require('child_process');
const { execSync } = require('child_process')
const metas = [
{ type: 'feat', section: '✨ Features | 新功能' },
@ -12,7 +12,7 @@ const metas = [
{ type: 'chore', section: '📦 Chores | 其他更新' },
{ type: 'style', section: '💄 Styles | 风格', hidden: true },
{ type: 'refactor', section: '♻ Code Refactoring | 代码重构' },
];
]
/** @type {import('cz-git').UserConfig} */
module.exports = {
@ -41,10 +41,12 @@ module.exports = {
'name',
)} <${readGitUser('email')}>`,
},
};
}
function readGitUser(key) {
return execSync(`git config user.${key}`)
return execSync(`git config user.${key}`, {
stdio: 'pipe',
})
.toString()
.replace(/(\r\n\t|\n|\r\t)/g, '');
.replace(/(\r\n\t|\n|\r\t)/g, '')
}

View File

@ -1,10 +1,11 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"useTabs": true,
"semi": false,
"singleQuote": true,
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "always"
"arrowParens": "always",
"jsxSingleQuote": true
}

View File

@ -50,30 +50,7 @@ import axios, {
createAdapter,
} from 'axios-miniprogram';
const {
// 取消令牌
CancelToken,
// 判断取消请求错误
isCancel,
// 原始 Axios 类
Axios,
// 判断请求响应错误
isAxiosError,
// 创建平台适配器
createAdapter,
// 创建实例
create,
// 获取系列化后的 URL
getUri,
} = axios;
axios('test');
axios('/test');
```
```ts [CommonJS]
@ -98,28 +75,7 @@ const {
createAdapter,
} = require('axios-miniprogram');
const {
// 取消令牌
CancelToken,
// 判断取消请求错误
isCancel,
// 原始 Axios 类
Axios,
// 判断请求响应错误
isAxiosError,
// 创建平台适配器
createAdapter,
// 创建实例
create,
// 获取系列化后的 URL
getUri,
} = axios;
axios('/test');
```
::::

View File

@ -1,7 +0,0 @@
{
"name": "example",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
}
}

View File

@ -42,12 +42,12 @@
"test:watch": "vitest",
"test:cov": "vitest run --coverage",
"typecheck": "tsc --noEmit",
"lint": "eslint --cache .",
"lint:fix": "pnpm lint --fix",
"lint": "eslint --cache . --fix",
"docs:dev": "pnpm -C docs dev",
"docs:build": "pnpm -C docs build",
"docs:preview": "pnpm -C docs preview",
"docs:deploy": "esno scripts/docs.deploy.ts"
"docs:deploy": "esno scripts/docs.deploy.ts",
"start": "esno scripts/start.ts"
},
"devDependencies": {
"@commitlint/cli": "^17.4.4",
@ -90,7 +90,7 @@
}
},
"lint-staged": {
"*.{js,json}": [
"*.{mjs,json}": [
"prettier --write"
],
"*.ts?(x)": [

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,2 @@
packages:
- docs
- example

View File

@ -1,33 +1,34 @@
import minimist from 'minimist';
import consola from 'consola';
import minimist from 'minimist'
import consola from 'consola'
import { distPath, exec } from './utils';
import { checkSize } from './checkSize';
import { distPath, exec } from './utils'
import { checkSize } from './checkSize'
import { safeExit } from './utils'
const args = minimist(process.argv.slice(2));
const watch = Boolean(args.watch || args.w);
const all = Boolean(args.all || args.a);
const sourceMap = all || Boolean(args.sourceMap || args.s);
const dts = all || Boolean(args.dts || args.d);
const args = minimist(process.argv.slice(2))
const watch = Boolean(args.watch || args.w)
const all = Boolean(args.all || args.a)
const sourceMap = all || Boolean(args.sourceMap || args.s)
const dts = all || Boolean(args.dts || args.d)
main();
main()
function main() {
exec('rimraf dist');
exec('rimraf dist')
consola.info('Rollup');
try {
consola.info('Rollup')
safeExit(() => {
exec(
`rollup -c rollup.config.ts --configPlugin typescript ${
watch ? '-w' : ''
} --environment SOURCE_MAP:${sourceMap},DTS:${dts}`,
);
)
})
checkSize(`${distPath}/**.js`);
} catch {
consola.error('已退出');
process.exit();
if (!watch) {
checkSize(`${distPath}/**.js`)
}
console.info('\n');
console.info('\n')
}

29
scripts/start.ts Normal file
View File

@ -0,0 +1,29 @@
import enquirer from 'enquirer'
import { exec } from './utils'
import { safeExit } from './utils'
const metas = [
{ name: 'weapp', message: '微信小程序' },
{ name: 'swan', message: '百度小程序' },
{ name: 'alipay', message: '支付宝小程序' },
{ name: 'tt', message: '抖音小程序' },
{ name: 'qq', message: 'QQ 小程序' },
{ name: 'jd', message: '京东小程序' },
{ name: 'dd', message: '钉钉小程序' },
{ name: 'lark', message: '飞书小程序' },
{ name: 'kwai', message: '快手小程序' },
{ name: 'h5', message: 'H5' },
]
safeExit(main)
async function main() {
const { platform } = await enquirer.prompt<{ platform: string }>({
type: 'select',
name: 'platform',
message: '请选择启动平台',
choices: metas,
})
exec(`pnpm -C example dev:${platform}`)
}

View File

@ -1,21 +1,39 @@
import path from 'node:path';
import { createRequire } from 'node:module';
import { fileURLToPath } from 'node:url';
import { ExecSyncOptions, execSync } from 'node:child_process';
import { isPromise } from 'node:util/types'
import path from 'node:path'
import { createRequire } from 'node:module'
import { fileURLToPath } from 'node:url'
import { ExecSyncOptions, execSync } from 'node:child_process'
import consola from 'consola'
export const __dirname = fileURLToPath(new URL('../', import.meta.url));
export const require = createRequire(import.meta.url);
export const pkgPath = path.resolve(__dirname, 'package.json');
export const distPath = path.resolve(__dirname, 'dist');
export const __dirname = fileURLToPath(new URL('../', import.meta.url))
export const require = createRequire(import.meta.url)
export const pkgPath = path.resolve(__dirname, 'package.json')
export const distPath = path.resolve(__dirname, 'dist')
export const resolve = (...paths: string[]) =>
path.resolve(__dirname, ...paths);
export const resolve = (...paths: string[]) => path.resolve(__dirname, ...paths)
export const exec = (command: string, options: ExecSyncOptions = {}) =>
execSync(command, {
stdio: 'inherit',
encoding: 'utf-8',
...options,
});
})
export const getPkgJSON = () => require(pkgPath);
export const getPkgJSON = () => require(pkgPath)
export function safeExit(run: () => unknown) {
try {
const p = run()
if (isPromise(p)) {
return p.catch(exit)
}
} catch {
exit()
}
}
function exit() {
consola.error('已退出')
process.exit()
}

View File

@ -1,16 +1,15 @@
import { AxiosRequestConfig } from '../core/Axios';
import { isPlainObject } from './isTypes';
import { buildURL } from './buildURL';
import { combineURL } from './combineURL';
import { dynamicURL } from './dynamicURL';
import { AxiosRequestConfig } from '../core/Axios'
import { isPlainObject } from './isTypes'
import { buildURL } from './buildURL'
import { combineURL } from './combineURL'
import { dynamicURL } from './dynamicURL'
export function transformURL(config: AxiosRequestConfig) {
let url = combineURL(config.baseURL, config.url);
url = dynamicURL(
url,
const fullPath = dynamicURL(
combineURL(config.baseURL, config.url),
config.params,
isPlainObject(config.data) ? config.data : {},
);
url = buildURL(url, config.params, config.paramsSerializer);
return url;
)
return buildURL(fullPath, config.params, config.paramsSerializer)
}

View File

@ -1,12 +1,12 @@
import { WITH_DATA_RE } from '../constants/methods';
import { isFunction, isString } from '../helpers/isTypes';
import { assert } from '../helpers/error';
import { AxiosRequestConfig, AxiosResponse } from '../core/Axios';
import { Cancel, isCancel, isCancelToken } from './cancel';
import { flattenHeaders } from './flattenHeaders';
import { AxiosTransformer, transformData } from './transformData';
import { request } from './request';
import { AxiosErrorResponse } from './createError';
import { WITH_DATA_RE } from '../constants/methods'
import { isFunction, isString } from '../helpers/isTypes'
import { assert } from '../helpers/error'
import { AxiosRequestConfig, AxiosResponse } from '../core/Axios'
import { Cancel, isCancel, isCancelToken } from './cancel'
import { flattenHeaders } from './flattenHeaders'
import { AxiosTransformer, transformData } from './transformData'
import { request } from './request'
import { AxiosErrorResponse } from './createError'
/**
*
@ -16,51 +16,51 @@ import { AxiosErrorResponse } from './createError';
* @param config
*/
export function dispatchRequest(config: AxiosRequestConfig) {
throwIfCancellationRequested(config);
throwIfCancellationRequested(config)
assert(isFunction(config.adapter), 'adapter 不是一个 function');
assert(isString(config.url), 'url 不是一个 string');
assert(isString(config.method), 'method 不是一个 string');
assert(isFunction(config.adapter), 'adapter 不是一个 function')
assert(isString(config.url), 'url 不是一个 string')
assert(isString(config.method), 'method 不是一个 string')
config.headers = flattenHeaders(config);
config.headers = flattenHeaders(config)
// 可以携带 data 的请求方法,转换 data
// 否则,删除 data
if (WITH_DATA_RE.test(config.method!)) {
dataTransformer(config, config.transformRequest);
dataTransformer(config, config.transformRequest)
} else {
delete config.data;
delete config.data
}
function onSuccess(response: AxiosResponse) {
throwIfCancellationRequested(config);
dataTransformer(response, config.transformResponse);
throwIfCancellationRequested(config)
dataTransformer(response, config.transformResponse)
return response;
return response
}
function onError(error: Cancel | AxiosErrorResponse) {
if (!isCancel(error)) {
throwIfCancellationRequested(config);
dataTransformer(error.response, config.transformResponse);
throwIfCancellationRequested(config)
dataTransformer(error.response, config.transformResponse)
}
return Promise.reject(error);
return Promise.reject(error)
}
function dataTransformer<TData = unknown>(
target: { data?: TData; headers?: AnyObject },
obj: { data?: TData; headers?: AnyObject },
fn?: AxiosTransformer<TData>,
) {
target.data = transformData(target.data, target.headers, fn);
obj.data = transformData(obj.data, obj.headers, fn)
}
return request(config).then(onSuccess, onError);
return request(config).then(onSuccess, onError)
}
function throwIfCancellationRequested(config: AxiosRequestConfig) {
const { cancelToken } = config;
const { cancelToken } = config
if (isCancelToken(cancelToken)) {
cancelToken.throwIfRequested();
cancelToken.throwIfRequested()
}
}

View File

@ -1,20 +1,20 @@
import { isFunction, isPlainObject } from '../helpers/isTypes';
import { transformURL } from '../helpers/transformURL';
import { isFunction, isPlainObject } from '../helpers/isTypes'
import { transformURL } from '../helpers/transformURL'
import {
AxiosRequestConfig,
AxiosResponse,
AxiosResponseError,
} from '../core/Axios';
} from '../core/Axios'
import {
AxiosAdapterRequestConfig,
AxiosAdapterResponse,
AxiosAdapterResponseError,
AxiosAdapterPlatformTask,
AxiosAdapterRequestMethod,
} from '../adpater/createAdapter';
import { isCancelToken } from './cancel';
import { AxiosErrorResponse, createError } from './createError';
import { generateType } from './generateType';
} from '../adpater/createAdapter'
import { isCancelToken } from './cancel'
import { AxiosErrorResponse, createError } from './createError'
import { generateType } from './generateType'
/**
*
@ -32,91 +32,91 @@ export function request(config: AxiosRequestConfig) {
method: config.method!.toUpperCase() as AxiosAdapterRequestMethod,
success,
fail,
};
}
let adapterTask: AxiosAdapterPlatformTask;
let adapterTask: AxiosAdapterPlatformTask
try {
adapterTask = config.adapter!(adapterConfig);
adapterTask = config.adapter!(adapterConfig)
} catch (err) {
fail({
status: 400,
statusText: 'Bad Adapter',
});
})
console.error(err);
console.error(err)
}
function success(baseResponse: AxiosAdapterResponse): void {
const response = baseResponse as AxiosResponse;
response.status = response.status ?? 200;
response.statusText = response.statusText ?? 'OK';
response.headers = response.headers ?? {};
response.config = config;
response.request = adapterTask;
const response = baseResponse as AxiosResponse
response.status = response.status ?? 200
response.statusText = response.statusText ?? 'OK'
response.headers = response.headers ?? {}
response.config = config
response.request = adapterTask
const { validateStatus } = config;
const { validateStatus } = config
if (!isFunction(validateStatus) || validateStatus(response.status)) {
resolve(response);
resolve(response)
} else {
catchError('validate status error', response);
catchError('validate status error', response)
}
}
function fail(baseResponseError: AxiosAdapterResponseError): void {
const responseError = baseResponseError as AxiosResponseError;
responseError.isFail = true;
responseError.status = responseError.status ?? 400;
responseError.statusText = responseError.statusText ?? 'Fail';
responseError.headers = responseError.headers ?? {};
responseError.config = config;
responseError.request = adapterTask;
const responseError = baseResponseError as AxiosResponseError
responseError.isFail = true
responseError.status = responseError.status ?? 400
responseError.statusText = responseError.statusText ?? 'Fail'
responseError.headers = responseError.headers ?? {}
responseError.config = config
responseError.request = adapterTask
catchError('request fail', responseError);
catchError('request fail', responseError)
}
function catchError(
message: string,
errorResponse: AxiosErrorResponse,
): void {
reject(createError(message, config, errorResponse, adapterTask));
reject(createError(message, config, errorResponse, adapterTask))
}
if (isPlainObject(adapterTask)) {
tryToggleProgressUpdate(adapterConfig, adapterTask.onProgressUpdate);
tryToggleProgressUpdate(adapterConfig, adapterTask.onProgressUpdate)
}
const { cancelToken } = config;
const { cancelToken } = config
if (isCancelToken(cancelToken)) {
cancelToken.onCancel((reason) => {
if (isPlainObject(adapterTask)) {
tryToggleProgressUpdate(adapterConfig, adapterTask.offProgressUpdate);
tryToggleProgressUpdate(adapterConfig, adapterTask.offProgressUpdate)
adapterTask?.abort?.();
adapterTask?.abort?.()
}
reject(reason);
});
reject(reason)
})
}
});
})
}
function tryToggleProgressUpdate(
adapterConfig: AxiosAdapterRequestConfig,
adapterProgress?: (cb: (event: AnyObject) => void) => void,
config: AxiosAdapterRequestConfig,
progress?: (cb: (event: AnyObject) => void) => void,
) {
const { onUploadProgress, onDownloadProgress } = adapterConfig;
if (isFunction(adapterProgress)) {
switch (adapterConfig.type) {
const { type, onUploadProgress, onDownloadProgress } = config
if (isFunction(progress)) {
switch (type) {
case 'upload':
if (isFunction(onUploadProgress)) {
adapterProgress(onUploadProgress);
progress(onUploadProgress)
}
break;
break
case 'download':
if (isFunction(onDownloadProgress)) {
adapterProgress(onDownloadProgress);
progress(onDownloadProgress)
}
break;
break
}
}
}

View File

@ -1,14 +1,14 @@
import { describe, test, expect, vi } from 'vitest';
import { asyncNext, mockAdapter, testEachMethods } from 'scripts/test.utils';
import { describe, test, expect, vi } from 'vitest'
import { asyncNext, mockAdapter } from 'scripts/test.utils'
import {
PLAIN_METHODS,
WITH_DATA_METHODS,
WITH_PARAMS_METHODS,
} from '@/constants/methods';
import { dispatchRequest } from '@/request/dispatchRequest';
} from '@/constants/methods'
import { dispatchRequest } from '@/request/dispatchRequest'
import axios from '@/axios';
import _defaults from '@/defaults';
import axios from '@/axios'
import _defaults from '@/defaults'
describe('src/request/dispatchRequest.ts', () => {
const defaults = {
@ -17,32 +17,32 @@ describe('src/request/dispatchRequest.ts', () => {
baseURL: 'http://api.com',
method: 'get' as const,
headers: {},
};
}
test('应该抛出异常', () => {
expect(() => dispatchRequest({})).toThrowErrorMatchingInlineSnapshot(
'"[axios-miniprogram]: adapter 不是一个 function"',
);
)
expect(() =>
dispatchRequest({ adapter: mockAdapter() }),
).toThrowErrorMatchingInlineSnapshot(
'"[axios-miniprogram]: url 不是一个 string"',
);
)
expect(() =>
dispatchRequest({ adapter: mockAdapter(), url: '/' }),
).toThrowErrorMatchingInlineSnapshot(
'"[axios-miniprogram]: method 不是一个 string"',
);
)
expect(() =>
dispatchRequest({ adapter: mockAdapter(), url: '/', method: 'get' }),
).not.toThrowError();
});
).not.toThrowError()
})
test('坏的适配器应该抛出异常', () => {
expect(
dispatchRequest({
adapter: () => {
throw 'bad adapter';
throw 'bad adapter'
},
url: '/',
method: 'get',
@ -71,8 +71,8 @@ describe('src/request/dispatchRequest.ts', () => {
"statusText": "Bad Adapter",
},
}
`);
});
`)
})
test('应该支持拉平请求头', () => {
const c = {
@ -87,16 +87,16 @@ describe('src/request/dispatchRequest.ts', () => {
},
h3: 3,
},
};
}
dispatchRequest(c);
dispatchRequest(c)
expect(c.headers).toEqual({
h1: 1,
h2: 2,
h3: 3,
});
});
})
})
test.each(WITH_DATA_METHODS)('%s 方法应该支持转换请求数据', (k) => {
const c = {
@ -105,12 +105,12 @@ describe('src/request/dispatchRequest.ts', () => {
method: k,
data: {},
transformRequest: () => ({ id: 1 }),
};
}
dispatchRequest(c);
dispatchRequest(c)
expect(c.data).toEqual({ id: 1 });
});
expect(c.data).toEqual({ id: 1 })
})
test('不能带数据的请求方法应该删除数据', () => {
const c = {
@ -118,66 +118,66 @@ describe('src/request/dispatchRequest.ts', () => {
url: 'test',
data: {},
transformRequest: () => ({ id: 1 }),
};
}
[...PLAIN_METHODS, ...WITH_PARAMS_METHODS].forEach((k) => {
const s = { ...c, method: k };
dispatchRequest(s);
expect(s.data).toBeUndefined();
});
});
;[...PLAIN_METHODS, ...WITH_PARAMS_METHODS].forEach((k) => {
const s = { ...c, method: k }
dispatchRequest(s)
expect(s.data).toBeUndefined()
})
})
test('应该支持转换响应数据', async () => {
const c = {
...defaults,
url: 'test',
transformResponse: () => ({ result: 1 }),
};
const r = await dispatchRequest(c);
expect(r.data).toEqual({ result: 1 });
});
test('请求发送前取消请求应该抛出异常', async () => {
const cb = vi.fn();
const { cancel, token } = axios.CancelToken.source();
const c = {
...defaults,
url: 'test',
cancelToken: token,
};
cancel();
try {
dispatchRequest(c);
} catch (err) {
cb(err);
}
expect(cb).toBeCalled();
expect(axios.isCancel(cb.mock.calls[0][0])).toBeTruthy();
});
const r = await dispatchRequest(c)
test('请求发送后取消请求应该抛出异常', async () => {
const cb = vi.fn();
const { cancel, token } = axios.CancelToken.source();
expect(r.data).toEqual({ result: 1 })
})
test('请求发送前取消请求应该抛出异常', async () => {
const cb = vi.fn()
const { cancel, token } = axios.CancelToken.source()
const c = {
...defaults,
url: 'test',
cancelToken: token,
};
}
const p = dispatchRequest(c).catch(cb);
cancel()
await asyncNext();
expect(cb).not.toBeCalled();
try {
dispatchRequest(c)
} catch (err) {
cb(err)
}
cancel();
await p;
expect(cb).toBeCalled()
expect(axios.isCancel(cb.mock.calls[0][0])).toBeTruthy()
})
expect(cb).toBeCalled();
expect(axios.isCancel(cb.mock.calls[0][0])).toBeTruthy();
});
});
test('请求发送后取消请求应该抛出异常', async () => {
const cb = vi.fn()
const { cancel, token } = axios.CancelToken.source()
const c = {
...defaults,
url: 'test',
cancelToken: token,
}
const p = dispatchRequest(c).catch(cb)
await asyncNext()
expect(cb).not.toBeCalled()
cancel()
await p
expect(cb).toBeCalled()
expect(axios.isCancel(cb.mock.calls[0][0])).toBeTruthy()
})
})