Compare commits

...

64 Commits
v2.3.0 ... main

Author SHA1 Message Date
zjx0905 9c9debbc17 chore: release v2.7.2 2024-01-31 19:15:27 +08:00
zjxxxxxxxxx c0352a5d6a
docs: 修复安装方式错误 (#58)
#57
2024-01-25 19:12:17 +08:00
zjxxxxxxxxx 5d45cd9670
fix: 修复设置请求 headers 影响了全局配置 (#56)
#55
2024-01-10 19:33:33 +08:00
zjx0905 6af2d8e5c3 chore: release v2.7.1 2023-12-16 12:48:10 +08:00
zjxxxxxxxxx df42674895
fix: 对上传文件响应数据JSON.parse (#54)
#53
2023-12-14 10:43:17 +08:00
zjxxxxxxxxx 3848fdd81b
feat: 添加符合 HTTP 规范的 statusText (#49) 2023-11-01 07:45:19 -05:00
zjx0905 7e7330405e chore: update format 2023-09-22 15:34:49 +08:00
zjx0905 5eaecd8b55 chore: 示例配置 allowedHosts 2023-08-17 17:11:57 +08:00
zjx0905 0c9fb2034a chore: 示例锁定 3000 端口号 2023-08-17 17:04:27 +08:00
zjx0905 2bc03961ce chore: release v2.7.0 2023-08-17 14:06:20 +08:00
zjx0905 4f91a45293 chore: 配置 CodeSandbox 和 Stackblitz 2023-08-17 13:41:55 +08:00
zjx0905 53f043275c feat: 新增支持小红书小程序 2023-08-15 15:43:24 +08:00
zjx0905 71e3007389 fix: 修复 errno 和 errMsg 丢失 2023-08-13 14:04:06 +08:00
zjx0905 391b47d7a9 docs: 升级 pnpm 2023-08-13 10:26:42 +08:00
zjx0905 6498923e9a chore: release v2.6.0 2023-08-13 10:22:29 +08:00
zjx0905 c57a01fd9e ci: 更新 pnpm 版本 2023-08-12 22:31:19 +08:00
zjx0905 a04f833d91 feat: 废弃 fork API
BREAKING CHANGE :
axios.fork() 已废弃
2023-08-12 22:08:44 +08:00
zjx0905 158d26fa64 chore: 更新所有者信息 2023-08-12 15:48:36 +08:00
zjx0905 11f69630a4 chore: release v2.5.0 2023-06-04 19:48:32 +08:00
zjx0905 96ea0266dd feat: 移除内置的 uni 适配器
BREAKING CHANGE :
uni 不再内部支持, 可以参阅文档中的自定义适配器自行适配 uni

#40
2023-06-04 19:44:32 +08:00
zjx0905 2496333e42 chore: release v2.4.2 2023-05-14 21:45:16 +08:00
zjx0905 3f4a8a12e0 chore: 隐藏内部使用类型 2023-05-14 21:44:08 +08:00
zjx0905 a1281f86a5 chore: 类型检查 2023-05-14 20:55:47 +08:00
zjx0905 7c60b723e1 chore: 修改 scripts 2023-05-14 19:12:47 +08:00
zjx0905 17022d2c98 chore: 编写基础示例 2023-05-09 20:35:31 +08:00
zjx0905 b6698ca22d feat: 发出请求前进行动态地址插值 2023-05-09 20:34:50 +08:00
zjx0905 6f1093fe1c docs: 移除边框 2023-05-08 15:57:18 +08:00
zjx0905 1152853ce2 docs: 修正下载文件示例 2023-05-07 23:16:28 +08:00
zjx0905 359b09172e docs: 初始化示例项目 2023-05-05 10:59:37 +08:00
zjx0905 74856f7fde fix: axios.use 函数返回值不是当前实例 2023-05-04 16:26:59 +08:00
zjx0905 fa5979b17e chore: release v2.4.1 2023-05-04 11:11:28 +08:00
zjx0905 cea4be518c chore: 修改部分内容 2023-05-04 11:10:07 +08:00
zjx0905 52037b8794 build: 优化包体积 2023-05-04 11:10:07 +08:00
zjx0905 671df397d3 docs: 修正错误处理示例 2023-05-04 11:08:01 +08:00
zjx0905 f23d27024f chore: 一些小的调整 2023-04-27 21:25:47 +08:00
zjx0905 e643f36fe0 chore: 移除 cleanStack 2023-04-27 11:08:24 +08:00
zjx0905 633c920247 feat: getUri 支持 baseURL/dynamicURL 2023-04-27 10:54:27 +08:00
zjx0905 0b82403c4c feat: 请求发送前请求方法转小写 2023-04-27 10:45:58 +08:00
zjx0905 c107171eba fix: 配置原始请求方法丢失 2023-04-27 10:34:36 +08:00
zjx0905 8b6eed2d6d fix: 配置原始 URL 丢失 2023-04-27 10:23:52 +08:00
zjx0905 4b02582152 feat: 允许设置默认请求方法 2023-04-27 09:45:48 +08:00
zjx0905 63f424133e docs: 介绍中间件 2023-04-26 22:57:18 +08:00
zjx0905 3931f230de perf: 优化中间件 2023-04-26 21:03:00 +08:00
zjx0905 f5db1102ce ci: 修改 release 2023-04-26 09:57:28 +08:00
zjx0905 0c562165c9 chore: release v2.4.0 2023-04-25 23:04:44 +08:00
zjx0905 db72446aa1 docs: 介绍扩展实例 2023-04-25 23:02:05 +08:00
zjx0905 1e5809aee3 revert: 取消支持为路径添加中间件 2023-04-25 22:18:08 +08:00
zjx0905 db787a2b5f fix: 丢失末尾自带的斜线
#44
2023-04-25 15:06:19 +08:00
zjx0905 bfc012b499 feat: 支持复用父级中间件 2023-04-25 14:28:28 +08:00
zjx0905 a84533a09f feat: 全局方法 create 改为实例方法 2023-04-25 11:59:50 +08:00
zjx0905 9093e1bdff feat: 添加扩展实例
BREAKING CHANGE :
原派生领域替换为功能更强的扩展实例
2023-04-25 11:54:10 +08:00
zjx0905 6263759ba9 feat: 添加中间件 2023-04-23 23:05:30 +08:00
zjx0905 7bfeba832c chore: release v2.3.2 2023-04-23 14:23:52 +08:00
zjx0905 c0ca9001d2 fix: 适配器请求头丢失
#43
2023-04-23 14:23:06 +08:00
zjx0905 968bbb775e refactor: 拆分模块 2023-04-22 16:12:32 +08:00
zjx0905 5aad9a83ab chore: release v2.3.1 2023-04-21 23:39:33 +08:00
zjx0905 cd65ce4a91 refactor: 新的目录结构 2023-04-21 18:09:32 +08:00
zjx0905 2d691b69cb fix: 下载进度/上传进度 类型错误 2023-04-20 21:49:26 +08:00
zjx0905 1867273460 refactor: 默认值的设置流程移到 request 里 2023-04-20 13:56:17 +08:00
zjx0905 258954afc1 fix: 控制台没有输出适配器错误 2023-04-20 10:57:10 +08:00
zjx0905 d021996c40 docs: 更新 algolia 2023-04-19 22:52:35 +08:00
zjx0905 7c29d2b74f docs: 修改错别字 2023-04-19 21:49:48 +08:00
zjx0905 e3346a866f feat: 添加版本号 2023-04-19 21:36:06 +08:00
zjx0905 5469471cea docs: 介绍转换数据 2023-04-19 12:00:06 +08:00
147 changed files with 20333 additions and 4793 deletions

View File

@ -1,50 +1,52 @@
const { execSync } = require('child_process');
const { execSync } = require('child_process')
const metas = [
{ type: 'feat', section: '✨ Features | 新功能' },
{ type: 'fix', section: '🐛 Bug Fixes | Bug 修复' },
{ type: 'test', section: '✅ Tests | 测试' },
{ type: 'docs', section: '📝 Documentation | 文档' },
{ type: 'build', section: '👷‍ Build System | 构建' },
{ type: 'ci', section: '🔧 Continuous Integration | CI 配置' },
{ type: 'perf', section: '⚡ Performance Improvements | 性能优化' },
{ type: 'revert', section: '⏪ Reverts | 回退' },
{ type: 'chore', section: '📦 Chores | 其他更新' },
{ type: 'style', section: '💄 Styles | 风格', hidden: true },
{ type: 'refactor', section: '♻ Code Refactoring | 代码重构' },
];
{ type: 'feat', section: '✨ Features | 新功能' },
{ type: 'fix', section: '🐛 Bug Fixes | Bug 修复' },
{ type: 'test', section: '✅ Tests | 测试' },
{ type: 'docs', section: '📝 Documentation | 文档' },
{ type: 'build', section: '👷‍ Build System | 构建' },
{ type: 'ci', section: '🔧 Continuous Integration | CI 配置' },
{ type: 'perf', section: '⚡ Performance Improvements | 性能优化' },
{ type: 'revert', section: '⏪ Reverts | 回退' },
{ type: 'chore', section: '📦 Chores | 其他更新' },
{ type: 'style', section: '💄 Styles | 风格', hidden: true },
{ type: 'refactor', section: '♻ Code Refactoring | 代码重构' },
]
/** @type {import('cz-git').UserConfig} */
module.exports = {
rules: {
// @see: https://commitlint.js.org/#/reference-rules
'subject-min-length': [0, 'always', 3],
'subject-max-length': [0, 'always', 80],
'type-enum': [0, 'always', metas.map((meta) => meta.type)],
},
prompt: {
messages: {
type: '请选择提交类型',
subject: '请输入变更描述',
breaking: '列举非兼容性重大的变更,如果有多行,使用 "|" 换行(选填项)\n',
footer: '列举关联的 issue例如#31,#I3244选填项\n',
confirmCommit: '确定提交',
},
types: metas.map((meta) => ({
value: meta.type,
name: `${`${meta.type}:`.padEnd(10, ' ')}${meta.section}`,
})),
allowBreakingChanges: ['feat', 'fix'],
skipQuestions: ['scope', 'body', 'footerPrefix'],
formatMessageCB: (commit) =>
`${commit?.defaultMessage}\n\nCo-authored-by: ${readGitUser(
'name',
)} <${readGitUser('email')}>`,
},
};
rules: {
// @see: https://commitlint.js.org/#/reference-rules
'subject-min-length': [0, 'always', 3],
'subject-max-length': [0, 'always', 80],
'type-enum': [0, 'always', metas.map((meta) => meta.type)],
},
prompt: {
messages: {
type: '请选择提交类型',
subject: '请输入变更描述',
breaking: '列举非兼容性重大的变更,如果有多行,使用 "|" 换行(选填项)\n',
footer: '列举关联的 issue例如#31,#I3244选填项\n',
confirmCommit: '确定提交',
},
types: metas.map((meta) => ({
value: meta.type,
name: `${`${meta.type}:`.padEnd(10, ' ')}${meta.section}`,
})),
allowBreakingChanges: ['feat', 'fix'],
skipQuestions: ['scope', 'body', 'footerPrefix'],
formatMessageCB: (commit) =>
`${commit?.defaultMessage}\n\nCo-authored-by: ${readGitUser(
'name',
)} <${readGitUser('email')}>`,
},
}
function readGitUser(key) {
return execSync(`git config user.${key}`)
.toString()
.replace(/(\r\n\t|\n|\r\t)/g, '');
return execSync(`git config user.${key}`, {
stdio: 'pipe',
})
.toString()
.replace(/(\r\n\t|\n|\r\t)/g, '')
}

View File

@ -1 +1,4 @@
/dist
dist/
example/dist/
example/config/**.js

16
.eslintrc Normal file
View File

@ -0,0 +1,16 @@
{
"root": true,
"env": {
"es2022": true,
"node": true
},
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-non-null-assertion": 0,
"@typescript-eslint/ban-ts-comment": 0,
"no-mixed-spaces-and-tabs": 0
}
}

View File

@ -1,15 +0,0 @@
{
"env": {
"es2022": true,
"node": true
},
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"root": true,
"rules": {
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-non-null-assertion": 0,
"@typescript-eslint/ban-ts-comment": 0
}
}

View File

@ -37,13 +37,13 @@ body:
label: 验证
description: 在提交问题之前,请确保您执行以下操作
options:
- label: 遵守我们的[行为准则 ](https://github.com/zjx0905/axios-miniprogram/blob/main/CODE_OF_CONDUCT.md)
- label: 遵守我们的[行为准则 ](https://github.com/zjxxxxxxxxx/axios-miniprogram/blob/main/CODE_OF_CONDUCT.md)
required: true
- label: 阅读[贡献指南](https://github.com/zjx0905/axios-miniprogram/blob/main/CONTRIBUTING.md).
- label: 阅读[贡献指南](https://github.com/zjxxxxxxxxx/axios-miniprogram/blob/main/CONTRIBUTING.md).
required: true
- label: 阅读[文档](https://axios-miniprogram.com).
required: true
- label: 检查是否还没有报告相同错误的[问题](https://github.com/zjx0905/axios-miniprogram/issues)以避免创建重复。
- label: 检查是否还没有报告相同错误的[问题](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues)以避免创建重复。
required: true
- label: 确保这是 axios-miniprogram 问题而不是特定于框架的问题。
required: true

View File

@ -17,7 +17,7 @@ body:
id: suggested-solution
attributes:
label: 建议的解决方案
description: '在模块 [xy] 中,我们可以提供以下实现......'
description: '我们可以提供以下实现......'
validations:
required: true
- type: textarea
@ -36,9 +36,9 @@ body:
label: 验证
description: 在提交问题之前,请确保您执行以下操作
options:
- label: 遵守我们的[行为准则 ](https://github.com/zjx0905/axios-miniprogram/blob/main/CODE_OF_CONDUCT.md)
- label: 遵守我们的[行为准则 ](https://github.com/zjxxxxxxxxx/axios-miniprogram/blob/main/CODE_OF_CONDUCT.md)
required: true
- label: 阅读[贡献指南](https://github.com/zjx0905/axios-miniprogram/blob/main/CONTRIBUTING.md).
- label: 阅读[贡献指南](https://github.com/zjxxxxxxxxx/axios-miniprogram/blob/main/CONTRIBUTING.md).
required: true
- label: 阅读[文档](https://axios-miniprogram.com).
required: true

View File

@ -24,7 +24,7 @@ jobs:
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 7
version: 8
- name: Set node
uses: actions/setup-node@v3
@ -33,7 +33,7 @@ jobs:
cache: pnpm
- name: Install
run: pnpm i
run: pnpm install --no-frozen-lockfile
- name: Lint
run: pnpm lint

View File

@ -2,6 +2,8 @@ name: Deploy Docs
on:
push:
tags:
- v*
branches:
- docs
workflow_dispatch:
@ -16,7 +18,7 @@ jobs:
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 7
version: 8
- name: Set node
uses: actions/setup-node@v3
@ -25,7 +27,7 @@ jobs:
cache: pnpm
- name: Install
run: pnpm i
run: pnpm install --no-frozen-lockfile
- name: Build
run: pnpm docs:build

View File

@ -15,7 +15,7 @@ jobs:
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 7
version: 8
- name: Set node
uses: actions/setup-node@v3
@ -24,7 +24,7 @@ jobs:
cache: pnpm
- name: Install
run: pnpm i
run: pnpm install --no-frozen-lockfile
- name: Build
run: pnpm build -a

View File

@ -15,7 +15,7 @@ jobs:
- name: Install pnpm
uses: pnpm/action-setup@v2
with:
version: 7
version: 8
- name: Set node
uses: actions/setup-node@v3
@ -24,7 +24,7 @@ jobs:
cache: pnpm
- name: Install
run: pnpm i
run: pnpm install --no-frozen-lockfile
- name: Build Release Assets
run: pnpm build:assets
@ -44,7 +44,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
name: Release ${{ github.ref_name }}
prerelease: ${{ steps.prerelease.outputs.result }}
body_path: 'RELEASELOG.md'
files: 'dist/**.zip'

4
.gitignore vendored
View File

@ -3,7 +3,6 @@ node_modules
*.log
# Docs
dist
docs/.vitepress/cache
docs/pages/guide/intro.md
@ -11,7 +10,8 @@ docs/pages/guide/intro.md
.DS_Store
# Bundle
lib/
dist/
.swc
# Typescript build file
*.tsbuildinfo

View File

@ -1 +1,5 @@
CHANGELOG.md
dist/
example/dist/
example/config/**.js

View File

@ -1,67 +1,219 @@
# [2.3.0](https://github.com/zjx0905/axios-miniprogram/compare/v2.2.0...v2.3.0) (2023-04-18)
## [2.7.2](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.7.1...v2.7.2) (2024-01-31)
### Bug Fixes
* 错误处理不是每次出错都执行 ([fb4762d](https://github.com/zjx0905/axios-miniprogram/commit/fb4762d01a0d304ce6c291d6487dce1507a985c5))
* data 不支持对象以外的类型 ([4d8ec80](https://github.com/zjx0905/axios-miniprogram/commit/4d8ec80f29b85e3419d1bc5112886a397ee2cc48))
### Features
* 从参数中删除动态地址属性 ([b0eaa04](https://github.com/zjx0905/axios-miniprogram/commit/b0eaa04c66dc82de944769893f62ecd0c4ae76d8))
* 提供更多可使用的类型 ([0dc58a4](https://github.com/zjx0905/axios-miniprogram/commit/0dc58a4b0cdd5d36c1b16f13697d8180952cb093))
* 支持具名导入工具函数 ([d714ed2](https://github.com/zjx0905/axios-miniprogram/commit/d714ed23c0f3b8ea3abecfb042c67bcf9adb29a7))
* 支持清空拦截器 ([cbcc43a](https://github.com/zjx0905/axios-miniprogram/commit/cbcc43ad77f0e79223e524aa6bb4502ee4b989c9))
* 修复设置请求 headers 影响了全局配置 ([#56](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues/56)) ([5d45cd9](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/5d45cd9670c3bc8b58437d2defc58753ebc6392e)), closes [#55](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues/55)
# [2.2.0](https://github.com/zjx0905/axios-miniprogram/compare/v2.1.0...v2.2.0) (2023-04-16)
## [2.7.1](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.7.0...v2.7.1) (2023-12-16)
### Bug Fixes
* 修复 Proxy uni 错误 ([021e052](https://github.com/zjx0905/axios-miniprogram/commit/021e05233a95ebc5c5f93d114d225cc45a22675f))
* 对上传文件响应数据JSON.parse ([#54](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues/54)) ([df42674](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/df4267489508f6d1851f52d78e9d9179709a562a)), closes [#53](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues/53)
### Features
* 仅 post/put/patch 方法允许设置请求数据 ([2c3ff56](https://github.com/zjx0905/axios-miniprogram/commit/2c3ff567c19197f6377645cd9f7109806cd93b77))
* 支持 HTTP PATCH 请求 ([22bcefc](https://github.com/zjx0905/axios-miniprogram/commit/22bcefcb97e50400403b131d307c97eb4cbb6071))
* 添加符合 HTTP 规范的 statusText ([#49](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues/49)) ([3848fdd](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/3848fdd81bf8fb1f5e373ca4e117adb653969acf))
# [2.1.0](https://github.com/zjx0905/axios-miniprogram/compare/v2.0.0...v2.1.0) (2023-04-11)
# [2.7.0](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.6.0...v2.7.0) (2023-08-17)
### Bug Fixes
* 修复 axios.fork() 无法访问私有方法 ([2254e73](https://github.com/zjx0905/axios-miniprogram/commit/2254e73cf76f1bc95d4850211e3fa34acae50136))
* 移除 url 末尾的斜线 ([1c09ffd](https://github.com/zjx0905/axios-miniprogram/commit/1c09ffdd91d554078423cba57fe036106e9b0fa8))
* 修复 errno 和 errMsg 丢失 ([71e3007](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/71e30073890974f54461134620dfbda58cc36af0))
### Features
* 适配器异常处理成响应异常 ([be17ba7](https://github.com/zjx0905/axios-miniprogram/commit/be17ba7e6881699aeb74b45c8b4b084e1e53a777))
* 添加新功能 派生领域 axios.fork() ([222b935](https://github.com/zjx0905/axios-miniprogram/commit/222b935f6839ce8fcecfa951d937e6160211f7f9))
* 修改 mergeConfig 中 data 的合并方式 ([ee6a31b](https://github.com/zjx0905/axios-miniprogram/commit/ee6a31b4bbc07e93f8754c83a1ff02495a23dfa7))
* 支持深度合并 params & data ([22f65cf](https://github.com/zjx0905/axios-miniprogram/commit/22f65cf69c877f314b269d8c3d0fac8f1c8ab71f))
* fileName 替换为 name ([69044f3](https://github.com/zjx0905/axios-miniprogram/commit/69044f35833d8d42a5f0c12b01687298c08f589b))
* 新增支持小红书小程序 ([53f0432](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/53f043275ced79c7204d791c62721e36db512f24))
# [2.0.0](https://github.com/zjx0905/axios-miniprogram/compare/v2.0.0-beta.10...v2.0.0) (2023-04-05)
# [2.6.0](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.5.0...v2.6.0) (2023-08-13)
### Features
* 废弃 fork API ([a04f833](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/a04f833d917cb07c3bd95678260971194179def0))
### BREAKING CHANGES
* axios.fork() 已废弃
# [2.5.0](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.4.2...v2.5.0) (2023-06-04)
### Features
* 移除内置的 uni 适配器 ([96ea026](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/96ea0266dd7c0da26341d8fea4d3bdb53361ffd0)), closes [#40](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues/40)
### BREAKING CHANGES
* uni 不再内部支持, 可以参阅文档中的自定义适配器自行适配 uni
## [2.4.2](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.4.1...v2.4.2) (2023-05-14)
### Bug Fixes
* 修复 dynamicURL 错误匹配端口号 ([7e29e91](https://github.com/zjx0905/axios-miniprogram/commit/7e29e91f0a2a4b1b1f3ca49a9cd5ff123466301a))
* axios.use 函数返回值不是当前实例 ([74856f7](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/74856f7fdef4f0e75b8665300960416a840f561c))
### Features
* 添加新的 API isAxiosError ([61337a9](https://github.com/zjx0905/axios-miniprogram/commit/61337a9bbe100cdab9e175f8ee42e4d5d2ba6842))
* 优化 defaults ([2793dd8](https://github.com/zjx0905/axios-miniprogram/commit/2793dd8b5e1ad34218088718314e06545033cbbf))
* 发出请求前进行动态地址插值 ([b6698ca](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/b6698ca22da3f754e21916e69d43b961e12571e6))
## [2.4.1](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.4.0...v2.4.1) (2023-05-04)
### Bug Fixes
* 配置原始 URL 丢失 ([8b6eed2](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/8b6eed2d6df5c7aacd181f6fbcfba9eca875178c))
* 配置原始请求方法丢失 ([c107171](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/c107171eba69a129eddad34861611837a0efac25))
### Features
* 请求发送前请求方法转小写 ([0b82403](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/0b82403c4c630676042ff390b77d5791c4ab0a6e))
* 允许设置默认请求方法 ([4b02582](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/4b025821525712d7e6bb68faa9af3cf7d9ad0e0d))
* getUri 支持 baseURL/dynamicURL ([633c920](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/633c92024718370e24919fcfb44b86b795248c8f))
### Performance Improvements
* 优化中间件 ([3931f23](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/3931f230deffbb72a70fd24798334e63a3d531f9))
# [2.4.0](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.3.2...v2.4.0) (2023-04-25)
### Bug Fixes
* 丢失末尾自带的斜线 ([db787a2](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/db787a2b5f7f1188d1813ddb715ef23e653120a9)), closes [#44](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues/44)
### Features
* 全局方法 create 改为实例方法 ([a84533a](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/a84533a09f493e27ba3e567549be5e534271ed22))
* 添加扩展实例 ([9093e1b](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/9093e1bdffe5bd75fccfeeeeb0e2b487751c549a))
* 添加中间件 ([6263759](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/6263759ba94b2269082c49a2f2a5e038f6766027))
* 支持复用父级中间件 ([bfc012b](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/bfc012b4999d717629b997ab908fd411954b0323))
### Reverts
* 取消支持为路径添加中间件 ([1e5809a](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/1e5809aee3f1653eced0c2ca351c6e3f8616f719))
### BREAKING CHANGES
* 原派生领域替换为功能更强的扩展实例
## [2.3.2](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.3.1...v2.3.2) (2023-04-23)
### Bug Fixes
* 适配器请求头丢失 ([c0ca900](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/c0ca9001d2dc2b138a916c18da000b733d58ec7a)), closes [#43](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues/43)
## [2.3.1](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.3.0...v2.3.1) (2023-04-21)
### Bug Fixes
* 控制台没有输出适配器错误 ([258954a](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/258954afc1c39483ff6b1828c8904c5b284890d2))
* 下载进度/上传进度 类型错误 ([2d691b6](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/2d691b69cbb2d3e27be3698bf4a4188cf71ccb7e))
### Features
* 添加版本号 ([e3346a8](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/e3346a866f12ed8aa07695f45a8177d631973abd))
# [2.3.0](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.2.0...v2.3.0) (2023-04-18)
### Bug Fixes
* 错误处理不是每次出错都执行 ([fb4762d](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/fb4762d01a0d304ce6c291d6487dce1507a985c5))
* data 不支持对象以外的类型 ([4d8ec80](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/4d8ec80f29b85e3419d1bc5112886a397ee2cc48))
### Features
* 从参数中删除动态地址属性 ([b0eaa04](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/b0eaa04c66dc82de944769893f62ecd0c4ae76d8))
* 提供更多可使用的类型 ([0dc58a4](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/0dc58a4b0cdd5d36c1b16f13697d8180952cb093))
* 支持具名导入工具函数 ([d714ed2](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/d714ed23c0f3b8ea3abecfb042c67bcf9adb29a7))
* 支持清空拦截器 ([cbcc43a](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/cbcc43ad77f0e79223e524aa6bb4502ee4b989c9))
# [2.2.0](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.1.0...v2.2.0) (2023-04-16)
### Bug Fixes
* 修复 Proxy uni 错误 ([021e052](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/021e05233a95ebc5c5f93d114d225cc45a22675f))
### Features
* 仅 post/put/patch 方法允许设置请求数据 ([2c3ff56](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/2c3ff567c19197f6377645cd9f7109806cd93b77))
* 支持 HTTP PATCH 请求 ([22bcefc](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/22bcefcb97e50400403b131d307c97eb4cbb6071))
# [2.1.0](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.0.0...v2.1.0) (2023-04-11)
### Bug Fixes
* 修复 axios.fork() 无法访问私有方法 ([2254e73](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/2254e73cf76f1bc95d4850211e3fa34acae50136))
* 移除 url 末尾的斜线 ([1c09ffd](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/1c09ffdd91d554078423cba57fe036106e9b0fa8))
### Features
* 适配器异常处理成响应异常 ([be17ba7](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/be17ba7e6881699aeb74b45c8b4b084e1e53a777))
* 添加新功能 派生领域 axios.fork() ([222b935](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/222b935f6839ce8fcecfa951d937e6160211f7f9))
* 修改 mergeConfig 中 data 的合并方式 ([ee6a31b](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/ee6a31b4bbc07e93f8754c83a1ff02495a23dfa7))
* 支持深度合并 params & data ([22f65cf](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/22f65cf69c877f314b269d8c3d0fac8f1c8ab71f))
* fileName 替换为 name ([69044f3](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/69044f35833d8d42a5f0c12b01687298c08f589b))
# [2.0.0](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.0.0-beta.10...v2.0.0) (2023-04-05)
### Bug Fixes
* 修复 dynamicURL 错误匹配端口号 ([7e29e91](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/7e29e91f0a2a4b1b1f3ca49a9cd5ff123466301a))
### Features
* 添加新的 API isAxiosError ([61337a9](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/61337a9bbe100cdab9e175f8ee42e4d5d2ba6842))
* 优化 defaults ([2793dd8](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/2793dd8b5e1ad34218088718314e06545033cbbf))
### BREAKING CHANGES
@ -70,12 +222,12 @@
# [2.0.0-beta.10](https://github.com/zjx0905/axios-miniprogram/compare/v2.0.0-beta.0...v2.0.0-beta.10) (2023-04-05)
# [2.0.0-beta.10](https://github.com/zjxxxxxxxxx/axios-miniprogram/compare/v2.0.0-beta.0...v2.0.0-beta.10) (2023-04-05)
### Features
* 支持 es2015 ([b66176f](https://github.com/zjx0905/axios-miniprogram/commit/b66176f0ed90eaec5c1377077359a234691ae1b3))
* 支持 es2015 ([b66176f](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/b66176f0ed90eaec5c1377077359a234691ae1b3))
@ -83,14 +235,14 @@
### Bug Fixes
* 清理 url 前面多余的斜线 ([666a942](https://github.com/zjx0905/axios-miniprogram/commit/666a9427d3c9bfbd96def9e112d5183acdf08d84))
* 清理 url 前面多余的斜线 ([666a942](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/666a9427d3c9bfbd96def9e112d5183acdf08d84))
### Features
* 增强默认参数系列化器 ([0cfb3e1](https://github.com/zjx0905/axios-miniprogram/commit/0cfb3e1ff04b69896ba43ffcb6abba5fb61ad48a))
* 支持合并自定义配置 ([4409a57](https://github.com/zjx0905/axios-miniprogram/commit/4409a5720ba1e58a4c218ee67f71d5f05beee6a8)), closes [#38](https://github.com/zjx0905/axios-miniprogram/issues/38)
* 支持京东小程序 ([0d1d21f](https://github.com/zjx0905/axios-miniprogram/commit/0d1d21fc66eb202463ef2baaa174b0f60276035e))
* 支持自定义配置 ([b15b31e](https://github.com/zjx0905/axios-miniprogram/commit/b15b31ee55217f11e08713ce02dd7ab21732fba1))
* 增强默认参数系列化器 ([0cfb3e1](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/0cfb3e1ff04b69896ba43ffcb6abba5fb61ad48a))
* 支持合并自定义配置 ([4409a57](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/4409a5720ba1e58a4c218ee67f71d5f05beee6a8)), closes [#38](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues/38)
* 支持京东小程序 ([0d1d21f](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/0d1d21fc66eb202463ef2baaa174b0f60276035e))
* 支持自定义配置 ([b15b31e](https://github.com/zjxxxxxxxxx/axios-miniprogram/commit/b15b31ee55217f11e08713ce02dd7ab21732fba1))
### BREAKING CHANGES

View File

@ -34,7 +34,7 @@ pnpm cz
脚本列表
- `pnpm build` 打包源代码
- `pnpm watch` 监听文件变更并运行 `build`
- `pnpm dev` 监听文件变更并运行 `build`
- `pnpm test` 单元测试
- `pnpm test:watch` 监听文件变更并运行 `test`
- `pnpm test:cov` 运行 `test` 并输出测试覆盖率
@ -50,7 +50,7 @@ pnpm cz
添加新功能有一些注意事项。
- 在你开始工作之前,最好先开一个 [issue](https://github.com/zjx0905/axios-miniprogram/issues) 来讨论。
- 在你开始工作之前,最好先开一个 [issue](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues) 来讨论。
- 应该对新功能进行单元测试。
- 应该在文档中添加相关的使用介绍及方法。

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2020-present, zjx0905 <https://github.com/zjx0905>
Copyright (c) 2020-present, zjxxxxxxxxx <https://github.com/zjxxxxxxxxx>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,24 +1,26 @@
# axios-miniprogram
<h1 align="center">axios-miniprogram</h1>
<p style="display: flex;margin-left:-5px;">
<a href="https://github.com/zjx0905/axios-miniprogram/actions/workflows/ci.yml">
<img src="https://github.com/zjx0905/axios-miniprogram/actions/workflows/ci.yml/badge.svg" alt="ci">
<p style="text-align: center;" align="center">
<a style="display: inline-block;margin-left: 5px;" href="https://github.com/zjxxxxxxxxx/axios-miniprogram/actions/workflows/ci.yml">
<img src="https://github.com/zjxxxxxxxxx/axios-miniprogram/actions/workflows/ci.yml/badge.svg" alt="ci"/>
</a>
<a style="margin-left:5px;" href="https://www.npmjs.org/package/axios-miniprogram">
<img src="https://img.shields.io/npm/v/axios-miniprogram" alt="npm">
<a style="display: inline-block;margin-left: 5px;" href="https://codecov.io/gh/zjxxxxxxxxx/axios-miniprogram" >
<img src="https://codecov.io/gh/zjxxxxxxxxx/axios-miniprogram/branch/main/graph/badge.svg?token=WIQVYX2WIK" alt="codecov"/>
</a>
<a style="margin-left:5px;" href="https://codecov.io/gh/zjx0905/axios-miniprogram" >
<img src="https://codecov.io/gh/zjx0905/axios-miniprogram/branch/main/graph/badge.svg?token=WIQVYX2WIK" alt="codecov"/>
<a style="display: inline-block;margin-left: 5px;" href="https://opensource.org/licenses/MIT">
<img src="https://img.shields.io/github/license/zjxxxxxxxxx/axios-miniprogram" alt="license"/>
</a>
<a style="margin-left:5px;" href="https://www.npmjs.org/package/axios-miniprogram">
<img src="https://img.shields.io/bundlephobia/min/axios-miniprogram" alt="npm bundle size">
</a>
<a style="margin-left:5px;" href="https://opensource.org/licenses/MIT">
<img src="https://img.shields.io/github/license/zjx0905/axios-miniprogram" alt="license">
<a style="display: inline-block;margin-left: 5px;" href="https://www.npmjs.org/package/axios-miniprogram">
<img src="https://img.shields.io/bundlephobia/min/axios-miniprogram" alt="npm bundle size"/>
</a>
<a style="display: inline-block;" href="https://www.npmjs.org/package/axios-miniprogram">
<img alt="npm" src="https://img.shields.io/npm/dt/axios-miniprogram"/>
</a>
</p>
[中文文档](https://axios-miniprogram.com)
<p style="text-align: center;" align="center">
<a href='https://axios-miniprogram.com'>中文文档</a>
</p>
## axios-miniprogram 是什么?
@ -27,16 +29,17 @@ axios-miniprogram 是一款为小程序平台量身定制的轻量级请求库
## 特性
- 支持 `Typescript`,健全的类型系统,智能的 `IDE` 提示。
- 支持 `Promise`
- 支持 拦截器。
- 支持 取消请求。
- 支持 自定义合法状态码。
- 支持 自定义参数序列化。
- 支持 自定义转换数据。
- 支持 自定义错误处理。
- 支持 自定义平台适配器。
- 支持 动态地址。
- 支持 校验状态码。
- 支持 参数序列化。
- 支持 上传/下载。
- 支持 派生领域。
- 支持 错误处理。
- 支持 转换数据。
- 支持 取消请求。
- 支持 扩展实例。
- 支持 中间件。
- 支持 拦截器。
- 支持 平台适配器。
## 目前内部支持的平台
@ -50,17 +53,28 @@ axios-miniprogram 是一款为小程序平台量身定制的轻量级请求库
- [飞书小程序](https://open.feishu.cn/document/uYjL24iN/uMjNzUjLzYzM14yM2MTN?from=axios-miniprogram)
- [快手小程序](https://mp.kuaishou.com/docs/introduction/quickStart.html?from=axios-miniprogram)
- [360 小程序](https://mp.360.cn/doc/miniprogram/dev/#/f4b41f0cc5683bce78dfadfa7f3c73e7?from=axios-miniprogram)
- [小红书小程序](https://miniapp.xiaohongshu.com/docs/guide/miniIntroduce?from=axios-miniprogram)
## 关于在跨端框架中使用时的支持度
问:在 uni-app 或者 Taro 等等这类跨端框架中使用时,该请求库支持 h5APPvue3react 等等吗?
问:在 uni-app 或者 Taro 等等这类跨端框架中使用时,该请求库支持 h5APPvue3 等等吗?
答:该请求库只是对框架提供的请求 API 进行了封装,并没有使用什么黑魔法。理论上来讲,框架支持的平台,该库也必然支持。
有问题欢迎反馈,请尽量把问题提到 [github issues](https://github.com/zjx0905/axios-miniprogram/issues) 中,这样更容易被我注意到。
有问题欢迎反馈,请尽量把问题提到 [github issues](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues) 中,这样更容易被我注意到。
[提问点这里](https://github.com/zjx0905/axios-miniprogram/issues)
[提问点这里](https://github.com/zjxxxxxxxxx/axios-miniprogram/issues)
## 未来计划
## 跨端框架示例
2023 年 6 月 1 日 起该库将不再内部支持第三方框架,内置的 uni-app 即将移除,您依旧可以使用[适配器](https://axios-miniprogram.com/advanced/adapter)兼容 uni-app。
### Taro
- [源代码](https://github.com/zjxxxxxxxxx/axios-miniprogram/tree/main/examples/taro)
- [CodeSandbox](https://codesandbox.io/p/sandbox/github/zjxxxxxxxxx/axios-miniprogram/tree/main/examples/taro)
- [StackBlitz](https://stackblitz.com/github/zjxxxxxxxxx/axios-miniprogram/tree/main/examples/taro)
### uni-app
- [源代码](https://github.com/zjxxxxxxxxx/axios-miniprogram/tree/main/examples/uni-app)
- [CodeSandbox](https://codesandbox.io/p/sandbox/github/zjxxxxxxxxx/axios-miniprogram/tree/main/examples/uni-app)
- [StackBlitz](https://stackblitz.com/github/zjxxxxxxxxx/axios-miniprogram/tree/main/examples/uni-app)

View File

@ -18,11 +18,10 @@ export default defineConfig({
nav: [
{ text: '指南', link: '/guide/intro', activeMatch: '/guide/' },
{ text: '请求方法', link: '/method/OPTIONS', activeMatch: '/method/' },
{ text: '基础', link: '/basics/config', activeMatch: '/basics/' },
{ text: '入门', link: '/basics/request', activeMatch: '/basics/' },
{
text: '高级',
link: '/advanced/request-interceptor',
text: '进阶',
link: '/advanced/middleware',
activeMatch: '/advanced/',
},
],
@ -30,15 +29,18 @@ export default defineConfig({
sidebar: sidebar(),
socialLinks: [
{ icon: 'github', link: 'https://github.com/zjx0905/axios-miniprogram' },
{
icon: 'github',
link: 'https://github.com/zjxxxxxxxxx/axios-miniprogram',
},
],
editLink: {
pattern: ({ relativePath }) => {
if (relativePath.endsWith('/intro.md')) {
return 'https://github.com/zjx0905/axios-miniprogram/edit/main/README.md';
return 'https://github.com/zjxxxxxxxxx/axios-miniprogram/edit/main/README.md';
}
return `https://github.com/zjx0905/axios-miniprogram/edit/main/docs/pages/${relativePath}`;
return `https://github.com/zjxxxxxxxxx/axios-miniprogram/edit/main/docs/pages/${relativePath}`;
},
text: '在 GitHub 上编辑此页面',
},
@ -56,9 +58,9 @@ export default defineConfig({
},
footer: {
message:
'根据 <a href="https://github.com/zjx0905/axios-miniprogram/blob/main/LICENSE">MIT License</a> 发布',
'根据 <a href="https://github.com/zjxxxxxxxxx/axios-miniprogram/blob/main/LICENSE">MIT License</a> 发布',
copyright:
'Copyright © 2020-至今 <a href="https://github.com/zjx0905">zjx0905</a>',
'Copyright © 2020-至今 <a href="https://github.com/zjxxxxxxxxx">zjxxxxxxxxx</a>',
},
},
@ -93,6 +95,38 @@ function sidebar() {
{ text: '开始', link: '/guide/quick-start' },
],
},
{
text: '入门',
items: [
{ text: '发送请求', link: '/basics/request' },
{ text: '响应体', link: '/basics/response' },
{ text: '错误处理', link: '/basics/error-handler' },
{ text: '动态地址', link: '/basics/dynamic-url' },
{ text: '请求配置', link: '/basics/config' },
{ text: '默认配置', link: '/basics/defaults' },
{ text: '参数系列化', link: '/basics/params-serializer' },
{ text: '转换数据', link: '/basics/transform-data' },
{ text: '下载文件', link: '/basics/download' },
{ text: '上传文件', link: '/basics/upload' },
],
collapsed: false,
},
{
text: '进阶',
items: [
{ text: '中间件', link: '/advanced/middleware' },
{ text: '请求拦截器', link: '/advanced/request-interceptor' },
{ text: '响应拦截器', link: '/advanced/response-interceptor' },
{ text: '取消请求', link: '/advanced/cancel' },
{ text: '创建实例', link: '/advanced/instance' },
{ text: '扩展实例', link: '/advanced/extend' },
{ text: '平台适配器', link: '/advanced/adapter' },
],
collapsed: false,
},
{
text: '请求方法',
items: [
@ -108,45 +142,17 @@ function sidebar() {
],
collapsed: false,
},
{
text: '基础',
items: [
{ text: '请求配置', link: '/basics/config' },
{ text: '默认配置', link: '/basics/defaults' },
{ text: '响应体', link: '/basics/response' },
{ text: '发送请求', link: '/basics/request' },
{ text: '动态地址', link: '/basics/dynamic-url' },
{ text: '参数系列化', link: '/basics/params-serializer' },
{ text: '转换数据', link: '/basics/transform-data' },
{ text: '下载文件', link: '/basics/download' },
{ text: '上传文件', link: '/basics/upload' },
{ text: '错误处理', link: '/basics/error-handler' },
{ text: '取消请求', link: '/basics/cancel' },
],
collapsed: false,
},
{
text: '高级',
items: [
{ text: '请求拦截器', link: '/advanced/request-interceptor' },
{ text: '响应拦截器', link: '/advanced/response-interceptor' },
{ text: '创建实例', link: '/advanced/instance' },
{ text: '派生领域', link: '/advanced/fork' },
{ text: '平台适配器', link: '/advanced/adapter' },
],
collapsed: false,
},
{
text: '致贡献者',
items: [
{
text: '行为准则',
link: 'https://github.com/zjx0905/axios-miniprogram/blob/main/CODE_OF_CONDUCT.md',
link: 'https://github.com/zjxxxxxxxxx/axios-miniprogram/blob/main/CODE_OF_CONDUCT.md',
},
{
text: '贡献指南',
link: 'https://github.com/zjx0905/axios-miniprogram/blob/main/CONTRIBUTING.md',
link: 'https://github.com/zjxxxxxxxxx/axios-miniprogram/blob/main/CONTRIBUTING.md',
},
],
},
@ -156,7 +162,7 @@ function sidebar() {
function algolia() {
return {
appId: 'B2V3TSSQ2T',
apiKey: 'c3edeb2daf09a254ec07ad98abfd84b5',
apiKey: '2eddc4539ada25bf664eddcb91930736',
indexName: 'axios-miniprogram',
placeholder: '搜索文档',
translations: {

View File

@ -20,7 +20,6 @@
margin-top: var(--vp-nav-height);
padding-top: 40px !important;
height: calc(100% - var(--vp-nav-height));
border-right: 1px solid var(--vp-c-gutter);
transition: transform 0.3s cubic-bezier(0.19, 1, 0.22, 1) !important;
}
@ -149,11 +148,6 @@
}
.vp-code-group .tabs {
border-top: 1px;
border-left: 1px;
border-right: 1px;
border-bottom: 0;
border-style: solid;
border-color: var(--vp-c-gutter);
}
@ -170,6 +164,10 @@
box-shadow: none;
}
.DocSearch-Logo svg > * {
fill: currentColor;
}
.custom-block {
border-radius: 6px;
background-color: var(--vp-custom-block-tip-bg) !important;
@ -183,6 +181,10 @@
background-color: var(--vp-code-block-bg);
}
.dark .DocSearch-Logo svg > * {
fill: currentColor;
}
@media (min-width: 960px) {
.VPFeatures .item {
width: calc(100% / 2) !important;
@ -203,7 +205,6 @@
.language-bash,
.language-ts {
border-radius: 6px;
border: 1px solid var(--vp-c-gutter);
}
.prev-next {

View File

@ -39,7 +39,8 @@
--vp-custom-block-tip-text: var(--vp-c-brand);
--vp-custom-block-tip-bg: var(--vp-c-bg);
--docsearch-container-background: rgba(0, 0, 0, 0.1);
--docsearch-container-background: rgba(0, 0, 0, 0.02);
--docsearch-logo-color: var(--vp-c-brand);
--vp-sidebar-width: 340px;
}
@ -67,5 +68,9 @@
--vp-code-copy-code-border-color: rgba(240, 246, 252, 0.1);
--vp-code-copy-code-hover-border-color: #8b949e;
--docsearch-container-background: rgba(255, 255, 255, 0.1);
--docsearch-container-background: rgba(255, 255, 255, 0.08);
}
.dark .DocSearch {
--docsearch-logo-color: var(--vp-c-brand);
}

View File

@ -1,4 +1,4 @@
import { linkSync } from 'node:fs';
import { linkSync, unlinkSync } from 'node:fs';
import { resolve } from '../../../scripts/utils';
const readmePath = resolve('README.md');
@ -6,6 +6,9 @@ const introPath = resolve('docs/pages/guide/intro.md');
export function linkIntro() {
try {
linkSync(readmePath, introPath);
} catch {}
unlinkSync(introPath);
} catch {
//
}
linkSync(readmePath, introPath);
}

View File

@ -91,7 +91,7 @@ import axios from 'axios-miniprogram';
// 适配器
axios.defaults.adapter = (config) => {
// 可以先看看 config 都有哪些东西
// 可以先看看 config 上都有哪些属性
console.log(config);
// 开始适配不同类型的请求
@ -122,13 +122,12 @@ axios.defaults.adapter = (config) => {
success: (response) => {
config.success({
// 状态码
// 默认值200
status: response.statusCode,
// 状态文本,选填,不传默认 'OK'
statusText: 'OK',
// 响应头
headers: response.header ?? {},
// 默认值:{}
headers: response.header,
// 响应数据
data: response.data,
@ -139,13 +138,12 @@ axios.defaults.adapter = (config) => {
},
fail: (error) => {
config.fail({
// 状态码,选填,不传默认 400
// 状态码
// 默认值400
status: 400,
// 状态文本,选填,不传默认 'Fail Adapter'
statusText: 'Fail Adapter',
// 响应头,选填,不传默认 {}
// 响应头
// 默认值:{}
headers: {},
// 响应数据
@ -171,12 +169,11 @@ axios.defaults.adapter = (config) => {
success: (response) => {
config.success({
// 状态码
// 默认值200
status: response.statusCode,
// 状态文本,选填,不传默认 'OK'
statusText: 'OK',
// 响应头
// 默认值:{}
headers: response.header,
// 响应数据
@ -185,13 +182,12 @@ axios.defaults.adapter = (config) => {
},
fail: (error) => {
config.fail({
// 状态码,选填,不传默认 400
// 状态码
// 默认值400
status: 400,
// 状态文本,选填,不传默认 'Fail Adapter'
statusText: 'Fail Adapter',
// 响应头,选填,不传默认 {}
// 响应头
// 默认值:{}
headers: {},
// 响应数据
@ -210,13 +206,12 @@ axios.defaults.adapter = (config) => {
success: (response) => {
config.success({
// 状态码
// 默认值200
status: response.statusCode,
// 状态文本,选填,不传默认 'OK'
statusText: 'OK',
// 响应头
headers: response.header ?? {},
// 默认值:{}
headers: response.header,
// 响应数据
data: {
@ -227,13 +222,12 @@ axios.defaults.adapter = (config) => {
},
fail: (error) => {
config.fail({
// 状态码,选填,不传默认 400
// 状态码
// 默认值400
status: 400,
// 状态文本,选填,不传默认 'Fail Adapter'
statusText: 'Fail Adapter',
// 响应头,选填,不传默认 {}
// 响应头
// 默认值:{}
headers: {},
// 响应数据
@ -270,6 +264,7 @@ import axios from 'axios-miniprogram';
axios.defaults.adapter = axios.createAdapter({
request: uni.request,
upload: (config) => {
// 其实差异只有一点点,抹平可以很轻易~
const {
// 需要上传的文件列表
// App、H5 2.6.15+

View File

@ -35,7 +35,7 @@ cancel('request canceled');
## 工厂方法
可以用 `CancelToken.source` 工厂方法创建 `CancelToken` 实例用来取消请求。
可以用 `CancelToken.source` 工厂方法创建 `CancelToken` 实例用来取消请求。
```ts
import axios from 'axios-miniprogram';
@ -57,7 +57,7 @@ cancel('request canceled');
## 判断取消请求
可以`axios.isCancel` 判断请求错误是否来自取消请求,从而做出相应的处理。
可以判断请求错误是否来自取消请求,从而做出相应的处理。
```ts
import axios from 'axios-miniprogram';
@ -70,6 +70,7 @@ axios('https://api.com/test', {
// 成功之后做些什么
})
.catch((error) => {
// 判断取消请求
if (axios.isCancel(error)) {
console.log(error, '请求已被取消');
}

View File

@ -0,0 +1,255 @@
---
title: 扩展实例
---
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
扩展新的实例,复用拦截器、中间件。
:::
## 扩展实例
可以基于 `axios` 扩展实例,配置项 `baseURL` 传相对地址时会和 `axios.defaults.baseURL` 一起组合成完整的服务端地址。
全局默认配置 `axios.defaults` 和扩展实例时传入的配置 `config` 将会按优先级[合并](/basics/defaults#配置合并策略)成实例默认配置 `instance.defaults`
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
// 相对地址会进行组合
// baseURL 最终结果为 https://api.com/user
const instance = axios.extend({
baseURL: 'user',
headers: {
common: {
['Content-Type']: 'application/json',
},
post: {
['Content-Type']: 'application/x-www-form-urlencoded',
},
},
timeout: 1000,
});
// 绝对地址会直接使用
// baseURL 最终结果为 https://api2.com/user
const instance = axios.extend({
baseURL: 'https://api2.com/user',
headers: {
common: {
['Content-Type']: 'application/json',
},
post: {
['Content-Type']: 'application/x-www-form-urlencoded',
},
},
timeout: 1000,
});
```
## 默认配置
可以设置配置项默认值。
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
const instance = axios.extend({
baseURL: 'user',
});
instance.defaults.headers.common['Content-Type'] = 'application/json';
instance.defaults.timeout = 1000;
```
## 添加拦截器
可以添加实例的[请求拦截器](/advanced/request-interceptor)和[响应拦截器](/advanced/response-interceptor)。
```ts
import axios from 'axios-miniprogram';
const instance = axios.extend({
baseURL: 'test',
});
// 请求拦截器
instance.interceptors.request.use(
function (config) {
console.log('instance request');
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
},
);
// 响应拦截器
instance.interceptors.response.use(
function (response) {
console.log('instance response');
return response;
},
function (error) {
// 在 catch 之前做些什么
return Promise.reject(error);
},
);
// instance request -> instance response
instance('/');
```
也可以复用拦截器。
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
const parent = axios.extend({
baseURL: '/parent',
});
const child = parent.extend({
baseURL: '/child',
});
// 请求拦截器
axios.interceptors.request.use(
function (config) {
console.log('axios request');
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
},
);
// 响应拦截器
axios.interceptors.response.use(
function (response) {
console.log('axios response');
return response;
},
function (error) {
// 在 catch 之前做些什么
return Promise.reject(error);
},
);
// axios request -> https://api.com/parent/child/ -> axios response
child('/');
// 请求拦截器
parent.interceptors.request.use(
function (config) {
console.log('parent request');
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
},
);
// 响应拦截器
parent.interceptors.response.use(
function (response) {
console.log('parent response');
return response;
},
function (error) {
// 在 catch 之前做些什么
return Promise.reject(error);
},
);
// axios request -> parent request -> https://api.com/parent/child/ -> parent response -> axios response
child('/');
// 请求拦截器
child.interceptors.request.use(
function (config) {
console.log('child request');
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
},
);
// 响应拦截器
child.interceptors.response.use(
function (response) {
console.log('child response');
return response;
},
function (error) {
// 在 catch 之前做些什么
return Promise.reject(error);
},
);
// axios request -> parent request -> child request -> https://api.com/parent/child/ -> child response -> parent response -> axios response
child('/');
```
## 使用
使用方式和 `axios` 完全一致。
```ts
const instance = axios.extend({
baseURL: 'https://api.com',
});
instance('test')
.then((response) => {
// 请求成功后做些什么
})
.catch((error) => {
// 请求失败后做些什么
});
instance('test', {
method: 'POST',
})
.then((response) => {
// 请求成功后做些什么
})
.catch((error) => {
// 请求失败后做些什么
});
instance({
url: 'test',
method: 'POST',
})
.then((response) => {
// 请求成功后做些什么
})
.catch((error) => {
// 请求失败后做些什么
});
```
也可以使用请求方法简化请求。
- [instance.request(url, config?) | instance.request(config)](/basics/request)
- [instance.options(url, config?)](/method/OPTIONS)
- [instance.get(url, params?, config?)](/method/GET)
- [instance.head(url, params?, config?)](/method/HEAD)
- [instance.post(url, data?, config?)](/method/POST)
- [instance.put(url, data?, config?)](/method/PUT)
- [instance.patch(url, data?, config?)](/method/PATCH)
- [instance.delete(url, params?, config?)](/method/DELETE)
- [instance.trace(url, config?)](/method/TRACE)
- [instance.connect(url, config?)](/method/CONNECT)

View File

@ -1,164 +0,0 @@
---
title: 派生领域
---
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
派生新的领域管理 `URL` 简化请求。
`defaults` 和派生 `domain` 时传入的 `config` 将会按优先级合并成 `domain.defaults`
如果 `config.baseURL` 是一个相对地址,将会和 `defaults.baseURL` 组合成完整的服务端地址。
[合并策略](/basics/defaults#合并策略)
:::
## 派生领域
可以传入 config 派生领域。
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
const domain = axios.fork({
baseURL: 'user',
headers: {
common: {
['Content-Type']: 'application/json',
},
post: {
['Content-Type']: 'application/x-www-form-urlencoded',
},
},
timeout: 1000,
});
// 请求的服务端地址 https://api.com/uesr
domain.get('/');
```
也可以使用绝对路径 `config.baseURL` 派生领域。
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
const domain = axios.fork({
baseURL: 'https://api2.com/user',
headers: {
common: {
['Content-Type']: 'application/json',
},
post: {
['Content-Type']: 'application/x-www-form-urlencoded',
},
},
timeout: 1000,
});
// 请求的服务端地址 https://api2.com/uesr
domain.get('/');
```
## 默认配置
可以设置 `domain.defaults` 属性默认值。
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
const domain = axios.fork({
baseURL: 'user',
});
domain.defaults.headers.common['Content-Type'] = 'application/json';
domain.defaults.timeout = 1000;
```
## 拦截器
基于 `axios` 派生出的 `domain`,在发送请求时会使用 `axios` 的拦截器。
基于 `instance` 派生出的 `domain`,在发送请求时会使用 `instance` 的拦截器。
目前上不支持为 `domain` 单独添加拦截器。
## 使用
可以使用请求方法发送请求。
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
const domain = axios.fork({
baseURL: 'user',
});
// 请求的服务端地址 https://api.com/uesr/1
domain
.get('/:id', {
id: 1,
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
// 请求的服务端地址 https://api.com/uesr
domain
.post('/', {
id: 1,
name: 'user',
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
// 请求的服务端地址 https://api.com/uesr/1
domain
.put('/:id', {
name: 'user',
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
// 请求的服务端地址 https://api.com/uesr/1
domain
.delete('/:id', {
id: 1,
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
```
- [domain.request(url, config?) | domain.request(config)](/basics/request)
- [domain.options(url, config?)](/method/OPTIONS)
- [domain.get(url, params?, config?)](/method/GET)
- [domain.head(url, params?, config?)](/method/HEAD)
- [domain.post(url, data?, config?)](/method/POST)
- [domain.put(url, data?, config?)](/method/PUT)
- [domain.patch(url, data?, config?)](/method/PATCH)
- [domain.delete(url, params?, config?)](/method/DELETE)
- [domain.trace(url, config?)](/method/TRACE)
- [domain.connect(url, config?)](/method/CONNECT)

View File

@ -5,22 +5,20 @@ title: 创建实例
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
创建全新的 `instance` 实例。
`defaults` 和创建 `instance` 时传入的 `config` 将会按优先级合并成 `instance.defaults`
[合并策略](/basics/defaults#合并策略)
创建新的实例。
:::
## 创建实例
可以使用 `axios.create(config)` 创建 `instance`
可以使用 `axios.create(config)` 创建新的实例。
全局默认配置 `axios.defaults` 和创建实例时传入的配置 `config` 将会按优先级[合并](/basics/defaults#配置合并策略)成实例默认配置 `instance.defaults`
```ts
import axios from 'axios-miniprogram';
const instance = axios.create({
baseURL: 'https"//api2.com',
baseURL: 'https://api2.com',
headers: {
common: {
['Content-Type']: 'application/json',
@ -35,13 +33,13 @@ const instance = axios.create({
## 默认配置
可以设置 `instance.defaults` 属性默认值。
可以设置配置项默认值。
```ts
import axios from 'axios-miniprogram';
const instance = axios.create({
baseURL: 'https"//api2.com',
baseURL: 'https://api2.com',
});
instance.defaults.headers.common['Content-Type'] = 'application/json';
@ -50,13 +48,13 @@ instance.defaults.timeout = 1000;
## 添加拦截器
可以`instance`上添加 [请求拦截器](/advanced/request-interceptor) 和 [响应拦截器](/advanced/response-interceptor)。
可以添加实例的[请求拦截器](/advanced/request-interceptor)和[响应拦截器](/advanced/response-interceptor)。
```ts
import axios from 'axios-miniprogram';
const instance = axios.create({
baseURL: 'https"//api2.com',
baseURL: 'https://api2.com',
});
// 请求拦截器
@ -84,23 +82,25 @@ instance.interceptors.response.use(
);
```
## 派生领域
## 扩展实例
可以基于 `instance` [派生领域](/advanced/fork)。
可以基于实例[扩展实例](/advanced/extend)。
实例默认配置 `parent.defaults` 和派生领域时传入的配置 `config` 将会按优先级[合并](/basics/defaults#配置合并策略)成新实例默认配置 `child.defaults`
```ts
import axios from 'axios-miniprogram';
const instance = axios.create({
baseURL: 'https"//api2.com',
const parent = axios.create({
baseURL: 'https://api2.com',
});
const domain = instance.fork({
const child = instance.extend({
baseURL: 'user',
});
// 请求的服务端地址 https://api2.com/uesr
domain.get('/');
// 请求的服务端地址 https://api2.com/user
child('/');
```
## 使用
@ -108,8 +108,10 @@ domain.get('/');
使用方式和 `axios` 完全一致。
```ts
import axios from 'axios-miniprogram';
const instance = axios.create({
baseURL: 'https"//api2.com',
baseURL: 'https://api.com',
});
instance('test')

View File

@ -0,0 +1,123 @@
---
title: 中间件
---
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
基于洋葱模型的中间件。
:::
## 前言
如果您了解或者使用过[koa](https://github.com/koajs/koa),相信您一定十分了解什么是洋葱模型,中间件该怎么写。
中间件是一个异步函数,接收 `context``next` 两个参数。
`context` 是一个对象,提供了 `req` 对象和 `res` 对象作为其组成部分。
- `context.req`:请求配置。
- `context.res`:请求完成后服务端返回的响应体,它的初始值是 `null`,请求完成之后才能对其进行操作。
`next` 是一个异步函数,如果希望程序继续执行后续逻辑,请手动调用它。
```ts
async (ctx, next) => {
// 请求发送前
const {
// 请求配置
req,
// 此时为 null
res,
} = ctx;
// 调用 next 继续执行后续逻辑,最终发送请求
await next();
// 请求完成后
const {
// 请求配置
req,
// 服务端返回的响应体
res,
} = ctx;
};
```
## 全局中间件
可以添加全局中间件,对发送的每个请求生效。
```ts
import axios from 'axios-miniprogram';
// use 会返回 this可以链式添加多个
axios
.use(async (ctx, next) => {
console.log('1');
await next();
console.log('4');
})
.use(async (ctx, next) => {
console.log('2');
await next();
console.log('3');
});
// 洋葱模型执行顺序
// 1 -> 2 -> /test -> 3 -> 4
axios('/test');
```
## 实例中间件
可以为实例添加中间件,对实例发送的每个请求生效。
```ts
import axios from 'axios-miniprogram';
const instance = axios.create({
baseURL: 'https://api.com',
});
instance.use(async (ctx, next) => {
console.log('instance request');
await next();
console.log('instance response');
});
// instance request -> https://api.com/test -> instance response
instance('https://api.com/test');
```
## 扩展实例中间件
可以为扩展实例添加中间件,扩展实例同时也可以复用父级中间件。
```ts
import axios from 'axios-miniprogram';
axios.defaults.baseURL = 'https://api.com';
axios.use(async (ctx, next) => {
console.log('axios request');
await next();
console.log('axios response');
});
const instance = axios.extend({
baseURL: '/test',
});
instance.use(async (ctx, next) => {
console.log('instance request');
await next();
console.log('instance response');
});
// 复用父级中间件
// axios request -> instance request -> https://api.com/test/user -> instance response -> axios response
instance('/user');
```

View File

@ -5,7 +5,7 @@ title: 请求拦截器
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
用于请求发前拦截请求。
用于请求发前拦截请求。
通常会用于转换请求配置,或实现一些自定义功能。
:::

View File

@ -8,9 +8,9 @@ title: 请求配置
用于自定义请求行为。
:::
## 通用属性
## 通用配置项
可以设置这些属性
可以设置这些配置项
```ts
import axios from 'axios-miniprogram';
@ -103,9 +103,9 @@ axios({
});
```
## 平台属性
## 平台配置项
也可以设置平台特有属性,具体情况取决于平台特性。
可以设置平台特有的配置项,具体情况取决于平台特性。
微信小程序示例:
@ -144,11 +144,11 @@ axios({
想要了解更多请自行参阅对应平台文档。
## 自定义属性
## 自定义配置项
也可以设置自定义属性,从而实现一些自定义功能。
可以设置自定义配置项,从而实现一些自定义功能。
自定义属性可以根据需要随意设置。
自定义配置项可以根据需要随意设置。
```ts
import axios from 'axios-miniprogram';

View File

@ -5,14 +5,14 @@ title: 默认配置
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
默认配置 `defaults` 会作用于每个请求
用于设置作用于每个请求的配置项默认值
[合并策略](/basics/defaults#合并策略)
[配置合并策略](/basics/defaults#配置合并策略)
:::
## 默认值
在不更改 `defaults` 的情况下,它依然会存在一些默认值,在 [defaults.ts](https://github.com/zjx0905/axios-miniprogram/blob/main/src/defaults.ts) 中定义,大概长下面这样。
在不更改默认配置的情况下,它依然会存在一些默认值,在 [defaults.ts](https://github.com/zjxxxxxxxxx/axios-miniprogram/blob/main/src/defaults.ts) 中定义,大概长下面这样。
```ts
{
@ -53,9 +53,9 @@ title: 默认配置
}
```
## 设置属性
## 设置配置项
可以给属性设置默认值。
可以设置配置项默认值。
列举部分示例:
@ -91,9 +91,9 @@ axios.defaults.onUploadProgress = (event) => {
};
```
## 设置平台属性
## 设置平台配置项
也可以给平台特有属性设置默认值,具体情况取决于平台特性。
可以设置平台特有配置项默认值,具体情况取决于平台特性。
微信小程序示例:
@ -121,15 +121,17 @@ axios.defaults.forceCellularNetwork = false;
想要了解更多请自行参阅对应平台文档。
## 设置自定义属性
## 设置自定义配置项
也可以给自定义属性设置默认值,从而实现一些自定义功能
可以设置自定义配置项默认值
```ts
import axios from 'axios-miniprogram';
// 出错时显示错误信息
axios.defaults.showError = true;
// 请求时自动 loading
axios.defaults.showLoading = true;
// 错误处理
axios.defaults.errorHandler = (error) => {
@ -143,9 +145,6 @@ axios.defaults.errorHandler = (error) => {
}
};
// 请求时自动 loading
axios.defaults.showLoading = true;
// 请求拦截器
axios.interceptors.request.use((config) => {
// 自动显示 loading
@ -165,10 +164,14 @@ axios.interceptors.response.use((response) => {
});
```
## 合并策略
## 配置合并策略
`defaults``config` 将会按优先级进行合并。
默认配置和请求配置将会按优先级进行合并。
其中 `url/method/data/upload/download` 只从 `config` 取值,`headers/params` 进行深度合并,其余属性则会优先从 `config` 取值。
其中
具体合并策略请参阅 [mergeConfig.ts](https://github.com/zjx0905/axios-miniprogram/blob/main/src/core/mergeConfig.ts) 。
1. `url`、`method`、`data`、`upload`、`download` 只从 `config` 取值。
2. `headers`、`params` 会分别进行深度合并。
3. 其余属性则会优先从 `config` 取值。
具体配置合并策略请参阅 [mergeConfig.ts](https://github.com/zjxxxxxxxxx/axios-miniprogram/blob/main/src/core/mergeConfig.ts) 。

View File

@ -5,7 +5,11 @@ title: 下载文件
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
下载文件资源到本地,必须使用 `GET` 方法请求,并将请求配置的 `download` 属性设置为 `true`
下载文件资源到本地。
:::
::: warning 注意
下载文件只能使用 `GET` 方法请求,并将配置项 `download` 设置为 `true`
:::
## 普通的下载请求
@ -15,19 +19,14 @@ title: 下载文件
```ts
import axios from 'axios-miniprogram';
axios
.get(
'https://api.com/test',
{},
{
download: true,
},
)
axios('https://api.com/test', {
download: true,
})
.then((response) => {
const {
// 临时文件路径 (本地路径)。没传入 filePath 指定文件存储路径时会返回,下载后的文件会存储到一个临时文件
tempFilePath,
} = response;
} = response.data;
})
.catch((error) => {
// 失败之后做些什么
@ -36,26 +35,22 @@ axios
## 携带参数的下载请求
可以指定文件下载后存储的路径 (本地路径)。
可以指定文件下载后存储的路径 (本地路径)。
```ts
import axios from 'axios-miniprogram';
axios
.get(
'https://api.com/test',
{
filePath: '你的本地路径',
},
{
download: true,
},
)
axios('https://api.com/test', {
download: true,
params: {
filePath: '你的本地路径',
},
})
.then((response) => {
const {
// 指定文件下载后存储的路径 (本地路径)
filePath,
} = response;
} = response.data;
})
.catch((error) => {
// 失败之后做些什么
@ -64,38 +59,34 @@ axios
## 监听下载进度
可以监听下载进度变化。
可以监听下载进度变化。
```ts
import axios from 'axios-miniprogram';
axios
.get(
'https://api.com/test',
{
filePath: '你的本地路径',
},
{
download: true,
onDownloadProgress(event) {
const {
// 下载进度
progress,
axios('https://api.com/test', {
download: true,
params: {
filePath: '你的本地路径',
},
onDownloadProgress(event) {
const {
// 下载进度百分比
progress,
// 已经下载的数据长度
totalBytesSent,
// 已经下载的数据长度,单位 Bytes
totalBytesWritten,
// 预期需要下载的数据总长度
totalBytesExpectedToSend,
} = event;
},
},
)
// 预预期需要下载的数据总长度,单位 Bytes
totalBytesExpectedToWrite,
} = event;
},
})
.then((response) => {
const {
// 指定文件下载后存储的路径 (本地路径)
filePath,
} = response;
} = response.data;
})
.catch((error) => {
// 失败之后做些什么

View File

@ -5,15 +5,15 @@ title: 动态地址
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
简化设置地址参数。
简化地址参数的设置方式
:::
## 设置 `params` 动态参数
## 设置请求参数
可以设置属性 `params`,最终会从 `params` 中获取到对应的值。
可以设置请求参数,最终会从请求参数中获取对应的值。
::: warning 注意
获取到值之后,会从 `params` 中删除对应的属性
获取到值后会从请求参数中删除对应的值
:::
```ts
@ -34,9 +34,9 @@ axios('https://api.com/:id', {
});
```
## 设置 `data` 动态参数
## 设置请求数据
可以设置属性 `data`,最终会从 `data` 中获取到对应的值。
可以设置请求数据,最终会从请求数据中获取对应的值。
```ts
import axios from 'axios-miniprogram';
@ -57,9 +57,9 @@ axios('https://api.com/:id', {
});
```
## 同时设置 `params``data`
## 同时设置请求参数和请求数据
可以同时设置 `params``data`,会优先从 `params` 中获取对应的值。
可以同时设置请求参数和请求数据,会优先从请求参数中获取对应的值。
```ts
import axios from 'axios-miniprogram';
@ -81,14 +81,14 @@ axios('https://api.com/:id', {
// 失败之后做些什么
});
// 请求的服务端地址 https://api.com/1/2
axios('https://api.com/:id1/:id2', {
// 请求的服务端地址 https://api.com/1/test
axios('https://api.com/:id/:name', {
method: 'POST',
params: {
id1: 1,
id: 1,
},
data: {
id2: 2,
name: 'test',
},
})
.then((response) => {

View File

@ -8,17 +8,16 @@ title: 错误处理
当请求失败时,可以对错误进行处理。
:::
## 使用 `validateStatus` 抛出错误
## 校验状态抛出错误
可以使用 `validateStatus` 自定义抛出错误的 HTTP code
可以设置校验状态,自定义抛出错误的状态码
```ts
import axios from 'axios-miniprogram';
axios('https://api.com/test', {
validateStatus(status) {
// status 小于 200 大于 299 会抛出错误
return status >= 200 && status < 300;
return status === 200;
},
})
.then((response) => {
@ -29,7 +28,7 @@ axios('https://api.com/test', {
});
```
## `catch`处理错误
## `catch` 处理错误
可以处理不同类型的错误。
@ -68,10 +67,12 @@ axios('https://api.com/test')
} else {
// 其他错误
}
return Promise.reject(error);
});
```
## 使`errorHandler` 处理错误
## 用 `errorHandler` 处理错误
可以使用 `errorHandler` 处理不同类型的错误。
@ -107,6 +108,8 @@ axios('https://api.com/test', {
} else {
// 其他错误
}
return Promise.reject(error);
},
})
.then((response) => {
@ -119,7 +122,7 @@ axios('https://api.com/test', {
## 全局错误处理
可以`errorHandler` 设置到默认配置中,每一个请求都可以进行错误处理
可以设置全局错误处理,对每个请求生效
```ts
import axios from 'axios-miniprogram';
@ -153,5 +156,7 @@ axios.defaults.errorHandler = (error) => {
} else {
// 其他错误
}
return Promise.reject(error);
};
```

View File

@ -10,10 +10,11 @@ title: 参数系列化
## 自定义参数系列化器
可以用自己的方式对参数进行系列化。
可以用自己的方式系列化参数
```ts
import axios from 'axios-miniprogram';
import qs from 'qs';
axios('https://api.com', {
params: {

View File

@ -27,7 +27,7 @@ axios
## 携带请求配置
可以传递第二个参数 `config`,用于指定请求方法以及其他配置项。
可以额外传递第二个参数 `config`,用于指定请求方法以及其他配置项。
```ts
import axios from 'axios-miniprogram';
@ -50,7 +50,7 @@ axios
## 仅有请求配置
可以忽略以上示例,直接传递 `config` 发送请求。
可以直接传递 `config` 发送请求。
```ts
import axios from 'axios-miniprogram';
@ -70,6 +70,20 @@ axios
});
```
## 请求方法
提供一系列基于 `axios.request()` 的请求方法,可以使用请求方法简化请求。
- [axios.options(url, config?)](/method/OPTIONS)
- [axios.get(url, params?, config?)](/method/GET)
- [axios.head(url, params?, config?)](/method/HEAD)
- [axios.post(url, data?, config?)](/method/POST)
- [axios.put(url, data?, config?)](/method/PUT)
- [axios.patch(url, data?, config?)](/method/PATCH)
- [axios.delete(url, params?, config?)](/method/DELETE)
- [axios.trace(url, config?)](/method/TRACE)
- [axios.connect(url, config?)](/method/CONNECT)
## 说明
您可能发现 `axios.request()``axios()` 使用方式完全一致,为什么用法是一样的?

View File

@ -44,7 +44,7 @@ axios('https//api.com')
## 平台属性
请求成功返回的 `response` 可能带有平台特有的属性,具体情况取决于平台特性。
请求成功返回的 `response` 可能带有平台特有的属性,具体情况取决于平台特性。
微信小程序示例:

View File

@ -5,7 +5,117 @@ title: 转换数据
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
支持 请求发出前转换请求数据,响应到达 `then` 之前转换响应数据。
请求发送前转换请求数据,响应到达 `then` 之前转换响应数据。
:::
未完待续...
## 转换请求数据
可以转换请求数据,只对允许携带请求数据的请求方法生效,允许携带请求数据的方法有:`POST`、`PUT`、`PATCH`。
```ts
import axios from 'axios-miniprogram';
axios('test', {
method: 'POST',
transformRequest(data, headers) {
return JSON.stringify(data);
},
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
```
也支持多次转换。
```ts
import axios from 'axios-miniprogram';
axios('test', {
method: 'POST',
transformRequest: [
(data, headers) => {
return JSON.stringify(data);
},
(data, headers) => {
return encodeURIComponent(data);
},
],
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
```
## 全局转换请求数据
可以设置全局转换请求数据,对每个请求生效。
```ts
import axios from 'axios-miniprogram';
axios.defaults.transformRequest = (data, headers) => {
return JSON.stringify(data);
};
```
## 转换响应数据
可以转换响应数据。
```ts
import axios from 'axios-miniprogram';
axios('test', {
transformResponse(data, headers) {
return JSON.parse(data);
},
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
```
也支持多次转换。
```ts
import axios from 'axios-miniprogram';
axios('test', {
transformResponse: [
(data, headers) => {
return decodeURIComponent(data);
},
(data, headers) => {
return JSON.parse(data);
},
],
})
.then((response) => {
// 成功之后做些什么
})
.catch((error) => {
// 失败之后做些什么
});
```
## 全局转换响应数据
可以设置全局转换响应数据,对每个请求生效。
```ts
import axios from 'axios-miniprogram';
axios.defaults.transformResponse = (data, headers) => {
return JSON.parse(data);
};
```

View File

@ -5,7 +5,11 @@ title: 上传文件
# {{ $frontmatter.title }}
::: tip {{ $frontmatter.title }}
将本地资源上传到服务器,必须使用 `POST` 方法请求,并将请求配置的 `upload` 属性设置为 `true`
将本地资源上传到服务器。
:::
::: warning 注意
上传文件只能使用 `POST` 方法请求,并将请求配置项 `upload` 设置为 `true`
:::
## 普通的上传请求
@ -15,20 +19,17 @@ title: 上传文件
```ts
import axios from 'axios-miniprogram';
axios
.post(
'https://api.com/test',
{
// 文件对应的 key开发者在服务端可以通过这个 key 获取文件的二进制内容
name: 'fileName',
axios('https://api.com/test', {
method: 'POST',
upload: true,
data: {
// 文件对应的 key开发者在服务端可以通过这个 key 获取文件的二进制内容
name: 'fileName',
// 要上传文件资源的路径 (本地路径)
filePath: '你的本地路径',
},
{
upload: true,
},
)
// 要上传文件资源的路径 (本地路径)
filePath: '你的本地路径',
},
})
.then((response) => {
const {
// 开发者服务器返回的数据
@ -47,26 +48,23 @@ axios
```ts
import axios from 'axios-miniprogram';
axios
.post(
'https://api.com/test',
{
// 文件对应的 key开发者在服务端可以通过这个 key 获取文件的二进制内容
name: 'fileName',
axios('https://api.com/test', {
method: 'POST',
upload: true,
data: {
// 文件对应的 key开发者在服务端可以通过这个 key 获取文件的二进制内容
name: 'fileName',
// 要上传文件资源的路径 (本地路径)
filePath: '你的本地路径',
// 要上传文件资源的路径 (本地路径)
filePath: '你的本地路径',
// 这是额外的 formData 属性
id: 1,
// 这是额外的 formData 属性
id: 1,
// 这是额外的 formData 属性
user: '123',
},
{
upload: true,
},
)
// 这是额外的 formData 属性
user: '123',
},
})
.then((response) => {
const {
// 开发者服务器返回的数据
@ -85,38 +83,35 @@ axios
```ts
import axios from 'axios-miniprogram';
axios
.post(
'https://api.com/test',
{
// 文件对应的 key开发者在服务端可以通过这个 key 获取文件的二进制内容
name: 'fileName',
axios('https://api.com/test', {
method: 'POST',
upload: true,
data: {
// 文件对应的 key开发者在服务端可以通过这个 key 获取文件的二进制内容
name: 'fileName',
// 要上传文件资源的路径 (本地路径)
filePath: '你的本地路径',
// 要上传文件资源的路径 (本地路径)
filePath: '你的本地路径',
// 这是额外的 formData 属性
id: 1,
// 这是额外的 formData 属性
id: 1,
// 这是额外的 formData 属性
user: '123',
},
{
upload: true,
onUploadProgress(event) {
const {
// 上传进度
progress,
// 这是额外的 formData 属性
user: '123',
},
onUploadProgress(event) {
const {
// 上传进度百分比
progress,
// 已经上传的数据长度
totalBytesSent,
// 已经上传的数据长度,单位 Bytes
totalBytesSent,
// 预期需要上传的数据总长度
totalBytesExpectedToSend,
} = event;
},
},
)
// 预期需要上传的数据总长度,单位 Bytes
totalBytesExpectedToSend,
} = event;
},
})
.then((response) => {
const {
// 开发者服务器返回的数据

View File

@ -9,48 +9,30 @@ title: 开始
:::: code-group
```bash [NPM]
$ npm install -D axios-miniprogram
$ npm install axios-miniprogram
```
```bash [YARN]
$ yarn add -D axios-miniprogram
$ yarn add axios-miniprogram
```
```bash [PNPM]
$ pnpm install -D axios-miniprogram
$ pnpm install axios-miniprogram
```
::::
原生小程序也可以直接[下载源码包](https://github.com/zjx0905/axios-miniprogram/releases),但是这样是失去类型提示和 `sourceMap` 定位功能。
原生小程序也可以直接[下载源码包](https://github.com/zjxxxxxxxxx/axios-miniprogram/releases),但是这样是失去类型提示和 `sourceMap` 定位功能。
建议在条件允许的情况下优先使用包管理工具安装的方式,而不是使用下载源码包的方式。
## 引用
可以在不同的模块系统导入需要用到的功能。
:::: code-group
```ts [ES Module]
import axios from 'axios-miniprogram';
axios('test');
```
```ts [CommonJS]
const axios = require('axios-miniprogram').default;
axios('test');
```
::::
## 使用
### 引用
可以导入需要使用的功能。
```ts
import axios, {
// 取消令牌
CancelToken,
@ -67,15 +49,16 @@ import axios, {
// 创建平台适配器
createAdapter,
} from 'axios-miniprogram';
axios('/test');
```
axios 上也有同样的功能。
```ts
import axios from 'axios-miniprogram';
// axios 同样也有这些功能
```ts [CommonJS]
const {
// 静态对象
// 注意:默认导出的 axios 在 CommonJS 里是以 default 属性的方式存在
default: axios,
// 取消令牌
CancelToken,
@ -90,21 +73,45 @@ const {
// 创建平台适配器
createAdapter,
} = axios;
} = require('axios-miniprogram');
axios('/test');
```
axios 上还有一些额外的功能。
::::
不同的模块系统存在一些小差异,`esm` 会自动处理默认导入,但 `cjs` 不会处理默认导入。
```ts
const {
// 创建实例
create,
// 默认导入esm 和 cjs 这两种写法是等价关系
import axios from 'axios-miniprogram';
const axios = require('axios-miniprogram').default;
// 获取已处理的 URL
getUri,
} = axios;
// 别名导入esm 和 cjs 这两种写法是等价关系
import * as axios from 'axios-miniprogram';
const axios = require('axios-miniprogram');
// 具名导入esm 和 cjs 这两种写法是等价关系
import {
default as axios,
CancelToken,
isCancel,
Axios,
isAxiosError,
createAdapter,
} from 'axios-miniprogram';
const {
default: axios,
CancelToken,
isCancel,
Axios,
isAxiosError,
createAdapter,
} = require('axios-miniprogram');
```
## 使用
### `axios(url, config?)`
可以通过把 `url``config` 传递给 `axios` 来发送请求。

View File

@ -19,7 +19,7 @@ features:
details: 包尺寸仅 10 kb不会占用您太多空间
icon: 🤌
- title: 简单易用
details: 提供了简的 API并且具有很强的可拓展性
details: 提供了简易的 API并且具有很强的可拓展性
icon: 🎯
- title: 方便快捷
details: 除了提供 npm 安装包以外,还为原生小程序提供开箱即用的源码包

11
examples/taro/.babelrc Normal file
View File

@ -0,0 +1,11 @@
{
"presets": [
[
"taro",
{
"framework": "react",
"ts": true
}
]
]
}

View File

@ -0,0 +1,2 @@
FROM node:16
RUN npm i -g pnpm

View File

@ -0,0 +1,15 @@
{
"setupTasks": [
{
"name": "Install Dependencies",
"command": "pnpm i"
}
],
"tasks": {
"dev": {
"name": "dev",
"command": "pnpm dev:h5",
"runAtStart": true
}
}
}

8
examples/taro/.eslintrc Normal file
View File

@ -0,0 +1,8 @@
{
"extends": ["taro/react"],
"rules": {
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off",
"jsx-quotes": "off"
}
}

7
examples/taro/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
dist/
deploy_versions/
.temp/
.rn_temp/
node_modules/
.DS_Store
.swc

View File

@ -0,0 +1,15 @@
import type { UserConfigExport } from '@tarojs/cli';
export default {
logger: {
quiet: false,
stats: true,
},
mini: {},
h5: {
devServer: {
port: 3000,
allowedHosts: 'all',
},
},
} satisfies UserConfigExport;

View File

@ -0,0 +1,102 @@
import { defineConfig, type UserConfigExport } from '@tarojs/cli';
import TsconfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
import devConfig from './dev';
import prodConfig from './prod';
// https://taro-docs.jd.com/docs/next/config#defineconfig-辅助函数
export default defineConfig(async (merge) => {
const baseConfig: UserConfigExport = {
projectName: 'axios',
designWidth: 750,
deviceRatio: {
640: 2.34 / 2,
750: 1,
375: 2,
828: 1.81 / 2,
},
sourceRoot: 'src',
outputRoot: `dist/${process.env.TARO_ENV}`,
plugins: [
'@tarojs/plugin-platform-alipay-dd',
'@tarojs/plugin-platform-lark',
'@tarojs/plugin-platform-kwai',
],
defineConstants: {},
copy: {
patterns: [],
options: {},
},
framework: 'react',
compiler: 'webpack5',
cache: {
enable: false, // Webpack 持久化缓存配置建议开启。默认配置请参考https://docs.taro.zone/docs/config-detail#cache
},
mini: {
postcss: {
pxtransform: {
enable: true,
config: {},
},
url: {
enable: true,
config: {
limit: 1024, // 设定转换尺寸上限
},
},
cssModules: {
enable: false, // 默认为 false如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]',
},
},
},
webpackChain(chain) {
chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin);
},
},
h5: {
publicPath: '/',
staticDirectory: 'static',
output: {
filename: 'js/[name].[hash:8].js',
chunkFilename: 'js/[name].[chunkhash:8].js',
},
miniCssExtractPluginOption: {
ignoreOrder: true,
filename: 'css/[name].[hash].css',
chunkFilename: 'css/[name].[chunkhash].css',
},
postcss: {
autoprefixer: {
enable: true,
config: {},
},
cssModules: {
enable: false, // 默认为 false如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]',
},
},
},
webpackChain(chain) {
chain.resolve.plugin('tsconfig-paths').use(TsconfigPathsPlugin);
},
},
rn: {
appName: 'taroDemo',
postcss: {
cssModules: {
enable: false, // 默认为 false如需使用 css modules 功能,则设为 true
},
},
},
};
if (process.env.NODE_ENV === 'development') {
// 本地开发构建配置(不混淆压缩)
return merge({}, baseConfig, devConfig);
}
// 生产构建配置(默认开启压缩混淆等)
return merge({}, baseConfig, prodConfig);
});

View File

@ -0,0 +1,33 @@
import type { UserConfigExport } from '@tarojs/cli';
export default {
mini: {},
h5: {
/**
* WebpackChain
* @docs https://github.com/neutrinojs/webpack-chain
*/
// webpackChain (chain) {
// /**
// * 如果 h5 端编译后体积过大,可以使用 webpack-bundle-analyzer 插件对打包体积进行分析。
// * @docs https://github.com/webpack-contrib/webpack-bundle-analyzer
// */
// chain.plugin('analyzer')
// .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
// /**
// * 如果 h5 端首屏加载时间过长,可以使用 prerender-spa-plugin 插件预加载首页。
// * @docs https://github.com/chrisvfritz/prerender-spa-plugin
// */
// const path = require('path')
// const Prerender = require('prerender-spa-plugin')
// const staticDir = path.join(__dirname, '..', 'dist')
// chain
// .plugin('prerender')
// .use(new Prerender({
// staticDir,
// routes: [ '/pages/index/index' ],
// postProcess: (context) => ({ ...context, outputPath: path.join(staticDir, 'index.html') })
// }))
// }
},
} satisfies UserConfigExport;

