feat: change request to fetch

This commit is contained in:
winixt 2023-04-01 15:59:37 +08:00
parent 35be9b4aa6
commit 21c404aa07
12 changed files with 198 additions and 649 deletions

View File

@ -1,6 +1,6 @@
# @fesjs/plugin-request
基于 axios 封装的 request内置防止重复请求、请求缓存、错误处理等功能。
基于 fetch 封装的 request内置防止重复请求、请求缓存、错误处理等功能。
## 启用方式
@ -10,35 +10,39 @@
{
"dependencies": {
"@fesjs/fes": "^3.0.0",
"@fesjs/plugin-request": "^3.0.0"
"@fesjs/plugin-request": "^4.0.0-beta.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
import { defineRuntimeConfig } from '@fesjs/fes';
export default defineRuntimeConfig({
request: {
// API 前缀
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') {
FMesseage.error('hello world');
return Promise.reject(data);
}
if (data.code === '20000') {
FMesseage.error('hello world');
}
throw new Error(response);
return data?.result ? data.result : data;
}
// 响应数据格式化
return data?.result ? data.result : data;
return data;
},
// http 异常,和插件异常
errorHandler(error) {
@ -47,13 +51,7 @@ export default defineRuntimeConfig({
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// 请求已经成功发起,但没有收到响应
// `error.request` 在浏览器中是 XMLHttpRequest 的实例,
// 而在node.js中是 http.ClientRequest 的实例
console.log(error.request);
} else if (error.type) {
// 插件异常
} else if (error.msg) {
console.log(error.msg);
} else {
// 发送请求时出了点问题
@ -61,11 +59,7 @@ export default defineRuntimeConfig({
}
console.log(error.config);
},
// 请求拦截器
requestInterceptors: [],
// 响应拦截器
responseInterceptors: [],
// 支持其他 axios 配置
// 支持其他 fetch 配置
...otherConfigs,
},
});
@ -82,7 +76,7 @@ export default defineRuntimeConfig({
- url: 后端接口 url
- 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
@ -148,7 +142,7 @@ request(
password: '123456',
},
{
cache: {
cacheData: {
cacheType: 'ram', // ram: 内存session: sessionStoragelocallocalStorage
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 使用
@ -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 特有的配置不在支持

View File

@ -28,12 +28,12 @@
"access": "public"
},
"peerDependencies": {
"@fesjs/fes": "^3.0.0",
"vue": "^3.2.47"
"@fesjs/fes": "3.0.0-rc.5",
"vue": "^3.2.37"
},
"dependencies": {
"@fesjs/utils": "^3.0.0",
"axios": "^1.0.0-alpha.1"
"@fesjs/utils": "3.0.0-rc.2",
"@qlin/request": "^0.1.2"
},
"typings": "./types.d.ts"
}

View File

@ -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
* 只缓存参数类型为: stringplain objectURLSearchParams 或者无参数的 请求
*/
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);
}
}
};

View File

@ -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();
}

View File

@ -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);
}
});
}
}

View File

@ -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();
};

View File

@ -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);
}
};

View File

