mirror of
https://github.com/WeBankFinTech/fes.js.git
synced 2025-08-07 18:39:45 +08:00
feat: request to fetch
This commit is contained in:
parent
828a58d885
commit
3c66904896
@ -1,6 +1,6 @@
|
|||||||
# @fesjs/plugin-request
|
# @fesjs/plugin-request
|
||||||
|
|
||||||
基于 axios 封装的 request,内置防止重复请求、请求缓存、错误处理等功能。
|
基于 fetch 封装的 request,内置防止重复请求、请求缓存、错误处理等功能。
|
||||||
|
|
||||||
## 启用方式
|
## 启用方式
|
||||||
|
|
||||||
@ -10,35 +10,39 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fesjs/fes": "^3.0.0",
|
"@fesjs/fes": "^3.0.0",
|
||||||
"@fesjs/plugin-request": "^3.0.0"
|
"@fesjs/plugin-request": "^4.0.0-rc.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 运行时配置
|
## 运行时配置
|
||||||
|
|
||||||
入口文件的全局配置,具体请求的配置参数会覆盖全局配置,支持 [axios](https://axios-http.com/zh/docs/req_config) 所有的参数。
|
入口文件的全局配置,具体请求的配置参数会覆盖全局配置,支持 [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#sending_a_request_with_credentials_included) 所有的参数。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { defineRuntimeConfig } from '@fesjs/fes';
|
import { defineRuntimeConfig } from '@fesjs/fes';
|
||||||
|
|
||||||
export default defineRuntimeConfig({
|
export default defineRuntimeConfig({
|
||||||
request: {
|
request: {
|
||||||
// API 前缀
|
|
||||||
baseURL: '',
|
baseURL: '',
|
||||||
dataHandler(data, response) {
|
timeout: 10000, // 默认 10s
|
||||||
|
method: 'POST', // 默认 post
|
||||||
|
mergeRequest: false, // 是否合并请求
|
||||||
|
responseType: null, // 可选 'json' | 'text' | 'blob' | 'arrayBuffer' | 'formData',默认根据 content-type 处理
|
||||||
|
credentials: 'include', // 默认 include, 'include' | 'same-origin' | 'omit'
|
||||||
|
headers: {}, // 传给服务器的 header
|
||||||
|
cacheData: false, // 是否缓存
|
||||||
|
requestInterceptor: (config: Config) => Config,
|
||||||
|
responseInterceptor: (response: RequestResponse) => RequestResponse,
|
||||||
|
transformData(data, response) {
|
||||||
// 处理响应内容异常
|
// 处理响应内容异常
|
||||||
if (data.code !== '0') {
|
if (isPlainObject(data)) {
|
||||||
if (data.code === '10000') {
|
if (data.code === '10000') {
|
||||||
FMesseage.error('hello world');
|
return Promise.reject(data);
|
||||||
}
|
}
|
||||||
if (data.code === '20000') {
|
return data?.result ? data.result : data;
|
||||||
FMesseage.error('hello world');
|
|
||||||
}
|
|
||||||
throw new Error(response);
|
|
||||||
}
|
}
|
||||||
// 响应数据格式化
|
return data;
|
||||||
return data?.result ? data.result : data;
|
|
||||||
},
|
},
|
||||||
// http 异常,和插件异常
|
// http 异常,和插件异常
|
||||||
errorHandler(error) {
|
errorHandler(error) {
|
||||||
@ -47,13 +51,7 @@ export default defineRuntimeConfig({
|
|||||||
console.log(error.response.data);
|
console.log(error.response.data);
|
||||||
console.log(error.response.status);
|
console.log(error.response.status);
|
||||||
console.log(error.response.headers);
|
console.log(error.response.headers);
|
||||||
} else if (error.request) {
|
} else if (error.msg) {
|
||||||
// 请求已经成功发起,但没有收到响应
|
|
||||||
// `error.request` 在浏览器中是 XMLHttpRequest 的实例,
|
|
||||||
// 而在node.js中是 http.ClientRequest 的实例
|
|
||||||
console.log(error.request);
|
|
||||||
} else if (error.type) {
|
|
||||||
// 插件异常
|
|
||||||
console.log(error.msg);
|
console.log(error.msg);
|
||||||
} else {
|
} else {
|
||||||
// 发送请求时出了点问题
|
// 发送请求时出了点问题
|
||||||
@ -61,11 +59,7 @@ export default defineRuntimeConfig({
|
|||||||
}
|
}
|
||||||
console.log(error.config);
|
console.log(error.config);
|
||||||
},
|
},
|
||||||
// 请求拦截器
|
// 支持其他 fetch 配置
|
||||||
requestInterceptors: [],
|
|
||||||
// 响应拦截器
|
|
||||||
responseInterceptors: [],
|
|
||||||
// 支持其他 axios 配置
|
|
||||||
...otherConfigs,
|
...otherConfigs,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -82,7 +76,7 @@ export default defineRuntimeConfig({
|
|||||||
|
|
||||||
- url: 后端接口 url
|
- url: 后端接口 url
|
||||||
- data: 参数
|
- data: 参数
|
||||||
- options: 配置支持 [axios](https://axios-http.com/zh/docs/req_config) 所有的参数,和插件扩展参数。
|
- options: 配置支持 [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#sending_a_request_with_credentials_included) 所有的参数,和插件扩展参数。
|
||||||
|
|
||||||
- **返回值**: Promise
|
- **返回值**: Promise
|
||||||
|
|
||||||
@ -148,7 +142,7 @@ request(
|
|||||||
password: '123456',
|
password: '123456',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
cache: {
|
cacheData: {
|
||||||
cacheType: 'ram', // ram: 内存,session: sessionStorage,local:localStorage
|
cacheType: 'ram', // ram: 内存,session: sessionStorage,local:localStorage
|
||||||
cacheTime: 1000 * 60 * 3, // 缓存时间:默认3min
|
cacheTime: 1000 * 60 * 3, // 缓存时间:默认3min
|
||||||
},
|
},
|
||||||
@ -162,7 +156,37 @@ request(
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
若 `cache` 传 `true`,则默认使用 `ram` 缓存类型,缓存时间 3min。
|
若 `cacheData` 传 `true`,则默认使用 `ram` 缓存类型,缓存时间 3min。
|
||||||
|
|
||||||
|
### 请求 abort
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { request } from '@fesjs/fes';
|
||||||
|
|
||||||
|
const controller = new AbortController();
|
||||||
|
request('/url/abort', null, {
|
||||||
|
signal: controller.signal,
|
||||||
|
}).then((response) => {
|
||||||
|
console.log('process response: ' + response);
|
||||||
|
});
|
||||||
|
// cancel the request
|
||||||
|
controller.abort();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 获取 response headers
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import { rawRequest } from '@fesjs/fes';
|
||||||
|
|
||||||
|
const controller = new AbortController();
|
||||||
|
rawRequest('/url/abort', null, {
|
||||||
|
signal: controller.signal,
|
||||||
|
}).then((response) => {
|
||||||
|
console.log('process headers: ' + response.headers);
|
||||||
|
});
|
||||||
|
// cancel the request
|
||||||
|
controller.abort();
|
||||||
|
```
|
||||||
|
|
||||||
### 结合 use 使用
|
### 结合 use 使用
|
||||||
|
|
||||||
@ -184,3 +208,11 @@ export default {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 3.x 升级到 4.x
|
||||||
|
|
||||||
|
1. 缓存参数 cache 改成 cacheData(避免与 fetch 原本的 cache 冲突)
|
||||||
|
2. dataHandler 改成 transformData
|
||||||
|
3. requestInterceptors 改为 requestInterceptor,不在支持数组,只支持函数
|
||||||
|
4. responseInterceptors 改为 responseInterceptor,不在支持数组,只支持函数
|
||||||
|
5. 其他 axios 特有的配置不在支持
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
# @fesjs/plugin-windicss
|
# @fesjs/plugin-windicss
|
||||||
|
|
||||||
|
::: warning 即将废弃
|
||||||
|
由于 windicss 不怎么维护了,本插件即将废弃,推荐使用 [tailwindcss](https://tailwindcss.com/)。
|
||||||
|
:::
|
||||||
|
|
||||||
## 介绍
|
## 介绍
|
||||||
|
|
||||||
`windicss` 支持
|
`windicss` 支持
|
||||||
|
|
||||||
## 启用方式
|
## 启用方式
|
||||||
|
|
||||||
在 `package.json` 中引入依赖:
|
在 `package.json` 中引入依赖:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fesjs/plugin-windicss": "^2.0.0"
|
"@fesjs/plugin-windicss": "^2.0.0"
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -23,6 +28,6 @@
|
|||||||
export default {
|
export default {
|
||||||
windicss: {
|
windicss: {
|
||||||
root: './',
|
root: './',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
```
|
```
|
||||||
|
@ -46,10 +46,10 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fesjs/fes": "^3.0.0-rc.1",
|
"@fesjs/fes": "^3.0.0-rc.1",
|
||||||
"@fesjs/plugin-icon": "^3.0.0-rc.0",
|
"@fesjs/plugin-icon": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-request": "^3.0.0-rc.3",
|
"@fesjs/plugin-request": "^4.0.0-rc.0",
|
||||||
"@fesjs/builder-webpack": "^3.0.0-rc.1",
|
"@fesjs/builder-webpack": "^3.0.0-rc.1",
|
||||||
"vue": "^3.2.37",
|
"vue": "^3.2.37",
|
||||||
"core-js": "^3.27.0"
|
"core-js": "^3.27.0"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
@ -59,7 +59,7 @@
|
|||||||
"style-loader": "^2.0.0",
|
"style-loader": "^2.0.0",
|
||||||
"terser-webpack-plugin": "^5.3.6",
|
"terser-webpack-plugin": "^5.3.6",
|
||||||
"vue-loader": "^16.1.2",
|
"vue-loader": "^16.1.2",
|
||||||
"webpack": "^5.69.0",
|
"webpack": "^5.76.2",
|
||||||
"webpack-bundle-analyzer": "^4.4.0",
|
"webpack-bundle-analyzer": "^4.4.0",
|
||||||
"webpack-chain": "^6.5.1",
|
"webpack-chain": "^6.5.1",
|
||||||
"webpack-dev-server": "^4.8.1",
|
"webpack-dev-server": "^4.8.1",
|
||||||
@ -69,4 +69,4 @@
|
|||||||
"@fesjs/fes": "3.0.0-rc.8",
|
"@fesjs/fes": "3.0.0-rc.8",
|
||||||
"core-js": "^3.27.0"
|
"core-js": "^3.27.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -93,8 +93,8 @@ export default function createCssWebpackConfig({ isDev, config, webpackConfig, b
|
|||||||
if (!isDev) {
|
if (!isDev) {
|
||||||
webpackConfig.plugin('extra-css').use(require.resolve('mini-css-extract-plugin'), [
|
webpackConfig.plugin('extra-css').use(require.resolve('mini-css-extract-plugin'), [
|
||||||
{
|
{
|
||||||
filename: '[name].[contenthash:8].css',
|
filename: 'css/[name].[contenthash:8].css',
|
||||||
chunkFilename: '[id].[contenthash:8].css',
|
chunkFilename: 'css/[id].[contenthash:8].css',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
webpackConfig.optimization.minimizer('css').use(require.resolve('css-minimizer-webpack-plugin'), [{}]);
|
webpackConfig.optimization.minimizer('css').use(require.resolve('css-minimizer-webpack-plugin'), [{}]);
|
||||||
|
@ -77,8 +77,8 @@ export default async function getConfig({ api, cwd, config, env, entry = {}, mod
|
|||||||
webpackConfig.output
|
webpackConfig.output
|
||||||
.path(absoluteOutput)
|
.path(absoluteOutput)
|
||||||
.publicPath(publicPath || '/')
|
.publicPath(publicPath || '/')
|
||||||
.filename('[name].[contenthash:8].js')
|
.filename('js/[name].[contenthash:8].js')
|
||||||
.chunkFilename('[name].[contenthash:8].chunk.js');
|
.chunkFilename('js/[name].[contenthash:8].chunk.js');
|
||||||
|
|
||||||
// --------------- resolve -----------
|
// --------------- resolve -----------
|
||||||
webpackConfig.resolve.extensions.merge(['.mjs', '.js', '.jsx', '.vue', '.ts', '.tsx', '.json', '.wasm']);
|
webpackConfig.resolve.extensions.merge(['.mjs', '.js', '.jsx', '.vue', '.ts', '.tsx', '.json', '.wasm']);
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@fesjs/fes": "3.0.0-rc.4",
|
"@fesjs/fes": "3.0.0-rc.4",
|
||||||
"@fesjs/plugin-request": "3.0.0-rc.6",
|
"@fesjs/plugin-request": "^4.0.0-rc.0",
|
||||||
"vue": "^3.2.37"
|
"vue": "^3.2.37"
|
||||||
},
|
},
|
||||||
"typings": "./types.d.ts"
|
"typings": "./types.d.ts"
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@fesjs/plugin-request",
|
"name": "@fesjs/plugin-request",
|
||||||
"version": "3.0.0-rc.5",
|
"version": "4.0.0-rc.0",
|
||||||
"description": "@fesjs/plugin-request",
|
"description": "@fesjs/plugin-request",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
@ -33,7 +33,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fesjs/utils": "3.0.0-rc.2",
|
"@fesjs/utils": "3.0.0-rc.2",
|
||||||
"axios": "^1.0.0-alpha.1"
|
"@qlin/request": "^0.1.1"
|
||||||
},
|
},
|
||||||
"typings": "./types.d.ts"
|
"typings": "./types.d.ts"
|
||||||
}
|
}
|
@ -1,201 +0,0 @@
|
|||||||
import { isObject, isString, isURLSearchParams, checkHttpRequestHasBody } from './helpers';
|
|
||||||
/**
|
|
||||||
* 缓存实现的功能
|
|
||||||
* 1. 唯一定位一个请求(url, data | params, method)
|
|
||||||
* 其中请求参数根据请求方法使用其中一个就够了
|
|
||||||
* 一个请求同时包含 data | params 参数的设计本身不合理
|
|
||||||
* 不对这种情况进行兼容
|
|
||||||
* 2. 控制缓存内容的大小,localStorage 只有5M
|
|
||||||
* 3. 控制缓存时间
|
|
||||||
* session(存在内存中)
|
|
||||||
* expireTime 存在localStoreage 中
|
|
||||||
* 4. 成功的、且响应内容为json的请求进行缓存
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置数据
|
|
||||||
* type: 'ram' | 'sessionStorage' | 'localStorage'
|
|
||||||
* cacheTime: ''
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 缓存数据结构
|
|
||||||
* cache: {
|
|
||||||
* url: 'url', // 缓存 url
|
|
||||||
* data: data, // 数据
|
|
||||||
* expire: '' // 缓存时间
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 请求参数可以为如下类型
|
|
||||||
* - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
|
|
||||||
* - Browser only: FormData, File, Blob
|
|
||||||
* 只缓存参数类型为: string、plain object、URLSearchParams 或者无参数的 请求
|
|
||||||
*/
|
|
||||||
|
|
||||||
const CACHE_KEY_PREFIX = '__FES_REQUEST_CACHE:';
|
|
||||||
const CACHE_TYPE = {
|
|
||||||
ram: 'ram',
|
|
||||||
session: 'sessionStorage',
|
|
||||||
local: 'localStorage',
|
|
||||||
};
|
|
||||||
|
|
||||||
const CACHE_DATA_MAP = new Map();
|
|
||||||
|
|
||||||
function genInnerKey(key, cacheType = 'ram') {
|
|
||||||
if (cacheType !== CACHE_TYPE.ram) {
|
|
||||||
return `${CACHE_KEY_PREFIX}${key}`;
|
|
||||||
}
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
function canCache(data) {
|
|
||||||
return !data || isObject(data) || isString(data) || Array.isArray(data) || isURLSearchParams(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setCacheData({ key, cacheType = 'ram', data, cacheTime = 1000 * 60 * 3 }) {
|
|
||||||
const _key = genInnerKey(key, cacheType);
|
|
||||||
|
|
||||||
const currentCacheData = {
|
|
||||||
cacheType,
|
|
||||||
data,
|
|
||||||
cacheTime,
|
|
||||||
expire: Date.now() + cacheTime,
|
|
||||||
};
|
|
||||||
if (cacheType !== CACHE_TYPE.ram) {
|
|
||||||
const cacheInstance = window[CACHE_TYPE[cacheType]];
|
|
||||||
try {
|
|
||||||
cacheInstance.setItem(_key, JSON.stringify(currentCacheData));
|
|
||||||
} catch (e) {
|
|
||||||
// setItem 出现异常,清理缓存
|
|
||||||
for (const item in cacheInstance) {
|
|
||||||
if (item.startsWith(CACHE_KEY_PREFIX) && Object.prototype.hasOwnProperty.call(cacheInstance, item)) {
|
|
||||||
cacheInstance.removeItem(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CACHE_DATA_MAP.set(_key, currentCacheData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isExpire({ expire, cacheTime }) {
|
|
||||||
if (!cacheTime || expire >= Date.now()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCacheData({ key, cacheType = 'ram' }) {
|
|
||||||
const _key = genInnerKey(key, cacheType);
|
|
||||||
if (cacheType !== CACHE_TYPE.ram) {
|
|
||||||
const cacheInstance = window[CACHE_TYPE[cacheType]];
|
|
||||||
const text = cacheInstance.getItem(_key) || null;
|
|
||||||
try {
|
|
||||||
const currentCacheData = JSON.parse(text);
|
|
||||||
if (currentCacheData && !isExpire(currentCacheData)) {
|
|
||||||
return currentCacheData.data;
|
|
||||||
}
|
|
||||||
cacheInstance.removeItem(_key);
|
|
||||||
return null;
|
|
||||||
} catch (e) {
|
|
||||||
cacheInstance.removeItem(_key);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const currentCacheData = CACHE_DATA_MAP.get(_key);
|
|
||||||
if (currentCacheData && !isExpire(currentCacheData)) {
|
|
||||||
return currentCacheData.data;
|
|
||||||
}
|
|
||||||
CACHE_DATA_MAP.delete(_key);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 存储缓存队列
|
|
||||||
const cacheStartFlag = new Map();
|
|
||||||
const cachingQueue = new Map();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 等上一次请求结果
|
|
||||||
* 1. 如果上一次请求成功,直接使用上一次的请求结果
|
|
||||||
* 2. 如果上一次请求失败,重启本次请求
|
|
||||||
*/
|
|
||||||
function handleCachingStart(ctx, config) {
|
|
||||||
const _key = genInnerKey(ctx.key, config.cache.cacheType);
|
|
||||||
const caching = cacheStartFlag.get(_key);
|
|
||||||
if (caching) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
const queue = cachingQueue.get(_key) || [];
|
|
||||||
cachingQueue.set(_key, queue.concat(resolve));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
cacheStartFlag.set(_key, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 有请求成功的
|
|
||||||
function handleCachingQueueSuccess(ctx, config) {
|
|
||||||
// 移除首次缓存 flag
|
|
||||||
const _key = genInnerKey(ctx.key, config.cache.cacheType);
|
|
||||||
const queue = cachingQueue.get(_key);
|
|
||||||
if (queue && queue.length > 0) {
|
|
||||||
queue.forEach((resolve) => {
|
|
||||||
resolve({
|
|
||||||
response: ctx.response,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
cachingQueue.delete(_key);
|
|
||||||
cacheStartFlag.delete(_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理请求失败
|
|
||||||
function handleCachingQueueError(ctx, config) {
|
|
||||||
const _key = genInnerKey(ctx.key, config.cache.cacheType);
|
|
||||||
const queue = cachingQueue.get(_key);
|
|
||||||
if (queue && queue.length > 0) {
|
|
||||||
const firstResolve = queue.shift();
|
|
||||||
firstResolve();
|
|
||||||
cachingQueue.set(_key, queue);
|
|
||||||
} else {
|
|
||||||
cachingQueue.delete(_key);
|
|
||||||
cacheStartFlag.delete(_key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async (ctx, next) => {
|
|
||||||
const { config } = ctx;
|
|
||||||
if (config.cache) {
|
|
||||||
const cacheData = getCacheData({ key: ctx.key, cacheType: config.cache.cacheType });
|
|
||||||
if (cacheData) {
|
|
||||||
ctx.response = {
|
|
||||||
data: cacheData,
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const result = await handleCachingStart(ctx, config);
|
|
||||||
if (result) {
|
|
||||||
Object.keys(result).forEach((key) => {
|
|
||||||
ctx[key] = result[key];
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await next();
|
|
||||||
|
|
||||||
if (config.cache) {
|
|
||||||
const requestdata = checkHttpRequestHasBody(config.method) ? config.data : config.params;
|
|
||||||
if (!ctx.error && ctx.response && canCache(requestdata) && canCache(ctx.response.data)) {
|
|
||||||
handleCachingQueueSuccess(ctx, config);
|
|
||||||
|
|
||||||
setCacheData({
|
|
||||||
key: ctx.key,
|
|
||||||
data: ctx.response.data,
|
|
||||||
...config.cache,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
handleCachingQueueError(ctx, config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,22 +0,0 @@
|
|||||||
import { isURLSearchParams } from './helpers';
|
|
||||||
/**
|
|
||||||
* 唯一定位一个请求(url, data | params, method)
|
|
||||||
* 其中请求参数(data, params)根据请求方法,只使用其中一个
|
|
||||||
* 一个请求同时包含 data | params 参数的设计本身不合理
|
|
||||||
* 不对这种情况进行兼容
|
|
||||||
*/
|
|
||||||
|
|
||||||
const getQueryString = (data) => {
|
|
||||||
if (isURLSearchParams(data)) {
|
|
||||||
return data.toString();
|
|
||||||
}
|
|
||||||
return data ? JSON.stringify(data) : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function genRequestKey(ctx, next) {
|
|
||||||
const { url, data, params, method } = ctx.config;
|
|
||||||
|
|
||||||
ctx.key = `${url}${getQueryString(data)}${getQueryString(params)}${method}`;
|
|
||||||
|
|
||||||
await next();
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
/**
|
|
||||||
*判断类型
|
|
||||||
* @param {*} obj 需要判断的对象
|
|
||||||
*/
|
|
||||||
export function typeOf(obj) {
|
|
||||||
const map = {
|
|
||||||
'[object Boolean]': 'boolean',
|
|
||||||
'[object Number]': 'number',
|
|
||||||
'[object String]': 'string',
|
|
||||||
'[object Function]': 'function',
|
|
||||||
'[object Array]': 'array',
|
|
||||||
'[object Date]': 'date',
|
|
||||||
'[object RegExp]': 'regExp',
|
|
||||||
'[object Undefined]': 'undefined',
|
|
||||||
'[object Null]': 'null',
|
|
||||||
'[object Object]': 'object',
|
|
||||||
'[object URLSearchParams]': 'URLSearchParams',
|
|
||||||
};
|
|
||||||
return map[Object.prototype.toString.call(obj)];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isFunction(obj) {
|
|
||||||
return typeOf(obj) === 'function';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isDate(obj) {
|
|
||||||
return typeOf(obj) === 'date';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isString(obj) {
|
|
||||||
return typeOf(obj) === 'string';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isArray(obj) {
|
|
||||||
return typeOf(obj) === 'array';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isObject(obj) {
|
|
||||||
return typeOf(obj) === 'object';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isURLSearchParams(obj) {
|
|
||||||
return typeOf(obj) === 'URLSearchParams';
|
|
||||||
}
|
|
||||||
|
|
||||||
export function checkHttpRequestHasBody(method) {
|
|
||||||
method = method.toUpperCase();
|
|
||||||
const HTTP_METHOD = {
|
|
||||||
GET: {
|
|
||||||
request_body: false,
|
|
||||||
},
|
|
||||||
POST: {
|
|
||||||
request_body: true,
|
|
||||||
},
|
|
||||||
PUT: {
|
|
||||||
request_body: true,
|
|
||||||
},
|
|
||||||
DELETE: {
|
|
||||||
request_body: true,
|
|
||||||
},
|
|
||||||
HEAD: {
|
|
||||||
request_body: false,
|
|
||||||
},
|
|
||||||
OPTIONS: {
|
|
||||||
request_body: false,
|
|
||||||
},
|
|
||||||
PATCH: {
|
|
||||||
request_body: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return HTTP_METHOD[method].request_body;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trimObj(obj) {
|
|
||||||
if (isObject(obj)) {
|
|
||||||
Object.entries(obj).forEach(([key, value]) => {
|
|
||||||
if (isString(value)) {
|
|
||||||
obj[key] = value.trim();
|
|
||||||
} else if (isObject(value)) {
|
|
||||||
trimObj(value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
import { checkHttpRequestHasBody, trimObj } from './helpers';
|
|
||||||
|
|
||||||
export default async (ctx, next) => {
|
|
||||||
const config = ctx.config;
|
|
||||||
if (checkHttpRequestHasBody(config.method)) {
|
|
||||||
trimObj(config.data);
|
|
||||||
} else {
|
|
||||||
trimObj(config.params);
|
|
||||||
}
|
|
||||||
await next();
|
|
||||||
};
|
|
@ -1,64 +0,0 @@
|
|||||||
const requestMap = new Map();
|
|
||||||
|
|
||||||
const mergeRequestMap = new Map();
|
|
||||||
const requestQueue = new Map();
|
|
||||||
|
|
||||||
function handleCachingStart(ctx) {
|
|
||||||
const isRequesting = mergeRequestMap.get(ctx.key);
|
|
||||||
if (isRequesting) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
const queue = requestQueue.get(ctx.key) || [];
|
|
||||||
requestQueue.set(ctx.key, queue.concat(resolve));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
mergeRequestMap.set(ctx.key, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleRepeatRequest(ctx) {
|
|
||||||
const queue = requestQueue.get(ctx.key);
|
|
||||||
if (queue && queue.length > 0) {
|
|
||||||
queue.forEach((resolve) => {
|
|
||||||
if (ctx.error) {
|
|
||||||
resolve({
|
|
||||||
error: ctx.error,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
resolve({
|
|
||||||
response: ctx.response,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
requestQueue.delete(ctx.key);
|
|
||||||
mergeRequestMap.delete(ctx.key);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async (ctx, next) => {
|
|
||||||
if (ctx.config.mergeRequest) {
|
|
||||||
const result = await handleCachingStart(ctx);
|
|
||||||
if (result) {
|
|
||||||
Object.keys(result).forEach((key) => {
|
|
||||||
ctx[key] = result[key];
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (requestMap.get(ctx.key) && !ctx.config.mergeRequest) {
|
|
||||||
ctx.error = {
|
|
||||||
type: 'REPEAT',
|
|
||||||
msg: '重复请求',
|
|
||||||
config: ctx.config,
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
requestMap.set(ctx.key, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
await next();
|
|
||||||
|
|
||||||
if (ctx.config.mergeRequest) {
|
|
||||||
handleRepeatRequest(ctx);
|
|
||||||
} else {
|
|
||||||
requestMap.delete(ctx.key);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,131 +1,34 @@
|
|||||||
import axios from 'axios';
|
|
||||||
import { ApplyPluginsType, plugin } from '@fesjs/fes';
|
import { ApplyPluginsType, plugin } from '@fesjs/fes';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import scheduler from './scheduler';
|
|
||||||
import { checkHttpRequestHasBody, isFunction } from './helpers';
|
|
||||||
|
|
||||||
import paramsProcess from './paramsProcess';
|
import { createRequest } from '@qlin/request';
|
||||||
import genRequestKey from './genRequestKey';
|
|
||||||
import preventRepeatReq from './preventRepeatReq';
|
|
||||||
import cacheControl from './cacheControl';
|
|
||||||
|
|
||||||
function addInterceptors(instance, interceptors, type = 'request') {
|
|
||||||
interceptors.forEach((fn) => {
|
|
||||||
if (Array.isArray(fn)) {
|
|
||||||
instance.interceptors[type].use(...fn);
|
|
||||||
} else if (isFunction(fn)) {
|
|
||||||
instance.interceptors[type].use(fn);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function addRequestInterceptors(instance, interceptors) {
|
|
||||||
addInterceptors(instance, interceptors, 'request');
|
|
||||||
}
|
|
||||||
|
|
||||||
function addResponseInterceptors(instance, interceptors) {
|
|
||||||
addInterceptors(instance, interceptors, 'response');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function axiosMiddleware(context, next) {
|
|
||||||
try {
|
|
||||||
context.response = await context.instance.request(context.config);
|
|
||||||
} catch (error) {
|
|
||||||
context.error = error;
|
|
||||||
}
|
|
||||||
await next();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRequestInstance() {
|
function getRequestInstance() {
|
||||||
const {
|
const defaultConfig = plugin.applyPlugins({
|
||||||
dataHandler,
|
|
||||||
errorHandler,
|
|
||||||
requestInterceptors = [],
|
|
||||||
responseInterceptors = [],
|
|
||||||
...otherConfigs
|
|
||||||
} = plugin.applyPlugins({
|
|
||||||
key: 'request',
|
key: 'request',
|
||||||
type: ApplyPluginsType.modify,
|
type: ApplyPluginsType.modify,
|
||||||
initialValue: {},
|
initialValue: {
|
||||||
|
timeout: 10000,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const defaultConfig = Object.assign(
|
return createRequest(defaultConfig);
|
||||||
{
|
|
||||||
timeout: 10000,
|
|
||||||
withCredentials: true,
|
|
||||||
},
|
|
||||||
otherConfigs,
|
|
||||||
);
|
|
||||||
const instance = axios.create(defaultConfig);
|
|
||||||
|
|
||||||
addRequestInterceptors(instance, requestInterceptors);
|
|
||||||
addResponseInterceptors(instance, responseInterceptors);
|
|
||||||
|
|
||||||
// 洋葱模型内部应该这是对数据的处理,避免有副作用调用
|
|
||||||
scheduler.use(paramsProcess).use(genRequestKey).use(cacheControl).use(preventRepeatReq).use(axiosMiddleware);
|
|
||||||
|
|
||||||
return {
|
|
||||||
context: {
|
|
||||||
errorHandler,
|
|
||||||
dataHandler: dataHandler || ((data) => data),
|
|
||||||
instance,
|
|
||||||
defaultConfig,
|
|
||||||
},
|
|
||||||
request: scheduler.compose(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function userConfigHandler(url, data, options = {}) {
|
const currentRequest = getRequestInstance();
|
||||||
options.url = url;
|
|
||||||
options.method = (options.method || 'post').toUpperCase();
|
|
||||||
if (checkHttpRequestHasBody(options.method)) {
|
|
||||||
options.data = data;
|
|
||||||
} else {
|
|
||||||
options.params = data;
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
let currentRequestInstance = null;
|
export const rawRequest = (url, data, options = {}) => {
|
||||||
|
|
||||||
function createContext(userConfig) {
|
|
||||||
return {
|
|
||||||
...currentRequestInstance.context,
|
|
||||||
config: {
|
|
||||||
...currentRequestInstance.context.defaultConfig,
|
|
||||||
...userConfig,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCustomerHandler(ctx, options = {}) {
|
|
||||||
const { dataHandler, errorHandler } = ctx;
|
|
||||||
return {
|
|
||||||
dataHandler: options.dataHandler || dataHandler,
|
|
||||||
errorHandler: options.errorHandler || errorHandler,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export const request = (url, data, options = {}) => {
|
|
||||||
if (typeof options === 'string') {
|
if (typeof options === 'string') {
|
||||||
options = {
|
options = {
|
||||||
method: options,
|
method: options,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (!currentRequestInstance) {
|
return currentRequest(url, data, options);
|
||||||
currentRequestInstance = getRequestInstance();
|
};
|
||||||
}
|
|
||||||
const userConfig = userConfigHandler(url, data, options);
|
|
||||||
const context = createContext(userConfig);
|
|
||||||
const { dataHandler, errorHandler } = getCustomerHandler(context, options);
|
|
||||||
|
|
||||||
return currentRequestInstance.request(context).then(async () => {
|
export const request = async (url, data, options = {}) => {
|
||||||
if (!context.error) {
|
const response = await rawRequest(url, data, options);
|
||||||
return dataHandler(context.response.data, context.response);
|
return response.data;
|
||||||
}
|
|
||||||
errorHandler && errorHandler(context.error);
|
|
||||||
return Promise.reject(context.error);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function isPromiseLike(obj) {
|
function isPromiseLike(obj) {
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
class Scheduler {
|
|
||||||
constructor() {
|
|
||||||
this.middlewares = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
use(fn) {
|
|
||||||
if (typeof fn !== 'function') throw new TypeError('middleware must be a function!');
|
|
||||||
this.middlewares.push(fn);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
compose() {
|
|
||||||
return (context, next) => {
|
|
||||||
let index = -1;
|
|
||||||
const dispatch = (i) => {
|
|
||||||
if (i <= index) return Promise.reject(new Error('next() called multiple times'));
|
|
||||||
index = i;
|
|
||||||
let fn = this.middlewares[i];
|
|
||||||
if (index === this.middlewares.length) fn = next;
|
|
||||||
if (!fn) return Promise.resolve();
|
|
||||||
try {
|
|
||||||
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
|
|
||||||
} catch (e) {
|
|
||||||
return Promise.reject(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return dispatch(0);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new Scheduler();
|
|
35
packages/fes-plugin-request/types.d.ts
vendored
35
packages/fes-plugin-request/types.d.ts
vendored
@ -1,39 +1,18 @@
|
|||||||
import { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
|
import type { Config, ParamsType } from '@qlin/request/dist/interface';
|
||||||
import { Ref } from 'vue';
|
import { Ref } from 'vue';
|
||||||
|
|
||||||
type RequestInterceptor = (value: AxiosRequestConfig) => AxiosRequestConfig | [(value: AxiosRequestConfig) => AxiosRequestConfig, (error: any) => any];
|
export * from '@qlin/request';
|
||||||
type ResponseInterceptor = (value: AxiosResponse) => AxiosResponse | [(value: AxiosResponse) => AxiosResponse, (error: any) => any];
|
|
||||||
|
|
||||||
export type RequestResponse = AxiosResponse;
|
export function request(url: string, data?: ParamsType | null, options?: Partial<Config>): Promise<any>;
|
||||||
export type RequestError = AxiosError & { type: string; msg: string; [key: string]: any };
|
export function rawRequest(url: string, data?: ParamsType | null, options?: Partial<Config>): Promise<any>;
|
||||||
interface RequestPluginOption {
|
|
||||||
mergeRequest?: boolean;
|
|
||||||
dataHandler?(data: any, response: AxiosResponse): any;
|
|
||||||
errorHandler?(error: RequestError): void;
|
|
||||||
cache?:
|
|
||||||
| boolean
|
|
||||||
| {
|
|
||||||
type?: 'ram' | 'sessionStorage' | 'localStorage';
|
|
||||||
cacheTime?: number;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export type RequestOptions = AxiosRequestConfig & RequestPluginOption;
|
|
||||||
|
|
||||||
export function request(url: string, data?: null | Record<string, any>, options?: AxiosRequestConfig & RequestPluginOption): Promise<any>;
|
|
||||||
export function useRequest(
|
export function useRequest(
|
||||||
url: string,
|
url: string,
|
||||||
data?: null | Record<string, any>,
|
data?: null | ParamsType,
|
||||||
options?: AxiosRequestConfig & RequestPluginOption,
|
options?: Partial<Config>,
|
||||||
): { loadingRef: Ref<boolean>; errorRef: Ref<Error>; dataRef: Ref<any> };
|
): { loadingRef: Ref<boolean>; errorRef: Ref<Error>; dataRef: Ref<any> };
|
||||||
|
|
||||||
declare module '@fesjs/fes' {
|
declare module '@fesjs/fes' {
|
||||||
interface PluginRuntimeConfig {
|
interface PluginRuntimeConfig {
|
||||||
request?: {
|
request?: Partial<Config>;
|
||||||
dataHandler?(data: any, response: AxiosResponse): any;
|
|
||||||
errorHandler?(error: RequestError): void;
|
|
||||||
requestInterceptors?: RequestInterceptor[];
|
|
||||||
responseInterceptors?: ResponseInterceptor[];
|
|
||||||
} & AxiosRequestConfig;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ export default (api) => {
|
|||||||
config: {
|
config: {
|
||||||
default: '/',
|
default: '/',
|
||||||
schema(joi) {
|
schema(joi) {
|
||||||
return joi.string().regex(/\/$/).error(new Error('config.publicPath must end with /.'));
|
return joi.string();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
"@ttou/postcss-px-to-viewport": "1.1.4",
|
"@ttou/postcss-px-to-viewport": "1.1.4",
|
||||||
"@fesjs/fes": "^3.0.0-rc.0",
|
"@fesjs/fes": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-icon": "^3.0.0-rc.0",
|
"@fesjs/plugin-icon": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-request": "^3.0.0-rc.0",
|
"@fesjs/plugin-request": "^4.0.0-rc.0",
|
||||||
"@fesjs/builder-vite": "^3.0.0-rc.1",
|
"@fesjs/builder-vite": "^3.0.0-rc.1",
|
||||||
"core-js": "^3.27.0",
|
"core-js": "^3.27.0",
|
||||||
"vue": "^3.2.37"
|
"vue": "^3.2.37"
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
"@fesjs/plugin-model": "^3.0.0-rc.0",
|
"@fesjs/plugin-model": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-monaco-editor": "^3.0.0-rc.0",
|
"@fesjs/plugin-monaco-editor": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-pinia": "^3.0.0-rc.0",
|
"@fesjs/plugin-pinia": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-request": "^3.0.0-rc.0",
|
"@fesjs/plugin-request": "^4.0.0-rc.0",
|
||||||
"@fesjs/plugin-sass": "^3.0.0-rc.0",
|
"@fesjs/plugin-sass": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-windicss": "^3.0.0-rc.0",
|
"@fesjs/plugin-windicss": "^3.0.0-rc.0",
|
||||||
"core-js": "^3.27.0",
|
"core-js": "^3.27.0",
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
"@fesjs/plugin-monaco-editor": "^3.0.0-rc.0",
|
"@fesjs/plugin-monaco-editor": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-pinia": "^3.0.0-rc.0",
|
"@fesjs/plugin-pinia": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-qiankun": "^3.0.0-rc.0",
|
"@fesjs/plugin-qiankun": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-request": "^3.0.0-rc.0",
|
"@fesjs/plugin-request": "^4.0.0-rc.0",
|
||||||
"@fesjs/plugin-sass": "^3.0.0-rc.0",
|
"@fesjs/plugin-sass": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-watermark": "^3.0.0-rc.0",
|
"@fesjs/plugin-watermark": "^3.0.0-rc.0",
|
||||||
"@fesjs/plugin-windicss": "^3.0.0-rc.0",
|
"@fesjs/plugin-windicss": "^3.0.0-rc.0",
|
||||||
@ -67,4 +67,4 @@
|
|||||||
"vuex": "^4.0.0"
|
"vuex": "^4.0.0"
|
||||||
},
|
},
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
48
yarn.lock
48
yarn.lock
@ -2103,6 +2103,14 @@
|
|||||||
resolved "https://registry.npmmirror.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
|
resolved "https://registry.npmmirror.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
|
||||||
integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==
|
integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==
|
||||||
|
|
||||||
|
"@qlin/request@^0.1.1":
|
||||||
|
version "0.1.1"
|
||||||
|
resolved "https://registry.npmmirror.com/@qlin/request/-/request-0.1.1.tgz#265026e2741208640522161eb9621077aae05487"
|
||||||
|
integrity sha512-3bQ3XaD4I4/EYZC15CR1TIHFCWQtZfYz0oleXlf4RS1xIW+7zna3OT5c0VKPiDn/aK1wZAH0mYODChIaRKSciA==
|
||||||
|
dependencies:
|
||||||
|
"@types/lodash-es" "^4.17.6"
|
||||||
|
lodash-es "^4.17.21"
|
||||||
|
|
||||||
"@rollup/plugin-babel@^5.2.0":
|
"@rollup/plugin-babel@^5.2.0":
|
||||||
version "5.3.1"
|
version "5.3.1"
|
||||||
resolved "https://registry.npmmirror.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283"
|
resolved "https://registry.npmmirror.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283"
|
||||||
@ -2571,6 +2579,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/lodash" "*"
|
"@types/lodash" "*"
|
||||||
|
|
||||||
|
"@types/lodash-es@^4.17.6":
|
||||||
|
version "4.17.7"
|
||||||
|
resolved "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.7.tgz#22edcae9f44aff08546e71db8925f05b33c7cc40"
|
||||||
|
integrity sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/lodash" "*"
|
||||||
|
|
||||||
"@types/lodash@*":
|
"@types/lodash@*":
|
||||||
version "4.14.191"
|
version "4.14.191"
|
||||||
resolved "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.191.tgz#09511e7f7cba275acd8b419ddac8da9a6a79e2fa"
|
resolved "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.191.tgz#09511e7f7cba275acd8b419ddac8da9a6a79e2fa"
|
||||||
@ -3696,15 +3711,6 @@ aws4@^1.8.0:
|
|||||||
resolved "https://registry.npmmirror.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
|
resolved "https://registry.npmmirror.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
|
||||||
integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==
|
integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==
|
||||||
|
|
||||||
axios@^1.0.0-alpha.1:
|
|
||||||
version "1.3.4"
|
|
||||||
resolved "https://registry.npmmirror.com/axios/-/axios-1.3.4.tgz#f5760cefd9cfb51fd2481acf88c05f67c4523024"
|
|
||||||
integrity sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==
|
|
||||||
dependencies:
|
|
||||||
follow-redirects "^1.15.0"
|
|
||||||
form-data "^4.0.0"
|
|
||||||
proxy-from-env "^1.1.0"
|
|
||||||
|
|
||||||
babel-jest@^27.0.6, babel-jest@^27.5.1:
|
babel-jest@^27.0.6, babel-jest@^27.5.1:
|
||||||
version "27.5.1"
|
version "27.5.1"
|
||||||
resolved "https://registry.npmmirror.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444"
|
resolved "https://registry.npmmirror.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444"
|
||||||
@ -6156,7 +6162,7 @@ flatted@^3.1.0:
|
|||||||
resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
|
resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
|
||||||
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
|
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
|
||||||
|
|
||||||
follow-redirects@^1.0.0, follow-redirects@^1.15.0:
|
follow-redirects@^1.0.0:
|
||||||
version "1.15.2"
|
version "1.15.2"
|
||||||
resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||||
@ -6182,15 +6188,6 @@ form-data@^3.0.0:
|
|||||||
combined-stream "^1.0.8"
|
combined-stream "^1.0.8"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
form-data@^4.0.0:
|
|
||||||
version "4.0.0"
|
|
||||||
resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
|
||||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
|
||||||
dependencies:
|
|
||||||
asynckit "^0.4.0"
|
|
||||||
combined-stream "^1.0.8"
|
|
||||||
mime-types "^2.1.12"
|
|
||||||
|
|
||||||
form-data@~2.3.2:
|
form-data@~2.3.2:
|
||||||
version "2.3.3"
|
version "2.3.3"
|
||||||
resolved "https://registry.npmmirror.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
resolved "https://registry.npmmirror.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
|
||||||
@ -9588,11 +9585,6 @@ proxy-addr@~2.0.7:
|
|||||||
forwarded "0.2.0"
|
forwarded "0.2.0"
|
||||||
ipaddr.js "1.9.1"
|
ipaddr.js "1.9.1"
|
||||||
|
|
||||||
proxy-from-env@^1.1.0:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
|
||||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
|
||||||
|
|
||||||
prr@~1.0.1:
|
prr@~1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
resolved "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
||||||
@ -11609,10 +11601,10 @@ webpack-virtual-modules@^0.5.0:
|
|||||||
resolved "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz#362f14738a56dae107937ab98ea7062e8bdd3b6c"
|
resolved "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz#362f14738a56dae107937ab98ea7062e8bdd3b6c"
|
||||||
integrity sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==
|
integrity sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==
|
||||||
|
|
||||||
webpack@^5.69.0:
|
webpack@^5.76.2:
|
||||||
version "5.75.0"
|
version "5.76.2"
|
||||||
resolved "https://registry.npmmirror.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152"
|
resolved "https://registry.npmmirror.com/webpack/-/webpack-5.76.2.tgz#6f80d1c1d1e3bf704db571b2504a0461fac80230"
|
||||||
integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==
|
integrity sha512-Th05ggRm23rVzEOlX8y67NkYCHa9nTNcwHPBhdg+lKG+mtiW7XgggjAeeLnADAe7mLjJ6LUNfgHAuRRh+Z6J7w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/eslint-scope" "^3.7.3"
|
"@types/eslint-scope" "^3.7.3"
|
||||||
"@types/estree" "^0.0.51"
|
"@types/estree" "^0.0.51"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user