View File

@ -0,0 +1,79 @@
{
"private": true,
"name": "@examples/taro",
"scripts": {
"build:weapp": "taro build --type weapp",
"build:swan": "taro build --type swan",
"build:alipay": "taro build --type alipay",
"build:tt": "taro build --type tt",
"build:h5": "taro build --type h5",
"build:rn": "taro build --type rn",
"build:qq": "taro build --type qq",
"build:jd": "taro build --type jd",
"build:dd": "taro build --type dd",
"build:lark": "taro build --type lark",
"build:kwai": "taro build --type kwai",
"build:quickapp": "taro build --type quickapp",
"dev:weapp": "npm run build:weapp -- --watch",
"dev:swan": "npm run build:swan -- --watch",
"dev:alipay": "npm run build:alipay -- --watch",
"dev:tt": "npm run build:tt -- --watch",
"dev:h5": "npm run build:h5 -- --watch",
"dev:rn": "npm run build:rn -- --watch",
"dev:qq": "npm run build:qq -- --watch",
"dev:jd": "npm run build:jd -- --watch",
"dev:dd": "npm run build:dd -- --watch",
"dev:lark": "npm run build:lark -- --watch",
"dev:kwai": "npm run build:kwai -- --watch",
"dev:quickapp": "npm run build:quickapp -- --watch"
},
"dependencies": {
"@babel/core": "^7.8.0",
"@babel/runtime": "^7.21.5",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.5",
"@tarojs/cli": "3.6.13",
"@tarojs/components": "3.6.13",
"@tarojs/helper": "3.6.13",
"@tarojs/plugin-framework-react": "3.6.13",
"@tarojs/plugin-platform-alipay": "3.6.13",
"@tarojs/plugin-platform-alipay-dd": "^0.3.0",
"@tarojs/plugin-platform-h5": "3.6.13",
"@tarojs/plugin-platform-jd": "3.6.13",
"@tarojs/plugin-platform-kwai": "^6.0.0",
"@tarojs/plugin-platform-lark": "^1.1.4",
"@tarojs/plugin-platform-qq": "3.6.13",
"@tarojs/plugin-platform-swan": "3.6.13",
"@tarojs/plugin-platform-tt": "3.6.13",
"@tarojs/plugin-platform-weapp": "3.6.13",
"@tarojs/react": "3.6.13",
"@tarojs/runtime": "3.6.13",
"@tarojs/shared": "3.6.13",
"@tarojs/taro": "3.6.13",
"@tarojs/taro-loader": "3.6.13",
"@tarojs/webpack5-runner": "3.6.13",
"@types/react": "^18.0.0",
"@types/webpack-env": "^1.13.6",
"@typescript-eslint/eslint-plugin": "^6.2.0",
"@typescript-eslint/parser": "^6.2.0",
"axios-miniprogram": "latest",
"babel-preset-taro": "3.6.13",
"consola": "^3.2.3",
"eslint": "^8.12.0",
"eslint-config-taro": "3.6.13",
"eslint-plugin-import": "^2.12.0",
"eslint-plugin-react": "^7.8.2",
"eslint-plugin-react-hooks": "^4.2.0",
"postcss": "^8.4.18",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-refresh": "^0.11.0",
"stylelint": "^14.4.0",
"tsconfig-paths-webpack-plugin": "^4.0.1",
"typescript": "^5.1.0",
"webpack": "5.78.0"
},
"stackblitz": {
"installDependencies": false,
"startCommand": "pnpm i && pnpm dev:h5"
}
}