@ -1,131 +1,34 @@
import axios from 'axios';
import { ApplyPluginsType, plugin } from '@fesjs/fes';
import { ref } from 'vue';
import scheduler from './scheduler';
import { checkHttpRequestHasBody, isFunction } from './helpers';
import { ref, shallowRef } from 'vue';
import paramsProcess from './paramsProcess';
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();
}
import { createRequest } from '@qlin/request';
function getRequestInstance() {
const {
dataHandler,
errorHandler,
requestInterceptors = [],
responseInterceptors = [],
...otherConfigs
} = plugin.applyPlugins({
const defaultConfig = plugin.applyPlugins({
key: 'request',
type: ApplyPluginsType.modify,
initialValue: {},
initialValue: {
timeout: 10000,
},
});
const defaultConfig = Object.assign(
{
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(),
};
return createRequest(defaultConfig);
}
function userConfigHandler(url, data, options = {}) {
options.url = url;
options.method = (options.method || 'post').toUpperCase();
if (checkHttpRequestHasBody(options.method)) {
options.data = data;
} else {
options.params = data;
}
return options;
}
const currentRequest = getRequestInstance();
let currentRequestInstance = null;
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 = {}) => {
export const rawRequest = (url, data, options = {}) => {
if (typeof options === 'string') {
options = {
method: options,
};
}
if (!currentRequestInstance) {
currentRequestInstance = getRequestInstance();
}
const userConfig = userConfigHandler(url, data, options);
const context = createContext(userConfig);
const { dataHandler, errorHandler } = getCustomerHandler(context, options);
return currentRequest(url, data, options);
};
return currentRequestInstance.request(context).then(async () => {
if (!context.error) {
return dataHandler(context.response.data, context.response);
}
errorHandler && errorHandler(context.error);
return Promise.reject(context.error);
});
export const request = async (url, data, options = {}) => {
const response = await rawRequest(url, data, options);
return response.data;
};
function isPromiseLike(obj) {
@ -135,7 +38,7 @@ function isPromiseLike(obj) {
export const useRequest = (url, data, options = {}) => {
const loadingRef = ref(true);
const errorRef = ref(null);
const dataRef = ref(null);
const dataRef = shallowRef(null);
let promise;
if (isPromiseLike(url)) {
promise = url;

View File

@ -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();

View File

@ -1,39 +1,18 @@
import { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
import type { Config, ParamsType } from '@qlin/request/dist/interface';
import { Ref } from 'vue';
type RequestInterceptor = (value: AxiosRequestConfig) => AxiosRequestConfig | [(value: AxiosRequestConfig) => AxiosRequestConfig, (error: any) => any];
type ResponseInterceptor = (value: AxiosResponse) => AxiosResponse | [(value: AxiosResponse) => AxiosResponse, (error: any) => any];
export * from '@qlin/request';
export type RequestResponse = AxiosResponse;
export type RequestError = AxiosError & { type: string; msg: string; [key: string]: any };
interface RequestPluginOption {
mergeRequest?: boolean;
dataHandler?(data: any, response: AxiosResponse): any;
errorHandler?(error: RequestError): void;
cache?:
| boolean
| {
cacheType?: '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 request(url: string, data?: ParamsType | null, options?: Partial<Config>): Promise<any>;
export function rawRequest(url: string, data?: ParamsType | null, options?: Partial<Config>): Promise<any>;
export function useRequest(
url: string,
data?: null | Record<string, any>,
options?: AxiosRequestConfig & RequestPluginOption,
data?: null | ParamsType,
options?: Partial<Config>,
): { loadingRef: Ref<boolean>; errorRef: Ref<Error>; dataRef: Ref<any> };
declare module '@fesjs/fes' {
interface PluginRuntimeConfig {
request?: {
dataHandler?(data: any, response: AxiosResponse): any;
errorHandler?(error: RequestError): void;
requestInterceptors?: RequestInterceptor[];
responseInterceptors?: ResponseInterceptor[];
} & AxiosRequestConfig;
request?: Partial<Config>;
}
}

164
pnpm-lock.yaml generated
View File

@ -613,16 +613,16 @@ importers:
packages/fes-plugin-request:
dependencies:
'@fesjs/fes':
specifier: ^3.0.0
version: link:../fes
specifier: 3.0.0-rc.5
version: 3.0.0-rc.5(vue@3.2.47)
'@fesjs/utils':
specifier: ^3.0.0
version: link:../fes-utils
axios:
specifier: ^1.0.0-alpha.1
version: 1.0.0-alpha.1
specifier: 3.0.0-rc.2
version: 3.0.0-rc.2
'@qlin/request':
specifier: ^0.1.2
version: 0.1.2
vue:
specifier: ^3.2.47
specifier: ^3.2.37
version: 3.2.47
packages/fes-plugin-sass:
@ -2827,7 +2827,7 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
ajv: 6.12.6
debug: 4.3.2
debug: 4.3.4
espree: 9.5.1
globals: 13.20.0
ignore: 5.2.4
@ -2844,6 +2844,23 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@fesjs/compiler@3.0.0-rc.3:
resolution: {integrity: sha512-LlrvEl+4ylfdW5+35JtJ+2IipLEH1YqKo29wWG6ZrMy9vyW9i0u/j12C3PqLlzKa7LikMGYTMv4k4KdjX6ie7w==}
dependencies:
'@babel/core': 7.21.3
'@babel/preset-env': 7.20.2(@babel/core@7.21.3)
'@babel/register': 7.21.0(@babel/core@7.21.3)
'@fesjs/utils': 3.0.0-rc.2
commander: 7.2.0
dotenv: 8.2.0
joi: 17.3.0
readline: 1.3.0
set-value: 3.0.2
tapable: 2.2.0
transitivePeerDependencies:
- supports-color
dev: false
/@fesjs/fes-design@0.7.20(vue@3.2.47):
resolution: {integrity: sha512-XEyi1GLOLwCuGi2S0MGnwMGHoSDQ2XXjOgnzxrRz+z7XmC4jA/P+5Z2Q82J1F1D4lRxNAzzRjFQlfM+hNoLblA==}
peerDependencies:
@ -2867,6 +2884,23 @@ packages:
- '@vue/composition-api'
dev: false
/@fesjs/fes@3.0.0-rc.5(vue@3.2.47):
resolution: {integrity: sha512-dtNeVruuNgaJktjiZFkRDzVes3JfZu/7NetukkGCdrYY3eubuXz5Z7aNvbhQqHMsAWLsevy+YCy3qrjdiG5thw==}
engines: {node: ^10.12.0 || ^12.0.0 || >= 14.0.0}
hasBin: true
dependencies:
'@fesjs/compiler': 3.0.0-rc.3
'@fesjs/preset-built-in': 3.0.0-rc.5(vue@3.2.47)
'@fesjs/runtime': 3.0.0-rc.2(vue@3.2.47)
'@fesjs/utils': 3.0.0-rc.2
pirates: 4.0.5
resolve-cwd: 3.0.0
vue-router: 4.1.6(vue@3.2.47)
transitivePeerDependencies:
- supports-color
- vue
dev: false
/@fesjs/plugin-qiankun@3.0.0-rc.0(@fesjs/fes-design@0.7.20)(@fesjs/fes@packages+fes)(vue@3.2.47):
resolution: {integrity: sha512-qFQ3cDBmGJYZPbc8Mu4ZVodm+/Q8g1rIPRAg24cxVybVc1taA0YbGo8FefQayyaUTxFLtYp921TYWytzGDNJRg==}
peerDependencies:
@ -2899,6 +2933,31 @@ packages:
- supports-color
dev: false
/@fesjs/preset-built-in@3.0.0-rc.5(vue@3.2.47):
resolution: {integrity: sha512-PK4l66aCwPGthUQNRL+btmEejynTIW0jztWTQFtOEHuyTbfZvQSq0FEiVBdANSSnFC8iHsjlBx2f0WpUjbUKMw==}
peerDependencies:
vue: ^3.2.37
dependencies:
'@fesjs/compiler': 3.0.0-rc.3
'@fesjs/utils': 3.0.0-rc.2
'@vue/compiler-sfc': 3.2.47
envinfo: 7.8.1
express: 4.17.3
mockjs: 1.1.0
vue: 3.2.47
transitivePeerDependencies:
- supports-color
dev: false
/@fesjs/runtime@3.0.0-rc.2(vue@3.2.47):
resolution: {integrity: sha512-dvV9+eQ6bfDaeTLhDI7P7hTd3uCswze4Wa866dJEHzXfkR31W7oog7Q/CSX+mo++5UHVa2kuHamm1MFaPvkijw==}
peerDependencies:
vue: ^3.2.37
dependencies:
vue: 3.2.47
vue-router: 4.1.6(vue@3.2.47)
dev: false
/@fesjs/utils@3.0.0-rc.2:
resolution: {integrity: sha512-kZlFvKZtuw77Xd4gru0uHMWB13lTWvpSQzMhfD4UnPBQQhtpGZrDWX/7ik/qafdxPkZ3ovwPbirScrCMHdPvNw==}
dependencies:
@ -2949,7 +3008,7 @@ packages:
engines: {node: '>=10.10.0'}
dependencies:
'@humanwhocodes/object-schema': 1.2.1
debug: 4.3.2
debug: 4.3.4
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
@ -3401,6 +3460,13 @@ packages:
resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==}
dev: false
/@qlin/request@0.1.2:
resolution: {integrity: sha512-iHkkFQjNuutRIEatYcfWpSimQO9SumOvM5mcDJ6zLr4zLyXTqMlWaRXvORmvlt+DCbc/k8m2fi9DDXaUQb2TqQ==}
dependencies:
'@types/lodash-es': 4.17.7
lodash-es: 4.17.21
dev: false
/@rollup/plugin-babel@5.3.1(@babel/core@7.21.3)(rollup@2.79.1):
resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==}
engines: {node: '>= 10.0.0'}
@ -3429,7 +3495,7 @@ packages:
builtin-modules: 3.3.0
deepmerge: 4.2.2
is-module: 1.0.0
resolve: 1.20.0
resolve: 1.22.1
rollup: 2.79.1
dev: true
@ -4802,7 +4868,7 @@ packages:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'}
dependencies:
debug: 4.3.2
debug: 4.3.4
transitivePeerDependencies:
- supports-color
dev: false
@ -5081,16 +5147,6 @@ packages:
engines: {node: '>= 0.4'}
dev: true
/axios@1.0.0-alpha.1:
resolution: {integrity: sha512-p+meG161943WT+K7sJYquHR46xxi/z0tk7vnSmEf/LrfEAyiP+0uTMMYk1OEo1IRF18oGRhnFxN1y8fLcXaTMw==}
dependencies:
follow-redirects: 1.15.2
form-data: 4.0.0
proxy-from-env: 1.1.0
transitivePeerDependencies:
- debug
dev: false
/babel-jest@27.0.6(@babel/core@7.21.3):
resolution: {integrity: sha512-iTJyYLNc4wRofASmofpOc5NK9QunwMk+TLFgGXsTFS8uEqmd8wdI7sga0FPe2oVH3b5Agt/EAK1QjPEuKL8VfA==}
engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
@ -5505,6 +5561,7 @@ packages:
/chalk@5.0.1:
resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
dev: false
/chalk@5.2.0:
resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==}
@ -5851,7 +5908,7 @@ packages:
dev: false
/concat-map@0.0.1:
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=, tarball: https://registry.npmmirror.com/concat-map/download/concat-map-0.0.1.tgz}
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
/confusing-browser-globals@1.0.11:
resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==}
@ -7367,7 +7424,7 @@ packages:
dependencies:
eslint-plugin-import: 2.25.3(eslint@8.37.0)
glob-parent: 5.1.2
resolve: 1.20.0
resolve: 1.22.1
dev: true
/eslint-import-resolver-node@0.3.7:
@ -7451,7 +7508,7 @@ packages:
is-glob: 4.0.3
minimatch: 3.1.2
object.values: 1.1.6
resolve: 1.20.0
resolve: 1.22.1
tsconfig-paths: 3.14.2
transitivePeerDependencies:
- eslint-import-resolver-typescript
@ -7470,7 +7527,7 @@ packages:
eslint-utils: 2.1.0
ignore: 5.2.4
minimatch: 3.1.2
resolve: 1.20.0
resolve: 1.22.1
semver: 6.3.0
dev: true
@ -7502,7 +7559,7 @@ packages:
natural-compare: 1.4.0
nth-check: 2.1.1
postcss-selector-parser: 6.0.11
semver: 7.3.6
semver: 7.3.8
vue-eslint-parser: 8.3.0(eslint@8.37.0)
transitivePeerDependencies:
- supports-color
@ -7570,7 +7627,7 @@ packages:
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
debug: 4.3.2
debug: 4.3.4
doctrine: 3.0.0
escape-string-regexp: 4.0.0
eslint-scope: 7.1.1
@ -8040,17 +8097,8 @@ packages:
mime-types: 2.1.35
dev: false
/form-data@4.0.0:
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
engines: {node: '>= 6'}
dependencies:
asynckit: 0.4.0
combined-stream: 1.0.8
mime-types: 2.1.35
dev: false
/forwarded@0.2.0:
resolution: {integrity: sha1-ImmTZCiq1MFcfr6XeahL8LKoGBE=, tarball: https://registry.npmmirror.com/forwarded/download/forwarded-0.2.0.tgz}
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
engines: {node: '>= 0.6'}
dev: false
@ -8621,7 +8669,7 @@ packages:
dependencies:
'@tootallnate/once': 1.1.2
agent-base: 6.0.2
debug: 4.3.2
debug: 4.3.4
transitivePeerDependencies:
- supports-color
dev: false
@ -8661,7 +8709,7 @@ packages:
engines: {node: '>= 6'}
dependencies:
agent-base: 6.0.2
debug: 4.3.2
debug: 4.3.4
transitivePeerDependencies:
- supports-color
dev: false
@ -9191,7 +9239,7 @@ packages:
resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==}
engines: {node: '>=10'}
dependencies:
debug: 4.3.2
debug: 4.3.4
istanbul-lib-coverage: 3.2.0
source-map: 0.6.1
transitivePeerDependencies:
@ -9535,7 +9583,7 @@ packages:
jest-pnp-resolver: 1.2.3(jest-resolve@27.5.1)
jest-util: 27.5.1
jest-validate: 27.5.1
resolve: 1.20.0
resolve: 1.22.1
resolve.exports: 1.1.1
slash: 3.0.0
dev: false
@ -9635,7 +9683,7 @@ packages:
jest-util: 27.5.1
natural-compare: 1.4.0
pretty-format: 27.5.1
semver: 7.3.6
semver: 7.3.8
transitivePeerDependencies:
- supports-color
dev: false
@ -10167,7 +10215,7 @@ packages:
resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==}
engines: {node: '>=12'}
dependencies:
chalk: 5.0.1
chalk: 5.2.0
is-unicode-supported: 1.3.0
/log-update@4.0.0:
@ -10205,6 +10253,7 @@ packages:
/lru-cache@7.18.3:
resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==}
engines: {node: '>=12'}
dev: false
/magic-string@0.25.9:
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
@ -10300,7 +10349,7 @@ packages:
resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
/media-typer@0.3.0:
resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=, tarball: https://registry.npmmirror.com/media-typer/download/media-typer-0.3.0.tgz}
resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==}
engines: {node: '>= 0.6'}
dev: false
@ -10653,7 +10702,7 @@ packages:
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
dependencies:
hosted-git-info: 2.8.9
resolve: 1.20.0
resolve: 1.22.1
semver: 5.7.1
validate-npm-package-license: 3.0.4
@ -10663,7 +10712,7 @@ packages:
dependencies:
hosted-git-info: 4.1.0
is-core-module: 2.11.0
semver: 7.3.6
semver: 7.3.8
validate-npm-package-license: 3.0.4
/normalize-path@3.0.0:
@ -10855,7 +10904,7 @@ packages:
resolution: {integrity: sha512-1/D8uRFY0ay2kgBpmAwmSA404w4OoPVhHMqRqtjvrcK/dnzcEZxMJ+V4DUbyICu8IIVRclHcOf5wlD1tMY4GUQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
chalk: 5.0.1
chalk: 5.2.0
cli-cursor: 4.0.0
cli-spinners: 2.7.0
is-interactive: 2.0.0
@ -11648,10 +11697,6 @@ packages:
ipaddr.js: 1.9.1
dev: false
/proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
dev: false
/prr@1.0.1:
resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
dev: false
@ -12134,7 +12179,7 @@ packages:
engines: {node: '>=12.0.0'}
hasBin: true
dependencies:
chokidar: 3.5.2
chokidar: 3.5.3
immutable: 4.3.0
source-map-js: 1.0.2
dev: false
@ -12207,6 +12252,7 @@ packages:
hasBin: true
dependencies:
lru-cache: 7.18.3
dev: false
/semver@7.3.8:
resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==}
@ -12295,7 +12341,7 @@ packages:
dev: false
/setprototypeof@1.1.0:
resolution: {integrity: sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=, tarball: https://registry.npmmirror.com/setprototypeof/download/setprototypeof-1.1.0.tgz}
resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==}
dev: false
/setprototypeof@1.2.0:
@ -12513,7 +12559,7 @@ packages:
/spdy-transport@3.0.0:
resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==}
dependencies:
debug: 4.3.2
debug: 4.3.4
detect-node: 2.1.0
hpack.js: 2.1.6
obuf: 1.1.2
@ -12527,7 +12573,7 @@ packages:
resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==}
engines: {node: '>=6.0.0'}
dependencies:
debug: 4.3.2
debug: 4.3.4
handle-thing: 2.0.1
http-deceiver: 1.2.7
select-hose: 2.0.0
@ -13028,7 +13074,7 @@ packages:
dev: true
/toidentifier@1.0.1:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==, tarball: https://registry.npmmirror.com/toidentifier/download/toidentifier-1.0.1.tgz}
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
dev: false
@ -13563,14 +13609,14 @@ packages:
peerDependencies:
eslint: '>=6.0.0'
dependencies:
debug: 4.3.2
debug: 4.3.4
eslint: 8.37.0
eslint-scope: 7.1.1
eslint-visitor-keys: 3.4.0
espree: 9.5.1
esquery: 1.5.0
lodash: 4.17.21
semver: 7.3.6
semver: 7.3.8
transitivePeerDependencies:
- supports-color
dev: true

View File

@ -13,14 +13,17 @@ import buildConfig from '../build.config.js';
const { prompt } = enquirer;
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const { preid, dry: isDryRun } = minimist(process.argv.slice(2));
const { preid: preId, dry: isDryRun } = minimist(process.argv.slice(2));
const packages = buildConfig.pkgs;
const versionIncrements = ['patch', 'minor', 'major', 'prepatch', 'preminor', 'premajor', 'prerelease'];
const incVersion = (version, i) => {
const preId = preid || semver.prerelease(version)[0];
return semver.inc(version, i, preId);
let _preId = preId || semver.prerelease(version)?.[0];
if (!_preId && /pre/.test(i)) {
_preId = 'beta';
}
return semver.inc(version, i, _preId);
};
const autoIncVersion = (version) => {
if (version.includes('-')) {