View File

@ -0,0 +1,15 @@
{
"miniprogramRoot": "./dist",
"projectname": "taro",
"description": "",
"appid": "touristappid",
"setting": {
"urlCheck": true,
"es6": false,
"enhance": false,
"compileHotReLoad": false,
"postcss": false,
"minified": false
},
"compileType": "miniprogram"
}

View File

@ -0,0 +1,10 @@
{
"miniprogramRoot": "./",
"projectname": "axios-miniprogram",
"appid": "ks739467354825138594",
"libVersion": "0.2.0",
"setting": {
"urlCheck": false
},
"compileType": "miniprogram"
}

View File

@ -0,0 +1,9 @@
{
"miniprogramRoot": "./",
"projectname": "taro",
"appid": "testAppId",
"setting": {
"es6": false,
"minified": false
}
}

View File

@ -0,0 +1,9 @@
export default defineAppConfig({
pages: ['home'],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black',
},
});

5
examples/taro/src/app.ts Normal file
View File

@ -0,0 +1,5 @@
import { PropsWithChildren } from 'react';
export default function App({ children }: PropsWithChildren<any>) {
return children;
}

View File

@ -0,0 +1,13 @@
.page {
padding: 20px;
}
.button {
margin: 20px 0;
}
.code {
padding: 20px;
overflow-x: scroll;
white-space: pre;
}

202
examples/taro/src/home.tsx Normal file
View File

@ -0,0 +1,202 @@
import { View, Button } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { useEffect, useState } from 'react';
import axios, { createAdapter } from 'axios-miniprogram';
import { consola } from 'consola';
import './home.css';
export default function Home() {
const [config, setConfig] = useState<string>('');
const [response, setResponse] = useState<string>('');
const [error, setError] = useState<string>('');
useEffect(() => {
axios.defaults.adapter = createAdapter({
request: Taro.request,
download: Taro.downloadFile,
upload: Taro.uploadFile,
} as any);
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
axios.defaults.errorHandler = (err) => {
consola.info('[debug err]', (err as any).response);
setError(`<pre>${JSON.stringify(err, null, 2)}</pre>`);
Taro.hideLoading();
Taro.showToast({
icon: 'none',
title: (err as any).response?.data?.errMsg || '未知错误',
});
return Promise.reject(err);
};
axios.use(async (ctx, next) => {
consola.info('[debug req]', ctx.req);
Taro.showLoading({
title: 'Loading...',
});
setConfig(`<pre>${JSON.stringify(ctx.req, null, 2)}</pre>`);
setError('');
setResponse('');
await next();
consola.info('[debug res]', ctx.res);
setResponse(`<pre>${JSON.stringify(ctx.res, null, 2)}</pre>`);
Taro.hideLoading();
});
}, []);
function getRequest() {
axios.get('/users/:id', {
id: 1,
});
}
function postRequest() {
axios.post('/users', {
name: 'Leanne Graham',
username: 'Bret',
email: 'Sincere@april.biz',
address: {
street: 'Kulas Light',
suite: 'Apt. 556',
city: 'Gwenborough',
zipcode: '92998-3874',
geo: { lat: '-37.3159', lng: '81.1496' },
},
phone: '1-770-736-8031 x56442',
website: 'hildegard.org',
company: {
name: 'Romaguera-Crona',
catchPhrase: 'Multi-layered client-server neural-net',
bs: 'harness real-time e-markets',
},
});
}
function putRequest() {
axios.put('/users/:id', {
id: 1,
name: 'Leanne Graham',
username: 'Bret',
email: 'Sincere@april.biz',
address: {
street: 'Kulas Light',
suite: 'Apt. 556',
city: 'Gwenborough',
zipcode: '92998-3874',
geo: { lat: '-37.3159', lng: '81.1496' },
},
phone: '1-770-736-8031 x56442',
website: 'hildegard.org',
company: {
name: 'Romaguera-Crona',
catchPhrase: 'Multi-layered client-server neural-net',
bs: 'harness real-time e-markets',
},
});
}
function deleteRequest() {
axios.delete('/users/:id', {
id: 1,
});
}
function downloadRequest() {
axios.get(
'/users/:id',
{
id: 1,
},
{
download: true,
},
);
}
function uploadRequest() {
Taro.chooseImage({
count: 1,
success({ tempFilePaths }) {
axios.post(
'/users',
{
name: 'filename',
filePath: tempFilePaths[0],
fileType: 'image',
},
{
headers: {
'Content-Type': 'multipart/form-data',
},
upload: true,
},
);
},
});
}
function errorRequest() {
axios.get('/users/:id', {
id: -1,
});
}
function failRequest() {
axios.get(
'/users',
{},
{
timeout: 0,
},
);
}
return (
<View className="page">
<Button className="button" type="primary" onClick={getRequest}>
GET
</Button>
<Button className="button" type="primary" onClick={postRequest}>
POST
</Button>
<Button className="button" type="primary" onClick={putRequest}>
PUT
</Button>
<Button className="button" type="primary" onClick={deleteRequest}>
DELETE
</Button>
<Button className="button" type="primary" onClick={downloadRequest}>
DOWNLOAD
</Button>
<Button className="button" type="primary" onClick={uploadRequest}>
UPLOAD
</Button>
<Button className="button" type="primary" onClick={errorRequest}>
ERROR
</Button>
<Button className="button" type="primary" onClick={failRequest}>
FAIL
</Button>
config:
<View
className="code"
dangerouslySetInnerHTML={{
__html: config,
}}
></View>
response:
<View
className="code"
dangerouslySetInnerHTML={{
__html: response,
}}
></View>
error:
<View
className="code"
dangerouslySetInnerHTML={{
__html: error,
}}
></View>
</View>
);
}

View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<meta name="format-detection" content="telephone=no,address=no">
<meta name="apple-mobile-web-app-status-bar-style" content="white">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
<title>taro</title>
<script><%= htmlWebpackPlugin.options.script %></script>
</head>
<body>
<div id="app"></div>
</body>
</html>

View File

@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"removeComments": false,
"preserveConstEnums": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"noImplicitAny": false,
"allowSyntheticDefaultImports": true,
"outDir": "lib",
"noUnusedLocals": true,
"noUnusedParameters": true,
"strictNullChecks": true,
"sourceMap": true,
"baseUrl": ".",
"rootDir": ".",
"jsx": "preserve",
"allowJs": true,
"resolveJsonModule": true,
"typeRoots": ["node_modules/@types"],
"paths": {
"@/*": ["src/*"]
}
},
"include": ["./src", "./types", "./config"],
"compileOnSave": false
}

36
examples/taro/types/global.d.ts vendored Normal file
View File

@ -0,0 +1,36 @@
/// <reference types="@tarojs/taro" />
declare module '*.png';
declare module '*.gif';
declare module '*.jpg';
declare module '*.jpeg';
declare module '*.svg';
declare module '*.css';
declare module '*.less';
declare module '*.scss';
declare module '*.sass';
declare module '*.styl';
declare namespace NodeJS {
interface ProcessEnv {
/** NODE 内置环境变量, 会影响到最终构建生成产物 */
NODE_ENV: 'development' | 'production';
/** 当前构建的平台 */
TARO_ENV:
| 'weapp'
| 'swan'
| 'alipay'
| 'h5'
| 'rn'
| 'tt'
| 'quickapp'
| 'qq'
| 'jd';
/**
* appid
* @description env `TARO_APP_ID`便 appid dist/project.config.json
* @see https://taro-docs.jd.com/docs/next/env-mode-config#特殊环境变量-taro_app_id
*/
TARO_APP_ID: string;
}
}

View File

@ -0,0 +1,2 @@
FROM node:16
RUN npm i -g pnpm

View File

@ -0,0 +1,15 @@
{
"setupTasks": [
{
"name": "Install Dependencies",
"command": "pnpm i"
}
],
"tasks": {
"dev": {
"name": "dev",
"command": "pnpm dev:h5",
"runAtStart": true
}
}
}

21
examples/uni-app/.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
*.local
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

View File

@ -0,0 +1,79 @@
{
"private": true,
"name": "@examples/uni-app",
"scripts": {
"dev:app": "uni -p app",
"dev:app-android": "uni -p app-android",
"dev:app-ios": "uni -p app-ios",
"dev:custom": "uni -p",
"dev:h5": "uni",
"dev:h5:ssr": "uni --ssr",
"dev:alipay": "uni -p mp-alipay",
"dev:swan": "uni -p mp-baidu",
"dev:jd": "uni -p mp-jd",
"dev:kwai": "uni -p mp-kuaishou",
"dev:lark": "uni -p mp-lark",
"dev:qq": "uni -p mp-qq",
"dev:tt": "uni -p mp-toutiao",
"dev:dd": "uni -p mp-alipay",
"dev:weapp": "uni -p mp-weixin",
"dev:xhs": "uni -p mp-xhs",
"dev:quickapp-webview": "uni -p quickapp-webview",
"dev:quickapp-webview-huawei": "uni -p quickapp-webview-huawei",
"dev:quickapp-webview-union": "uni -p quickapp-webview-union",
"build:app": "uni build -p app",
"build:app-android": "uni build -p app-android",
"build:app-ios": "uni build -p app-ios",
"build:custom": "uni build -p",
"build:h5": "uni build",
"build:h5:ssr": "uni build --ssr",
"build:alipay": "uni build -p mp-alipay",
"build:swan": "uni build -p mp-baidu",
"build:jd": "uni build -p mp-jd",
"build:kwai": "uni build -p mp-kuaishou",
"build:lark": "uni build -p mp-lark",
"build:qq": "uni build -p mp-qq",
"build:tt": "uni build -p mp-toutiao",
"build:dd": "uni -p mp-alipay",
"build:weapp": "uni build -p mp-weixin",
"build:xhs": "uni build -p mp-xhs",
"build:quickapp-webview": "uni build -p quickapp-webview",
"build:quickapp-webview-huawei": "uni build -p quickapp-webview-huawei",
"build:quickapp-webview-union": "uni build -p quickapp-webview-union"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-3080720230703001",
"@dcloudio/uni-app-plus": "3.0.0-3080720230703001",
"@dcloudio/uni-components": "3.0.0-3080720230703001",
"@dcloudio/uni-h5": "3.0.0-3080720230703001",
"@dcloudio/uni-mp-alipay": "3.0.0-3080720230703001",
"@dcloudio/uni-mp-baidu": "3.0.0-3080720230703001",
"@dcloudio/uni-mp-jd": "3.0.0-3080720230703001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-3080720230703001",
"@dcloudio/uni-mp-lark": "3.0.0-3080720230703001",
"@dcloudio/uni-mp-qq": "3.0.0-3080720230703001",
"@dcloudio/uni-mp-toutiao": "3.0.0-3080720230703001",
"@dcloudio/uni-mp-weixin": "3.0.0-3080720230703001",
"@dcloudio/uni-mp-xhs": "3.0.0-alpha-3081220230802001",
"@dcloudio/uni-quickapp-webview": "3.0.0-3080720230703001",
"axios-miniprogram": "latest",
"consola": "^2.15.3",
"vue": "^3.2.45",
"vue-i18n": "^9.1.9"
},
"devDependencies": {
"@dcloudio/types": "^3.3.2",
"@dcloudio/uni-automator": "3.0.0-3080720230703001",
"@dcloudio/uni-cli-shared": "3.0.0-3080720230703001",
"@dcloudio/uni-stacktracey": "3.0.0-3080720230703001",
"@dcloudio/vite-plugin-uni": "3.0.0-3080720230703001",
"@vue/tsconfig": "^0.1.3",
"typescript": "^4.9.4",
"vite": "4.0.4",
"vue-tsc": "^1.0.24"
},
"stackblitz": {
"installDependencies": false,
"startCommand": "pnpm i && pnpm dev:h5"
}
}

View File

@ -0,0 +1,3 @@
<template></template>
<script setup lang="ts"></script>
<style></style>

8
examples/uni-app/src/env.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
/// <reference types="vite/client" />
declare module '*.vue' {
import { DefineComponent } from 'vue';
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>;
export default component;
}

View File

@ -0,0 +1,207 @@
<script lang="ts" setup>
import { ref } from 'vue';
import axios from 'axios-miniprogram';
import consola from 'consola';
const config = ref<string>('');
const response = ref<string>('');
const error = ref<string>('');
axios.defaults.adapter = axios.createAdapter({
request: uni.request as any,
download: uni.downloadFile,
upload: uni.uploadFile as any,
});
axios.defaults.baseURL = 'https://jsonplaceholder.typicode.com';
axios.defaults.errorHandler = (err) => {
consola.info('[debug err]', (err as any).response);
error.value = `<pre>${JSON.stringify(err, null, 2)}</pre>`;
uni.hideLoading();
uni.showToast({
icon: 'none',
title: (err as any).response?.data?.errMsg || '未知错误',
});
return Promise.reject(err);
};
axios.use(async (ctx, next) => {
consola.info('[debug req]', ctx.req);
uni.showLoading({
title: 'Loading...',
});
config.value = `<pre>${JSON.stringify(ctx.req, null, 2)}</pre>`;
error.value = '';
response.value = '';
await next();
consola.info('[debug res]', ctx.res);
response.value = `<pre>${JSON.stringify(ctx.res, null, 2)}</pre>`;
uni.hideLoading();
});
function getRequest() {
axios.get('/users/:id', {
id: 1,
});
}
function postRequest() {
axios.post('/users', {
name: 'Leanne Graham',
username: 'Bret',
email: 'Sincere@april.biz',
address: {
street: 'Kulas Light',
suite: 'Apt. 556',
city: 'Gwenborough',
zipcode: '92998-3874',
geo: { lat: '-37.3159', lng: '81.1496' },
},
phone: '1-770-736-8031 x56442',
website: 'hildegard.org',
company: {
name: 'Romaguera-Crona',
catchPhrase: 'Multi-layered client-server neural-net',
bs: 'harness real-time e-markets',
},
});
}
function putRequest() {
axios.put('/users/:id', {
id: 1,
name: 'Leanne Graham',
username: 'Bret',
email: 'Sincere@april.biz',
address: {
street: 'Kulas Light',
suite: 'Apt. 556',
city: 'Gwenborough',
zipcode: '92998-3874',
geo: { lat: '-37.3159', lng: '81.1496' },
},
phone: '1-770-736-8031 x56442',
website: 'hildegard.org',
company: {
name: 'Romaguera-Crona',
catchPhrase: 'Multi-layered client-server neural-net',
bs: 'harness real-time e-markets',
},
});
}
function deleteRequest() {
axios.delete('/users/:id', {
id: 1,
});
}
function downloadRequest() {
axios.get(
'/users/:id',
{
id: 1,
},
{
download: true,
},
);
}
function uploadRequest() {
uni.chooseImage({
count: 1,
success({ tempFilePaths }) {
axios.post(
'/users',
{
name: 'filename',
filePath: tempFilePaths[0],
fileType: 'image',
},
{
headers: {
'Content-Type': 'multipart/form-data',
},
upload: true,
},
);
},
});
}
function errorRequest() {
axios.get('/users/:id', {
id: -1,
});
}
function failRequest() {
axios.get(
'/users',
{},
{
timeout: 0,
},
);
}
defineExpose({
getRequest,
postRequest,
putRequest,
deleteRequest,
config,
response,
error,
});
</script>
<template>
<view class="page">
<button class="button" type="primary" @click="getRequest">GET </button>
<button class="button" type="primary" @click="postRequest">
POST 请求
</button>
<button class="button" type="primary" @click="putRequest">PUT </button>
<button class="button" type="primary" @click="deleteRequest">
DELETE 请求
</button>
<button class="button" type="primary" @click="downloadRequest">
DOWNLOAD 请求
</button>
<button class="button" type="primary" @click="uploadRequest">
UPLOAD 请求
</button>
<button class="button" type="primary" @click="errorRequest">
ERROR 请求
</button>
<button class="button" type="primary" @click="failRequest">
FAIL 请求
</button>
config:
<view class="code" v-html="config"></view>
response:
<view class="code" v-html="response"></view>
error:
<view class="code" v-html="error"></view>
</view>
</template>
<style>
.page {
padding: 20px;
}
.button {
margin: 20px 0;
}
.code {
padding: 20px;
overflow-x: scroll;
white-space: pre;
}
</style>

View File

@ -0,0 +1,8 @@
import { createSSRApp } from 'vue';
import App from './App.vue';
export function createApp() {
const app = createSSRApp(App);
return {
app,
};
}

View File

@ -0,0 +1,72 @@
{
"name": "",
"appid": "",
"description": "",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
/* 5+App */
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
},
/* */
"modules": {},
/* */
"distribute": {
/* android */
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios": {},
/* SDK */
"sdkConfigs": {}
}
},
/* */
"quickapp": {},
/* */
"mp-weixin": {
"appid": "",
"setting": {
"urlCheck": false
},
"usingComponents": true
},
"mp-alipay": {
"usingComponents": true
},
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics": {
"enable": false
},
"vueVersion": "3"
}

View File

@ -0,0 +1,9 @@
{
"pages": [{ "path": "home", "style": {} }],
"globalStyle": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "axios-miniprogram",
"navigationBarTextStyle": "black"
}
}

6
examples/uni-app/src/shime-uni.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
export {};
declare module 'vue' {
type Hooks = App.AppInstance & Page.PageInstance;
type ComponentCustomOptions = Hooks;
}

View File

@ -0,0 +1,13 @@
{
"extends": "@vue/tsconfig/tsconfig.json",
"compilerOptions": {
"sourceMap": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"lib": ["esnext", "dom"],
"types": ["@dcloudio/types"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}

View File

@ -0,0 +1,10 @@
import { defineConfig } from 'vite';
import uni from '@dcloudio/vite-plugin-uni';
// https://vitejs.dev/config/
export default defineConfig({
server: {
port: 3000,
},
plugins: [uni()],
});

View File

@ -1,4 +1,3 @@
declare const uni: any;
declare const wx: any;
declare const my: any;
declare const swan: any;
@ -8,3 +7,4 @@ declare const qh: any;
declare const ks: any;
declare const dd: any;
declare const jd: any;
declare const xhs: any;

View File

@ -1,36 +1,43 @@
{
"name": "axios-miniprogram",
"version": "2.3.0",
"version": "2.7.2",
"description": "基于 Promise 的 HTTP 请求库,适用于各大小程序平台。",
"main": "dist/axios-miniprogram.cjs.js",
"module": "dist/axios-miniprogram.esm.js",
"types": "dist/axios-miniprogram.d.ts",
"type": "module",
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "git+https://github.com/zjx0905/axios-miniprogram.git"
"url": "git+https://github.com/zjxxxxxxxxx/axios-miniprogram.git"
},
"keywords": [
"axios",
"request",
"wechat",
"miniprogram",
"uni-app"
"mini",
"miniprogram"
],
"author": "zjx0905 <954270063@qq.com>",
"author": "zjxxxxxxxxx <954270063@qq.com>",
"bugs": {
"url": "https://github.com/zjx0905/axios-miniprogram/issues"
"url": "https://github.com/zjxxxxxxxxx/axios-miniprogram/issues"
},
"homepage": "https://axios-miniprogram.com",
"license": "MIT",
"type": "module",
"engines": {
"node": ">=16",
"pnpm": ">=8"
},
"scripts": {
"cz": "simple-git-hooks && czg",
"play": "esno scripts/play.ts",
"typecheck": "tsc --noEmit",
"lint": "eslint --cache . --fix",
"format": "prettier -w {src,test,scripts}/**/*.{ts,tsx,js,jsx}",
"build": "esno scripts/build.ts",
"build:assets": "esno scripts/build.assets.ts",
"watch": "pnpm build -a -w",
"dev": "pnpm build -a -w",
"release": "esno scripts/release.ts",
"publish:ci": "esno scripts/publish.ts",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
@ -38,44 +45,43 @@
"test": "vitest run",
"test:watch": "vitest",
"test:cov": "vitest run --coverage",
"typecheck": "tsc --noEmit",
"lint": "eslint --cache .",
"lint:fix": "pnpm lint --fix",
"docs:dev": "pnpm -C docs dev",
"docs:build": "pnpm -C docs build",
"docs:preview": "pnpm -C docs preview",
"docs:dev": "pnpm --filter docs dev",
"docs:build": "pnpm --filter docs build",
"docs:preview": "pnpm --filter docs preview",
"docs:deploy": "esno scripts/docs.deploy.ts"
},
"devDependencies": {
"@commitlint/cli": "^17.4.4",
"@commitlint/config-conventional": "^17.4.4",
"@rollup/plugin-typescript": "^11.1.0",
"@types/node": "^18.15.5",
"@typescript-eslint/eslint-plugin": "^5.55.0",
"@typescript-eslint/parser": "^5.55.0",
"@vitest/coverage-istanbul": "^0.30.0",
"chalk": "^5.2.0",
"@commitlint/cli": "^17.7.1",
"@commitlint/config-conventional": "^17.7.0",
"@rollup/plugin-typescript": "^11.1.2",
"@types/minimist": "^1.2.2",
"@types/node": "^18.17.5",
"@types/semver": "^7.5.0",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@vitest/coverage-istanbul": "^0.30.1",
"chalk": "^5.3.0",
"consola": "^2.15.3",
"conventional-changelog-cli": "^2.2.2",
"cz-git": "1.3.8",
"czg": "1.3.8",
"enquirer": "^2.3.6",
"eslint": "^8.36.0",
"enquirer": "^2.4.1",
"eslint": "^8.47.0",
"esno": "^0.16.3",
"fast-glob": "^3.2.12",
"fast-glob": "^3.3.1",
"jszip": "^3.10.1",
"lint-staged": "13.2.0",
"minimist": "^1.2.8",
"prettier": "2.8.5",
"rimraf": "^4.4.0",
"rollup": "^3.20.0",
"rollup-plugin-dts": "^5.3.0",
"rimraf": "^4.4.1",
"rollup": "^3.28.0",
"rollup-plugin-dts": "^5.3.1",
"rollup-plugin-esbuild": "^5.0.0",
"semver": "^7.3.8",
"simple-git-hooks": "^2.8.1",
"tslib": "^2.5.0",
"typescript": "^5.0.2",
"vitest": "^0.30.0"
"semver": "^7.5.4",
"simple-git-hooks": "^2.9.0",
"tslib": "^2.6.1",
"typescript": "^5.1.6",
"vitest": "^0.30.1"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged && pnpm test && pnpm build -a",
@ -90,7 +96,7 @@
"*.{js,json}": [
"prettier --write"
],
"*.ts?(x)": [
"*.ts": [
"eslint",
"prettier --parser=typescript --write"
]
@ -100,7 +106,8 @@
"ignoreMissing": [
"@algolia/client-search",
"esbuild",
"vite"
"vite",
"eslint"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +1,3 @@
packages:
- docs
- examples/*

View File

@ -1,31 +1,35 @@
import fs from 'node:fs';
import { basename } from 'node:path';
import fg from 'fast-glob';
import JSZip from 'jszip';
import consola from 'consola';
import chalk from 'chalk';
import { distPath, exec, getFileName } from './utils';
import { distPath, exec } from './utils';
import { checkSize } from './checkSize';
main();
async function main() {
exec('pnpm build');
console.log('');
consola.info('Generate assets\n');
for (const filePath of await fg(`${distPath}/**.js`)) {
await generateZip(filePath, filePath.replace(/\.js$/, '.zip'));
}
checkSize(`${distPath}/**.zip`);
}
function generateZip(inputPath: string, outputPath: string) {
const start = Date.now();
const inputName = getFileName(inputPath);
const outputName = getFileName(outputPath);
const inputName = basename(inputPath);
const outputName = basename(outputPath);
console.log(chalk.cyanBright.bold(`${inputPath} → dist/${outputName}...`));
return new Promise((resolve, reject) => {
const finish = (result) => {
const finish = (result: any) => {
console.log(
`${chalk.green('created')} ${chalk.greenBright.bold(
`dist/${outputName} in ${Date.now() - start}ms\n`,

View File

@ -1,6 +1,9 @@
import minimist from 'minimist';
import consola from 'consola';
import { exec } from './utils';
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);
@ -14,15 +17,17 @@ function main() {
exec('rimraf dist');
consola.info('Rollup');
try {
safeExit(() => {
exec(
`rollup -c rollup.config.ts --configPlugin typescript ${
watch ? '-w' : ''
} --environment SOURCE_MAP:${sourceMap},DTS:${dts}`,
);
} catch {
consola.error('已退出');
process.exit();
});
if (!watch) {
checkSize(`${distPath}/**.js`);
}
console.info('\n');

20
scripts/checkSize.ts Normal file
View File

@ -0,0 +1,20 @@
import { readFileSync } from 'node:fs';
import { gzipSync } from 'node:zlib';
import { basename } from 'node:path';
import fg from 'fast-glob';
import chalk from 'chalk';
export async function checkSize(source: string) {
for (const filePath of await fg(source)) {
const file = readFileSync(filePath);
const minSize = (file.length / 1024).toFixed(2) + 'kb';
const gzipped = gzipSync(file);
const gzippedSize = (gzipped.length / 1024).toFixed(2) + 'kb';
console.log(
`${chalk.gray(
chalk.bold(basename(filePath)),
)} min:${minSize} / gzip:${gzippedSize}`,
);
}
}

48
scripts/play.ts Normal file
View File

@ -0,0 +1,48 @@
import enquirer from 'enquirer';
import consola from 'consola';
import { exec, resolve, safeExit } from './utils';
import { readdirSync } from 'fs';
safeExit(main);
async function main() {
const { framework } = await enquirer.prompt<{ framework: string }>({
type: 'select',
name: 'framework',
message: '请选择跨端框架',
choices: readdirSync(resolve('examples')).filter((i) => i !== '.DS_Store'),
});
const metas = framework === 'taro' ? taroMetas() : uniAppMetas();
const { platform } = await enquirer.prompt<{ platform: string }>({
type: 'select',
name: 'platform',
message: '请选择启动平台',
choices: metas,
});
console.log();
consola.info(
`启动${metas.find((meta) => meta.name === platform)!.message}...`,
);
exec(`pnpm --filter @examples/${framework} dev:${platform}`);
}
function taroMetas() {
return [
{ name: 'h5', message: 'H5' },
{ 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: '快手小程序' },
];
}
function uniAppMetas() {
return [...taroMetas(), { name: 'xhs', message: '小红书小程序' }];
}

View File

@ -22,7 +22,7 @@ function main() {
}
function generatePublishPkg() {
const publishPkg = {};
const publishPkg: AnyObject = {};
[
'name',

View File

@ -1,10 +1,11 @@
import fs from 'node:fs';
import semver from 'semver';
import { writeFileSync } from 'node:fs';
import semver, { ReleaseType } from 'semver';
import enquirer from 'enquirer';
import consola from 'consola';
import { exec, pkgPath, getPkgJSON } from './utils';
import { exec, pkgPath, getPkgJSON, resolve } from './utils';
const pkg = getPkgJSON();
const versionTSPath = resolve('src/version.ts');
const { version: currentVersion } = pkg;
main().catch((err) => exit(err.message));
@ -26,10 +27,10 @@ async function main() {
exec(`git tag -a v${version} -m "v${version}"`);
consola.info('Git push');
exec('git push');
exec('git push -f');
consola.info('Git push tag');
exec(`git push origin v${version}`);
exec(`git push -f origin v${version}`);
}
function checkBranch() {
@ -102,7 +103,9 @@ function createReleases() {
];
const releases: string[] = [];
for (const [type, preid] of types) {
releases.push(`${type} (${semver.inc(currentVersion, type, preid)})`);
releases.push(
`${type} (${semver.inc(currentVersion, type as ReleaseType, preid)})`,
);
}
return releases;
}
@ -115,5 +118,7 @@ function exit(msg: string) {
function updateVersion(version: string) {
pkg.version = version;
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
writeFileSync(versionTSPath, `export const version = '${version}';`);
}

View File

@ -5,7 +5,7 @@ import { getPkgJSON, resolve } from './utils';
const changelogPath = resolve('CHANGELOG.md');
const releaselogPath = resolve('RELEASELOG.md');
const { version } = getPkgJSON();
const versionRE = new RegExp(`^# \\[?${version}\\]?[ (]`);
const versionRE = new RegExp(`^#{1,2} \\[?${version}\\]?\\(?`);
main();
@ -17,7 +17,7 @@ async function main() {
let releaselog = '';
for await (const line of changelog) {
if (line.startsWith('# ') && !versionRE.test(line)) {
if (/^#{1,2} /.test(line) && !versionRE.test(line)) {
break;
}
releaselog += `${line}\n`;

View File

@ -1,4 +1,10 @@
import { AxiosAdapterRequestConfig } from 'src';
import { test } from 'vitest';
import {
PLAIN_METHODS,
WITH_PARAMS_METHODS,
WITH_DATA_METHODS,
} from '@/constants/methods';
import { AxiosAdapterRequestConfig } from '@/adpater/createAdapter';
export function asyncNext() {
return Promise.resolve().then;
@ -17,26 +23,17 @@ export function captureError<T = any>(fn: () => void) {
}
}
export function checkStack(error: Error) {
if (error.stack) {
return error.stack.indexOf('at') === error.stack.indexOf('at /');
}
return true;
}
export function noop() {
return;
}
export function mockResponse(
status: number,
statusText: string,
headers: AnyObject,
data: AnyObject,
status = 200,
headers: AnyObject = {},
data: AnyObject = {},
) {
return {
status,
statusText,
headers,
data,
};
@ -73,13 +70,13 @@ function mockAdapterBase(
if (!canceled) {
switch (type) {
case 'success':
config.success(mockResponse(200, 'OK', headers, data));
config.success(mockResponse(200, headers, data));
break;
case 'error':
config.success(mockResponse(500, 'ERROR', headers, data));
config.success(mockResponse(500, headers, data));
break;
case 'fail':
config.fail(mockResponse(400, 'FAIL', headers, data));
config.fail(mockResponse(400, headers, data));
break;
}
@ -106,3 +103,15 @@ export function mockAdapterError(options: MockAdapterOptions = {}) {
export function mockAdapterFail(options: MockAdapterOptions = {}) {
return mockAdapterBase('fail', options);
}
export const methods = [
...PLAIN_METHODS,
...WITH_PARAMS_METHODS,
...WITH_DATA_METHODS,
];
export const testEachMethods = test.each(methods);
export function eachMethods(cb: (k: (typeof methods)[number]) => void) {
methods.forEach(cb);
}

View File

@ -1,7 +1,9 @@
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);
@ -20,5 +22,19 @@ export const exec = (command: string, options: ExecSyncOptions = {}) =>
export const getPkgJSON = () => require(pkgPath);
export const getFileName = (filePath: string) =>
filePath.match(/\/([^/]*)$/)![1];
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,15 +1,11 @@
import { isFunction, isPlainObject } from '../helpers/types';
import { assert } from '../helpers/error';
import { ignore, orgIgnore } from '../helpers/ignore';
import {
isFunction,
isPlainObject,
isString,
isUndefined,
} from './helpers/isTypes';
import { assert } from './helpers/error';
import {
AxiosProgressCallback,
AxiosProgressEvent,
AxiosRequestFormData,
AxiosRequestHeaders,
} from './core/Axios';
} from '../core/Axios';
/**
*
@ -48,10 +44,6 @@ export interface AxiosAdapterResponse extends AnyObject {
*
*/
status?: number;
/**
*
*/
statusText?: string;
/**
*
*/
@ -70,10 +62,6 @@ export interface AxiosAdapterResponseError extends AnyObject {
*
*/
status?: number;
/**
*
*/
statusText?: string;
/**
*
*/
@ -115,11 +103,11 @@ export interface AxiosAdapterRequestConfig extends AnyObject {
/**
*
*/
dataType?: 'json' | '其他';
dataType?: string;
/**
*
*/
responseType?: 'text' | 'arraybuffer';
responseType?: string;
/**
* 60000
*/
@ -138,9 +126,18 @@ export interface AxiosAdapterRequestConfig extends AnyObject {
*
*/
export interface AxiosAdapterBaseOptions extends AxiosAdapterRequestConfig {
/**
* headers
*/
header?: AxiosRequestHeaders;
success(response: AxiosAdapterResponse): void;
fail(error: AxiosAdapterResponseError): void;
/**
*
*/
success(response: AnyObject): void;
/**
*
*/
fail(error: AnyObject): void;
}
/**
@ -152,6 +149,9 @@ export type AxiosAdapterRequestOptions = AxiosAdapterBaseOptions;
*
*/
export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions {
/**
*
*/
filePath?: string;
}
@ -161,7 +161,17 @@ export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions {
export interface AxiosAdapterUploadOptions
extends AxiosAdapterBaseOptions,
AxiosRequestFormData {
/**
* [ fileName name](https://open.dingtalk.com/document/orgapp/dd-upload-objects#title-ngk-rr1-eow)
*/
fileName: string;
/**
* |
*/
fileType?: 'image' | 'video' | 'audie';
/**
*
*/
formData?: AnyObject;
}
@ -212,8 +222,8 @@ export type AxiosAdapterPlatformTask =
| void
| {
abort?(): void;
onProgressUpdate?(callback: AxiosProgressCallback): void;
offProgressUpdate?(callback: AxiosProgressCallback): void;
onProgressUpdate?(callback: (event: AxiosProgressEvent) => void): void;
offProgressUpdate?(callback: (event: AxiosProgressEvent) => void): void;
};
/**
@ -223,59 +233,6 @@ export interface AxiosAdapter {
(config: AxiosAdapterRequestConfig): AxiosAdapterPlatformTask;
}
/**
*
*/
export function getDefaultAdapter() {
const platform = revisePlatformApiNames(getPlatform());
function getPlatform() {
const undef = 'undefined';
if (typeof uni !== undef) {
return {
request: uni.request,
downloadFile: uni.downloadFile,
uploadFile: uni.uploadFile,
};
} else if (typeof wx !== undef) {
return wx;
} else if (typeof my !== undef) {
return my;
} else if (typeof swan !== undef) {
return swan;
} else if (typeof tt !== undef) {
return tt;
} else if (typeof qq !== undef) {
return qq;
} else if (typeof qh !== undef) {
return qh;
} else if (typeof ks !== undef) {
return ks;
} else if (typeof dd !== undef) {
return dd;
} else if (typeof jd !== undef) {
return jd;
}
}
function revisePlatformApiNames(platform?: AnyObject) {
return (
platform && {
request: platform.request ?? platform.httpRequest,
upload: platform.upload ?? platform.uploadFile,
download: platform.download ?? platform.downloadFile,
}
);
}
if (!isPlatform(platform)) {
return;
}
return createAdapter(platform);
}
/**
*
*
@ -290,132 +247,148 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
function adapter(
config: AxiosAdapterRequestConfig,
): AxiosAdapterPlatformTask {
const baseOptions = transformOptions(config);
const options = transformOptions(config);
switch (config.type) {
case 'request':
return processRequest(platform.request, baseOptions);
return processRequest(platform.request, options);
case 'download':
return processDownload(platform.download, baseOptions);
return processDownload(platform.download, options);
case 'upload':
return processUpload(platform.upload, baseOptions);
return processUpload(platform.upload, options);
}
}
function processRequest(
request: AxiosAdapterRequest,
baseOptions: AxiosAdapterBaseOptions,
): AxiosAdapterPlatformTask {
return request(baseOptions);
}
function processUpload(
upload: AxiosAdapterUpload,
baseOptions: AxiosAdapterBaseOptions,
): AxiosAdapterPlatformTask {
const { name, filePath, fileType, ...formData } =
baseOptions.data as AxiosRequestFormData;
const options = {
...baseOptions,
name,
/**
* [ fileName name](https://open.dingtalk.com/document/orgapp/dd-upload-objects#title-ngk-rr1-eow)
*/
fileName: name,
filePath,
/**
* |
*/
fileType,
formData,
};
return upload(options);
}
function processDownload(
download: AxiosAdapterDownload,
baseOptions: AxiosAdapterBaseOptions,
): AxiosAdapterPlatformTask {
const options: AxiosAdapterDownloadOptions = {
...baseOptions,
filePath: baseOptions.params?.filePath,
success(response): void {
injectDownloadData(response);
baseOptions.success(response);
},
};
return download(options);
}
function transformResponse(response: AnyObject): void {
response.status = response.status ?? response.statusCode;
response.statusText = 'OK';
if (isUndefined(response.status)) {
response.status = 400;
response.statusText = 'Fail Adapter';
}
response.headers = response.headers ?? response.header ?? {};
if (isUndefined(response.data) && isString(response.errMsg)) {
response.data = {
errMsg: response.errMsg,
errno: response.errno,
};
}
cleanResponse(response, ['statusCode', 'errMsg', 'errno', 'header']);
}
function transformOptions(
config: AxiosAdapterRequestConfig,
): AxiosAdapterBaseOptions {
const { success, fail } = config;
return {
...config,
header: config.headers,
success(response): void {
transformResponse(response);
config.success(response);
success(rawRes: AxiosAdapterResponse) {
const response = transformResponse(rawRes) as AxiosAdapterResponse;
success(response);
},
fail(error: AxiosAdapterResponseError): void {
transformResponse(error);
config.fail(error);
fail(rawErr: AxiosAdapterResponseError) {
const responseError = {
...transformResponse(rawErr),
data: {
errno:
// 微信 | 飞书新规范
rawErr.errno ??
// 支付宝 | 钉钉
rawErr.error ??
// 百度 | 360 | 飞书
rawErr.errCode ??
// 抖音
rawErr.errNo,
errMsg:
// 飞书新规范
rawErr.errString ??
// 微信 | 支付宝 | 百度 | 抖音 | QQ | 360 | 飞书
rawErr.errMsg ??
// 钉钉
rawErr.errorMessage,
},
};
fail(responseError);
},
};
}
function injectDownloadData(response: AnyObject): void {
response.data = {
filePath: response.filePath,
tempFilePath:
response.tempFilePath ||
// response.apFilePath 为支付宝小程序基础库小于 2.7.23 的特有属性。
response.apFilePath,
};
function transformResponse(
rawRes: AxiosAdapterResponse | AxiosAdapterResponseError,
) {
return {
...ignore(
rawRes,
'statusCode',
'header',
cleanResponse(response, ['tempFilePath', 'apFilePath', 'filePath']);
// 错误码
'errno',
'error',
'errCode',
'errNo',
// 错误消息
'errMsg',
'errorMessage',
'errString',
),
status: rawRes.status ?? rawRes.statusCode,
headers: rawRes.headers ?? rawRes.header,
};
}
/**
* response key
*/
function cleanResponse(response: AnyObject, keys: string[]) {
for (const key of keys) {
delete response[key];
}
function processRequest(
request: AxiosAdapterRequest,
rawOpts: AxiosAdapterBaseOptions,
): AxiosAdapterPlatformTask {
return request(rawOpts);
}
function processDownload(
download: AxiosAdapterDownload,
rawOpts: AxiosAdapterBaseOptions,
): AxiosAdapterPlatformTask {
const options = rawOpts as AxiosAdapterDownloadOptions;
const { params, success } = options;
options.filePath = params?.filePath;
options.success = (rawRes) => {
const response = {
...ignore(rawRes, 'tempFilePath', 'apFilePath', 'filePath', 'fileSize'),
data: {
filePath: rawRes.filePath,
tempFilePath:
rawRes.tempFilePath ??
// 支付宝
rawRes.apFilePath,
fileSize:
// 飞书
rawRes.fileSize,
},
};
success(response);
};
orgIgnore(options, ['params']);
return download(options);
}
function processUpload(
upload: AxiosAdapterUpload,
rawOpts: AxiosAdapterBaseOptions,
): AxiosAdapterPlatformTask {
const options = rawOpts as AxiosAdapterUploadOptions;
const { data, success } = options;
const { name, filePath, fileType, ...formData } = data as AnyObject;
options.name = name;
options.filePath = filePath;
options.formData = formData;
// 支付宝 | 钉钉
options.fileName = name;
// 支付宝 | 钉钉
options.fileType = fileType;
options.success = (rawRes) => {
const response = { ...rawRes };
if (options.responseType === 'text' && options.dataType === 'json') {
try {
response.data = JSON.parse(rawRes.data);
} catch {
//
}
}
success(response);
};
orgIgnore(options, ['params', 'data']);
return upload(options);
}
return adapter;
}
export function isPlatform(value: any): value is AxiosAdapterPlatform {
return (
isPlainObject(value) &&
isFunction(value.request) &&
isFunction(value.upload) &&
isFunction(value.download)
);
}

View File

@ -0,0 +1,76 @@
import { isFunction, isPlainObject } from '../helpers/types';
import { AxiosAdapterPlatform, createAdapter } from './createAdapter';
/**
*
*/
export function getDefaultAdapter() {
const platform = revisePlatformApiNames(getPlatform());
if (isPlatform(platform)) {
return createAdapter(platform);
}
}
function getPlatform() {
const undef = 'undefined';
// 微信小程序
if (typeof wx !== undef) {
return wx;
}
// 支付宝小程序
else if (typeof my !== undef) {
return my;
}
// 百度小程序
else if (typeof swan !== undef) {
return swan;
}
// 抖音小程序 | 飞书小程序
else if (typeof tt !== undef) {
return tt;
}
// QQ 小程序
else if (typeof qq !== undef) {
return qq;
}
// 360 小程序
else if (typeof qh !== undef) {
return qh;
}
// 快手小程序
else if (typeof ks !== undef) {
return ks;
}
// 钉钉小程序
else if (typeof dd !== undef) {
return dd;
}
// 京东小程序
else if (typeof jd !== undef) {
return jd;
}
// 小红书小程序
else if (typeof xhs !== undef) {
return xhs;
}
}
function revisePlatformApiNames(platform?: AnyObject) {
if (platform) {
return {
request: platform.request ?? platform.httpRequest,
upload: platform.upload ?? platform.uploadFile,
download: platform.download ?? platform.downloadFile,
};
}
}
function isPlatform(value: any): value is AxiosAdapterPlatform {
return (
isPlainObject(value) &&
isFunction(value.request) &&
isFunction(value.upload) &&
isFunction(value.download)
);
}

View File

@ -1,39 +1,23 @@
import { AxiosDomainRequest } from './core/AxiosDomain';
import Axios, {
AxiosConstructor,
AxiosRequestConfig,
AxiosRequestHeaders,
} from './core/Axios';
import { CancelToken, CancelTokenConstructor, isCancel } from './core/cancel';
import { isAxiosError } from './core/createError';
import { mergeConfig } from './core/mergeConfig';
import { createAdapter } from './adapter';
import {
CancelToken,
CancelTokenConstructor,
isCancel,
} from './request/cancel';
import { isAxiosError } from './request/createError';
import Axios, { AxiosConstructor } from './core/Axios';
import { AxiosInstance, createInstance } from './core/createInstance';
import { createAdapter } from './adpater/createAdapter';
import defaults from './defaults';
/**
* axios
*/
export interface AxiosInstanceDefaults extends AxiosRequestConfig {
/**
*
*/
headers: Required<AxiosRequestHeaders>;
}
/**
* axios
*/
export interface AxiosInstance extends AxiosDomainRequest, Axios {
/**
*
*/
defaults: AxiosInstanceDefaults;
}
import { version } from './version';
/**
* axios
*/
export interface AxiosStatic extends AxiosInstance {
/**
*
*/
version: string;
/**
* Axios
*/
@ -42,12 +26,6 @@ export interface AxiosStatic extends AxiosInstance {
*
*/
CancelToken: CancelTokenConstructor;
/**
* axios
*
* @param defaults
*/
create(defaults?: AxiosRequestConfig): AxiosInstance;
/**
*
*/
@ -62,22 +40,8 @@ export interface AxiosStatic extends AxiosInstance {
isAxiosError: typeof isAxiosError;
}
function createInstance(defaults: AxiosRequestConfig) {
const context = new Axios(defaults);
const instance = context.request as AxiosInstance;
Object.assign(instance, context);
Object.setPrototypeOf(instance, Axios.prototype);
return instance;
}
const axios = createInstance(defaults) as AxiosStatic;
axios.create = function create(defaults) {
return createInstance(mergeConfig(axios.defaults, defaults));
};
axios.version = version;
axios.Axios = Axios;
axios.CancelToken = CancelToken;
axios.createAdapter = createAdapter;

22
src/constants/methods.ts Normal file
View File

@ -0,0 +1,22 @@
/**
*
*/
export const PLAIN_METHODS = ['options', 'trace', 'connect'] as const;
/**
*
*/
export const WITH_PARAMS_METHODS = ['head', 'get', 'delete'] as const;
/**
*
*/
export const WITH_DATA_METHODS = ['post', 'put', 'patch'] as const;
/**
* data
*/
export const WITH_DATA_RE = new RegExp(
`^(${WITH_DATA_METHODS.join('|')})`,
'i',
);

View File

@ -1,20 +1,29 @@
import { buildURL } from '../helpers/buildURL';
import { isAbsoluteURL } from '../helpers/isAbsoluteURL';
import { combineURL } from '../helpers/combineURL';
import { isFunction, isPromise, isString } from '../helpers/isTypes';
import {
PLAIN_METHODS,
WITH_DATA_METHODS,
WITH_PARAMS_METHODS,
} from '../constants/methods';
import { isString } from '../helpers/types';
import { dispatchRequest } from '../request/dispatchRequest';
import { CancelToken } from '../request/cancel';
import { AxiosTransformer } from '../request/transformData';
import { deepMerge } from '../helpers/deepMerge';
import {
AxiosAdapter,
AxiosAdapterRequestMethod,
AxiosAdapterPlatformTask,
AxiosAdapterRequestConfig,
AxiosAdapterResponseData,
} from '../adapter';
import InterceptorManager, { Interceptor } from './InterceptorManager';
} from '../adpater/createAdapter';
import InterceptorManager, {
Interceptor,
InterceptorExecutor,
} from './InterceptorManager';
import MiddlewareManager, {
MiddlewareCallback,
MiddlewareContext,
} from './MiddlewareManager';
import { mergeConfig } from './mergeConfig';
import { CancelToken } from './cancel';
import { dispatchRequest } from './dispatchRequest';
import { AxiosTransformer } from './transformData';
import AxiosDomain from './AxiosDomain';
/**
*
@ -99,36 +108,58 @@ export type AxiosRequestData =
/**
*
*/
export type AxiosResponseData = undefined | number | AxiosAdapterResponseData;
export type AxiosResponseData = number | AxiosAdapterResponseData;
/**
*
*
*/
export interface AxiosProgressEvent {
export interface AxiosProgressEvent extends AnyObject {
/**
*
*
*/
progress: number;
}
/**
*
*/
export interface AxiosDownloadProgressEvent extends AxiosProgressEvent {
/**
*
* Bytes
*/
totalBytesWritten: number;
/**
* Bytes
*/
totalBytesExpectedToWrite: number;
}
/**
*
*/
export interface AxiosDownloadProgressCallback {
(event: AxiosDownloadProgressEvent): void;
}
/**
*
*/
export interface AxiosUploadProgressEvent extends AxiosProgressEvent {
/**
* Bytes
*/
totalBytesSent: number;
/**
*
* Bytes
*/
totalBytesExpectedToSend: number;
}
/**
*
*
*/
export interface AxiosProgressCallback {
(
/**
*
*/
event: AxiosProgressEvent,
): void;
export interface AxiosUploadProgressCallback {
(event: AxiosUploadProgressEvent): void;
}
/**
@ -171,13 +202,21 @@ export interface AxiosRequestConfig
*/
cancelToken?: CancelToken;
/**
*
*
*/
download?: boolean;
/**
*
*/
upload?: boolean;
/**
*
*
*/
download?: boolean;
paramsSerializer?: (params?: AnyObject) => string;
/**
*
*/
validateStatus?: (status: number) => boolean;
/**
*
*/
@ -189,23 +228,15 @@ export interface AxiosRequestConfig
/**
*
*/
errorHandler?: (error: unknown) => Promise<void> | void;
/**
*
*/
onUploadProgress?: AxiosProgressCallback;
errorHandler?: (error: unknown) => Promise<AxiosResponse>;
/**
*
*/
onDownloadProgress?: AxiosProgressCallback;
onDownloadProgress?: AxiosUploadProgressCallback;
/**
*
*
*/
paramsSerializer?: (params?: AnyObject) => string;
/**
*
*/
validateStatus?: (status: number) => boolean;
onUploadProgress?: AxiosUploadProgressCallback;
}
/**
@ -259,7 +290,7 @@ export interface AxiosResponseError extends AnyObject {
/**
*
*/
data?: AnyObject;
data: AnyObject;
/**
*
*/
@ -274,6 +305,46 @@ export interface AxiosResponseError extends AnyObject {
request?: AxiosAdapterPlatformTask;
}
export interface AxiosRequest {
<TData extends AxiosResponseData>(config: AxiosRequestConfig): Promise<
AxiosResponse<TData>
>;
<TData extends AxiosResponseData>(
url: string,
config?: AxiosRequestConfig,
): Promise<AxiosResponse<TData>>;
}
/**
*
*/
export type AxiosRequestMethodFn = <TData extends AxiosResponseData>(
url: string,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
/**
*
*/
export type AxiosRequestMethodFnWithParams = <TData extends AxiosResponseData>(
url: string,
params?: AnyObject,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
/**
*
*/
export type AxiosRequestMethodFnWithData = <TData extends AxiosResponseData>(
url: string,
data?: AxiosRequestData,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
export interface AxiosDomainRequestHandler {
(config: AxiosRequestConfig): Promise<AxiosResponse>;
}
/**
* Axios
*/
@ -281,7 +352,19 @@ export interface AxiosConstructor {
new (config: AxiosRequestConfig): Axios;
}
export default class Axios extends AxiosDomain {
export default class Axios {
/**
* @internal
*
*
*/
private declare parent?: Axios;
/**
*
*/
declare defaults: AxiosRequestConfig;
/**
*
*/
@ -296,65 +379,219 @@ export default class Axios extends AxiosDomain {
response: new InterceptorManager<AxiosResponse>(),
};
constructor(defaults: AxiosRequestConfig = {}) {
super(defaults, (config) => this.#processRequest(config));
}
/**
* @internal
*
*
*/
private middleware = new MiddlewareManager();
getUri(config: AxiosRequestConfig): string {
const { url, params, paramsSerializer } = mergeConfig(
this.defaults,
config,
);
return buildURL(url, params, paramsSerializer).replace(/^\?/, '');
/**
* options
*/
declare options: AxiosRequestMethodFn;
/**
* get
*/
declare get: AxiosRequestMethodFnWithParams;
/**
* head
*/
declare head: AxiosRequestMethodFnWithParams;
/**
* post
*/
declare post: AxiosRequestMethodFnWithData;
/**
* put
*/
declare put: AxiosRequestMethodFnWithData;
/**
* patch
*/
declare patch: AxiosRequestMethodFnWithData;
/**
* delete
*/
declare delete: AxiosRequestMethodFnWithParams;
/**
* trace
*/
declare trace: AxiosRequestMethodFn;
/**
* connect
*/
declare connect: AxiosRequestMethodFn;
/**
* @param config
* @param parent
*/
constructor(config: AxiosRequestConfig, parent?: Axios) {
this.defaults = config;
this.parent = parent;
}
/**
*
*
*/
fork = (defaults: AxiosRequestConfig = {}) => {
if (isString(defaults.baseURL) && !isAbsoluteURL(defaults.baseURL)) {
defaults.baseURL = combineURL(this.defaults.baseURL, defaults.baseURL);
request: AxiosRequest = (
urlOrConfig: string | AxiosRequestConfig,
config: AxiosRequestConfig = {},
) => {
if (isString(urlOrConfig)) {
config.url = urlOrConfig;
} else {
config = urlOrConfig;
}
return new AxiosDomain(mergeConfig(this.defaults, defaults), (config) =>
this.#processRequest(config),
);
config = mergeConfig(this.defaults, config);
config.method = (config.method?.toLowerCase() ??
'get') as AxiosRequestMethod;
const requestHandler = {
resolved: this.handleRequest,
};
const errorHandler = {
rejected: config.errorHandler,
};
const chain: (
| Partial<Interceptor<AxiosRequestConfig>>
| Partial<Interceptor<AxiosResponse>>
)[] = [];
this.eachInterceptors('request', (interceptor) => {
chain.unshift(interceptor);
});
chain.push(requestHandler);
this.eachInterceptors('response', (interceptor) => {
chain.push(interceptor);
});
chain.push(errorHandler);
return chain.reduce(
(next, { resolved, rejected }) =>
next.then(
// @ts-ignore
resolved,
rejected,
),
Promise.resolve(config),
) as Promise<AxiosResponse>;
};
#processRequest(config: AxiosRequestConfig) {
const chain: [
Interceptor<AxiosRequestConfig> | Interceptor<AxiosResponse>,
] = [
{
resolved: dispatchRequest,
},
];
this.interceptors.request.forEach(chain.unshift.bind(chain));
this.interceptors.response.forEach(chain.push.bind(chain));
let next = Promise.resolve(config);
for (const { resolved, rejected } of chain) {
next = next.then(
// @ts-ignore
resolved,
rejected,
);
/**
* @internal
*/
private eachInterceptors<T extends 'request' | 'response'>(
type: T,
executor: InterceptorExecutor<
T extends 'request' ? AxiosRequestConfig : AxiosResponse
>,
) {
// @ts-ignore
this.interceptors[type].forEach(executor);
if (this.parent) {
this.parent.eachInterceptors(type, executor);
}
// 错误处理
next = next.catch((reason) => {
const { errorHandler } = config;
if (isFunction(errorHandler)) {
const promise = errorHandler(reason);
if (isPromise(promise)) {
return promise.then(() => Promise.reject(reason));
}
}
return Promise.reject(reason);
});
return next as Promise<AxiosResponse>;
}
/**
*
*
* 1
* ```ts
* axios.use(async function middleware(ctx, next) {
* console.log(ctx.req);
* await next();
* console.log(ctx.res);
* });
* ```
*
* 2
* ```ts
* axios
* .use(async function middleware1(ctx, next) {
* console.log(ctx.req);
* await next();
* console.log(ctx.res);
* })
* .use(async function middleware2(ctx, next) {
* console.log(ctx.req);
* await next();
* console.log(ctx.res);
* });
* ```
*/
use = (middleware: MiddlewareCallback) => {
this.middleware.use(middleware);
return this;
};
/**
* @internal
*/
private handleRequest = async (config: AxiosRequestConfig) => {
const ctx = this.middleware.createContext(config);
await this.run(ctx, this.handleResponse);
return ctx.res as AxiosResponse;
};
/**
* @internal
*/
private async handleResponse(ctx: MiddlewareContext) {
ctx.res = await dispatchRequest(ctx.req);
}
/**
* @internal
*/
private run = (
ctx: MiddlewareContext,
respond: MiddlewareCallback,
): Promise<void> => {
if (!this.parent) {
return this.middleware.run(ctx, respond);
}
return this.middleware.enhanceRun(this.parent.run)(ctx, respond);
};
}
for (const method of PLAIN_METHODS) {
Axios.prototype[method] = function processRequestMethod(url, config = {}) {
config.method = method;
return this.request(url, config);
};
}
for (const method of WITH_PARAMS_METHODS) {
Axios.prototype[method] = function processRequestMethodWithParams(
url,
params,
config = {},
) {
config.method = method;
config.params = deepMerge(params, config.params);
return this.request(url, config);
};
}
for (const method of WITH_DATA_METHODS) {
Axios.prototype[method] = function processRequestMethodWithData(
url,
data,
config = {},
) {
config.method = method;
config.data = data;
return this.request(url, config);
};
}

View File

@ -1,182 +0,0 @@
import { isString, isUndefined } from '../helpers/isTypes';
import { deepMerge } from '../helpers/deepMerge';
import { mergeConfig } from './mergeConfig';
import {
AxiosRequestConfig,
AxiosRequestData,
AxiosResponse,
AxiosResponseData,
} from './Axios';
/**
*
*/
export interface AxiosDomainRequest {
<TData extends AxiosResponseData>(config: AxiosRequestConfig): Promise<
AxiosResponse<TData>
>;
<TData extends AxiosResponseData>(
url: string,
config?: AxiosRequestConfig,
): Promise<AxiosResponse<TData>>;
}
/**
*
*/
export type AxiosDomainRequestMethod = <TData extends AxiosResponseData>(
url: string,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
/**
*
*/
export type AxiosDomainRequestMethodWithParams = <
TData extends AxiosResponseData,
>(
url: string,
params?: AnyObject,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
/**
*
*/
export type AxiosDomainRequestMethodWithData = <
TData extends AxiosResponseData,
>(
url: string,
data?: AxiosRequestData,
config?: AxiosRequestConfig,
) => Promise<AxiosResponse<TData>>;
/**
*
*/
export const requestMethodNames = ['options', 'trace', 'connect'] as const;
/**
*
*/
export const requestMethodWithParamsNames = ['head', 'get', 'delete'] as const;
/**
*
*/
export const requestMethodWithDataNames = ['post', 'put', 'patch'] as const;
export default class AxiosDomain {
/**
*
*/
defaults: AxiosRequestConfig;
/**
*
*/
request!: AxiosDomainRequest;
/**
* options
*/
options!: AxiosDomainRequestMethod;
/**
* get
*/
get!: AxiosDomainRequestMethodWithParams;
/**
* head
*/
head!: AxiosDomainRequestMethodWithParams;
/**
* post
*/
post!: AxiosDomainRequestMethodWithData;
/**
* put
*/
put!: AxiosDomainRequestMethodWithData;
/**
* patch
*/
patch!: AxiosDomainRequestMethodWithData;
/**
* delete
*/
delete!: AxiosDomainRequestMethodWithParams;
/**
* trace
*/
trace!: AxiosDomainRequestMethod;
/**
* connect
*/
connect!: AxiosDomainRequestMethod;
constructor(
defaults: AxiosRequestConfig,
processRequest: (config: AxiosRequestConfig) => Promise<AxiosResponse>,
) {
this.defaults = defaults;
this.request = (
urlOrConfig: string | AxiosRequestConfig,
config: AxiosRequestConfig = {},
) => {
if (isString(urlOrConfig)) {
config.url = urlOrConfig;
} else {
config = urlOrConfig;
}
if (isUndefined(config.method)) {
config.method = 'get';
}
return processRequest(mergeConfig(this.defaults, config));
};
}
}
for (const method of requestMethodNames) {
AxiosDomain.prototype[method] = function processRequestMethod(
url,
config = {},
) {
config.method = method;
return this.request(url, config);
};
}
for (const method of requestMethodWithParamsNames) {
AxiosDomain.prototype[method] = function processRequestMethodWithParams(
url,
params = {},
config = {},
) {
config.method = method;
config.params = deepMerge(params, config.params ?? {});
return this.request(url, config);
};
}
for (const method of requestMethodWithDataNames) {
AxiosDomain.prototype[method] = function processRequestMethodWithData(
url,
data,
config = {},
) {
config.method = method;
config.data = data;
return this.request(url, config);
};
}

View File

@ -6,8 +6,17 @@ export interface InterceptorRejected<T = unknown> {
(error: unknown): T | Promise<T>;
}
/**
*
*/
export interface Interceptor<T = unknown> {
/**
*
*/
resolved: InterceptorResolved<T>;
/**
*
*/
rejected?: InterceptorRejected<T>;
}
@ -15,36 +24,76 @@ export interface InterceptorExecutor<T = unknown> {
(interceptor: Interceptor<T>): void;
}
/**
*
*/
export default class InterceptorManager<T = unknown> {
#id = 0;
/**
* @internal
*
*
*/
private id = 0;
#interceptors = new Map<number, Interceptor<T>>();
/**
* @internal
*
*
*/
private interceptors = new Map<number, Interceptor<T>>();
/**
* @internal
*
*
*/
get size() {
return this.#interceptors.size;
return this.interceptors.size;
}
/**
*
*
* @param resolved
* @param rejected
* @returns
*/
use(
resolved: InterceptorResolved<T>,
rejected?: InterceptorRejected<T>,
): number {
this.#interceptors.set(++this.#id, {
this.interceptors.set(++this.id, {
resolved,
rejected,
});
return this.#id;
return this.id;
}
/**
*
*
* @param id
*/
eject(id: number): boolean {
return this.#interceptors.delete(id);
return this.interceptors.delete(id);
}
/**
*
*/
clear() {
this.#interceptors.clear();
this.interceptors.clear();
}
/**
* @internal
*
*
*
* @param executor
*/
forEach(executor: InterceptorExecutor<T>): void {
this.#interceptors.forEach(executor);
this.interceptors.forEach(executor);
}
}

View File

@ -0,0 +1,91 @@
import { assert } from '../helpers/error';
import { isFunction } from '../helpers/types';
import { AxiosRequestConfig, AxiosResponse } from './Axios';
export interface MiddlewareNext {
(): Promise<void>;
}
/**
*
*/
export interface MiddlewareContext {
/**
*
*
*
*/
req: AxiosRequestConfig;
/**
*
*/
res: null | AxiosResponse;
}
/**
*
*/
export interface MiddlewareCallback {
(ctx: MiddlewareContext, next: MiddlewareNext): Promise<void>;
}
/**
*
*/
export default class MiddlewareManager {
/**
* @internal
*
*
*/
private middlewares: MiddlewareCallback[] = [];
/**
*
*/
use(middleware: MiddlewareCallback) {
assert(isFunction(middleware), 'middleware 不是一个 function');
this.middlewares.push(middleware);
}
/**
* @internal
*
*
*/
createContext(config: AxiosRequestConfig): MiddlewareContext {
return {
req: config,
res: null,
};
}
/**
* @internal
*
*
*
* @param ctx
* @param respond
*/
run(ctx: MiddlewareContext, respond: MiddlewareCallback) {
const middlewares = [...this.middlewares, respond];
async function next() {
await middlewares.shift()!(ctx, next);
}
return next();
}
/**
* @internal
*
*
*
* @param enhancer
*/
enhanceRun(enhancer: MiddlewareManager['run']): MiddlewareManager['run'] {
return (ctx, respond) => {
return enhancer(ctx, () => this.run(ctx, respond));
};
}
}

View File

@ -0,0 +1,72 @@
import { dynamicURL } from '../helpers/dynamicURL';
import { combineURL } from '../helpers/combineURL';
import { transformURL } from '../helpers/transformURL';
import Axios, {
AxiosRequest,
AxiosRequestConfig,
AxiosRequestHeaders,
} from './Axios';
import { mergeConfig } from './mergeConfig';
/**
* axios
*/
export interface AxiosInstanceDefaults extends AxiosRequestConfig {
/**
*
*/
headers: Required<AxiosRequestHeaders>;
}
/**
* axios
*/
export interface AxiosInstance extends AxiosRequest, Axios {
/**
*
*/
defaults: AxiosInstanceDefaults;
/**
* URI
*
* @param config
*/
getUri(config: AxiosRequestConfig): string;
/**
*
*
* @param config
*/
create(config?: AxiosRequestConfig): AxiosInstance;
/**
*
*
* @param config
*/
extend(config: AxiosRequestConfig): AxiosInstance;
}
export function createInstance(
defaults: AxiosRequestConfig,
parentContext?: Axios,
) {
const context = new Axios(defaults, parentContext);
const instance = context.request as AxiosInstance;
instance.getUri = function getUri(config) {
config.url = dynamicURL(config.url!, config.params, config.data);
return transformURL(mergeConfig(defaults, config));
};
instance.create = function create(config) {
return createInstance(mergeConfig(defaults, config));
};
instance.extend = function extend(config) {
config.baseURL = combineURL(defaults.baseURL, config.baseURL);
return createInstance(mergeConfig(defaults, config), context);
};
Object.assign(instance, context);
Object.setPrototypeOf(instance, Axios.prototype);
return instance;
}

View File

@ -1,29 +0,0 @@
import { isPlainObject } from '../helpers/isTypes';
import { ignore } from '../helpers/ignore';
import { AxiosRequestConfig, AxiosRequestHeaders } from './Axios';
export function flattenHeaders(
config: AxiosRequestConfig,
): AxiosRequestHeaders {
if (!isPlainObject(config.headers)) {
return {};
}
return {
...(config.headers.common ?? {}),
...(config.headers[config.method!.toLowerCase()] ?? {}),
...ignore(
config.headers,
'common',
'options',
'get',
'head',
'post',
'put',
'patch',
'delete',
'trace',
'connect',
),
};
}

View File

@ -1,10 +1,9 @@
import { isUndefined, isPlainObject } from '../helpers/isTypes';
import { isUndefined, isPlainObject } from '../helpers/types';
import { deepMerge } from '../helpers/deepMerge';
import { AxiosRequestConfig } from './Axios';
const fromConfig2Map: Record<string, boolean> = {
url: true,
method: true,
data: true,
upload: true,
download: true,
@ -14,6 +13,11 @@ const deepMergeConfigMap: Record<string, boolean> = {
params: true,
};
/**
*
*
*
*/
export function mergeConfig(
config1: AxiosRequestConfig = {},
config2: AxiosRequestConfig = {},
@ -35,12 +39,10 @@ export function mergeConfig(
}
// 深度合并 config1 和 config2 中的对象
else if (deepMergeConfigMap[key]) {
if (isPlainObject(val1) && isPlainObject(val2)) {
config[key] = deepMerge(val1, val2);
if (isPlainObject(val1)) {
config[key] = deepMerge(val1, isPlainObject(val2) ? val2 : {});
} else if (isPlainObject(val2)) {
config[key] = val2;
} else if (isPlainObject(val1)) {
config[key] = val1;
config[key] = deepMerge(val2, {});
}
}
// 优先从 config2 中取值,如果没有值就从 config1 中取值

View File

@ -1,20 +0,0 @@
import { isPlainObject } from '../helpers/isTypes';
import { buildURL } from '../helpers/buildURL';
import { combineURL } from '../helpers/combineURL';
import { dynamicURL } from '../helpers/dynamicURL';
import { isAbsoluteURL } from '../helpers/isAbsoluteURL';
import { AxiosRequestConfig } from './Axios';
export function transformURL(config: AxiosRequestConfig) {
let url = config.url ?? '';
if (!isAbsoluteURL(url)) url = combineURL(config.baseURL ?? '', url);
url = dynamicURL(
url,
config.params,
isPlainObject(config.data) ? config.data : {},
);
url = buildURL(url, config.params, config.paramsSerializer);
return url;
}

View File

@ -1,5 +1,5 @@
import { getDefaultAdapter } from './adapter';
import { AxiosInstanceDefaults } from './axios';
import { getDefaultAdapter } from './adpater/getDefaultAdapter';
import { AxiosInstanceDefaults } from './core/createInstance';
const defaults: AxiosInstanceDefaults = {
// 适配器,在支持的平台中有值。

View File

@ -1,8 +1,8 @@
import { isArray, isDate, isNull, isPlainObject, isUndefined } from './isTypes';
import { isArray, isDate, isNull, isPlainObject, isUndefined } from './types';
export function buildURL(
url = '',
params?: AnyObject,
params: AnyObject = {},
paramsSerializer = defaultSerializer,
): string {
const paramsStr = paramsSerializer(params);
@ -12,9 +12,7 @@ export function buildURL(
return url;
}
function defaultSerializer(params?: AnyObject): string {
if (!isPlainObject(params)) return '';
function defaultSerializer(params: AnyObject): string {
const parts: string[] = [];
function push(key: string, value: string) {

Some files were not shown because too many files have changed in this diff Show More