@ruan-cat/utils 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +26 -9
- package/readme.md +2 -0
- package/src/Prettify.ts +0 -1
- package/src/define-promise-tasks.ts +131 -0
- package/src/index.ts +3 -0
- package/src/simple-promise-tools.ts +55 -0
- package/src/vueuse/useAxios.ts +126 -0
- package/tsconfig.json +4 -9
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ruan-cat/utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "阮喵喵工具集合。一个纯typescript库。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
7
7
|
"types": "./src/index.ts",
|
|
8
|
-
"homepage": "https://
|
|
8
|
+
"homepage": "https://utils.ruancat6312.top",
|
|
9
9
|
"bugs": {
|
|
10
10
|
"url": "https://github.com/ruan-cat/vercel-monorepo-test/issues"
|
|
11
11
|
},
|
|
12
12
|
"repository": {
|
|
13
13
|
"type": "git",
|
|
14
14
|
"url": "git+https://github.com/ruan-cat/vercel-monorepo-test.git",
|
|
15
|
-
"directory": "utils"
|
|
15
|
+
"directory": "packages/utils"
|
|
16
16
|
},
|
|
17
17
|
"exports": {
|
|
18
18
|
".": {
|
|
@@ -35,17 +35,27 @@
|
|
|
35
35
|
},
|
|
36
36
|
"files": [
|
|
37
37
|
"src",
|
|
38
|
+
"!src/tests",
|
|
38
39
|
"tsconfig.json"
|
|
39
40
|
],
|
|
40
41
|
"devDependencies": {
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
42
|
+
"@antfu/utils": "^0.7.10",
|
|
43
|
+
"@types/qs": "^6.9.17",
|
|
44
|
+
"@vueuse/integrations": "^12.1.0",
|
|
45
|
+
"axios": "^1.7.9",
|
|
46
|
+
"qs": "^6.13.1",
|
|
47
|
+
"tsup": "^8.3.5",
|
|
48
|
+
"type-plus": "^7.6.2",
|
|
49
|
+
"typedoc": "^0.27.0",
|
|
50
|
+
"typedoc-plugin-markdown": "^4.3.0",
|
|
51
|
+
"typescript": "5.7.2",
|
|
44
52
|
"unplugin-vue-router": "^0.10.8",
|
|
45
|
-
"@ruan-cat/vuepress-preset-config": "^0.1.
|
|
53
|
+
"@ruan-cat/vuepress-preset-config": "^0.1.14"
|
|
46
54
|
},
|
|
47
55
|
"peerDependencies": {
|
|
48
|
-
"
|
|
56
|
+
"@vueuse/integrations": "^12",
|
|
57
|
+
"axios": "^1.7.x",
|
|
58
|
+
"typescript": "5.7.2",
|
|
49
59
|
"unplugin-vue-router": "^0.10.8"
|
|
50
60
|
},
|
|
51
61
|
"peerDependenciesMeta": {
|
|
@@ -54,12 +64,18 @@
|
|
|
54
64
|
},
|
|
55
65
|
"unplugin-vue-router": {
|
|
56
66
|
"optional": true
|
|
67
|
+
},
|
|
68
|
+
"@vueuse/integrations": {
|
|
69
|
+
"optional": true
|
|
70
|
+
},
|
|
71
|
+
"axios": {
|
|
72
|
+
"optional": true
|
|
57
73
|
}
|
|
58
74
|
},
|
|
59
75
|
"scripts": {
|
|
60
76
|
"copy-readme": "cpx readme.md docs",
|
|
61
77
|
"copy-changelog": "cpx CHANGELOG.md docs",
|
|
62
|
-
"typedoc": "typedoc",
|
|
78
|
+
"typedoc": "typedoc --options typedoc.config.mjs",
|
|
63
79
|
"prettier-docs-(invalid)": "prettier docs/**/*.md --write",
|
|
64
80
|
"docs:dev-main": "vuepress-vite dev docs",
|
|
65
81
|
"docs:dev": "turbo docs:dev",
|
|
@@ -72,6 +88,7 @@
|
|
|
72
88
|
"generate:type-3": "vue-tsc -p tsconfig.types.json",
|
|
73
89
|
"get-type": "pnpm clean:type && pnpm generate:type-3",
|
|
74
90
|
"build:-try-1": "pnpm clean:type && vue-tsc -p tsconfig.build.json",
|
|
91
|
+
"build:tsup": "tsup",
|
|
75
92
|
"rm:node_modules": "rimraf node_modules"
|
|
76
93
|
}
|
|
77
94
|
}
|
package/readme.md
CHANGED
package/src/Prettify.ts
CHANGED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { type SimpleAsyncTask } from "./simple-promise-tools.ts";
|
|
2
|
+
|
|
3
|
+
export const taskTypes = <const>["single", "parallel", "queue"];
|
|
4
|
+
|
|
5
|
+
export type TaskType = (typeof taskTypes)[number];
|
|
6
|
+
|
|
7
|
+
export interface BaseTask {
|
|
8
|
+
/** 任务类型 */
|
|
9
|
+
type: TaskType;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type Task = SimpleAsyncTask | TasksConfig;
|
|
13
|
+
|
|
14
|
+
export interface SingleTasks extends BaseTask {
|
|
15
|
+
type: "single";
|
|
16
|
+
tasks: Task;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ParallelTasks extends BaseTask {
|
|
20
|
+
type: "parallel";
|
|
21
|
+
tasks: Task[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface QueueTasks extends BaseTask {
|
|
25
|
+
type: "queue";
|
|
26
|
+
tasks: Task[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type TasksConfig = SingleTasks | ParallelTasks | QueueTasks;
|
|
30
|
+
|
|
31
|
+
export type PromiseTasksConfig = TasksConfig;
|
|
32
|
+
|
|
33
|
+
function isSingleTasks(config: TasksConfig): config is SingleTasks {
|
|
34
|
+
return config.type === "single";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function isParallelTasks(config: TasksConfig): config is ParallelTasks {
|
|
38
|
+
return config.type === "parallel";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isQueueTasks(config: TasksConfig): config is QueueTasks {
|
|
42
|
+
return config.type === "queue";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function isSimpleAsyncTask(config: Task): config is SimpleAsyncTask {
|
|
46
|
+
return typeof config === "function";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function isTasksConfig(config: Task): config is TasksConfig {
|
|
50
|
+
return typeof config === "object";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 定义异步任务对象
|
|
55
|
+
* @description
|
|
56
|
+
* 这个对象是一揽子异步任务的配置
|
|
57
|
+
*/
|
|
58
|
+
export function definePromiseTasks(config: TasksConfig) {
|
|
59
|
+
return config;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @private 一个工具函数 用于生成异步函数数组
|
|
64
|
+
* @deprecated 在处理串行任务时 疑似有故障
|
|
65
|
+
*/
|
|
66
|
+
function getPromises(tasks: Task[]): ((...args: any) => Promise<any>)[] {
|
|
67
|
+
return tasks.map((task) => {
|
|
68
|
+
return async function (...args: any) {
|
|
69
|
+
if (isSimpleAsyncTask(task)) {
|
|
70
|
+
return await task(...args);
|
|
71
|
+
} else {
|
|
72
|
+
return await executePromiseTasks(task);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 执行异步函数对象
|
|
80
|
+
*/
|
|
81
|
+
export async function executePromiseTasks(
|
|
82
|
+
config: TasksConfig,
|
|
83
|
+
/**
|
|
84
|
+
* 上一次递归执行时提供的参数
|
|
85
|
+
* @description
|
|
86
|
+
* 考虑到递归函数 这里提供了一个参数 用于传递上一次递归执行的结果
|
|
87
|
+
*/
|
|
88
|
+
lastParams: any = null,
|
|
89
|
+
): Promise<any> {
|
|
90
|
+
if (isSingleTasks(config)) {
|
|
91
|
+
if (isSimpleAsyncTask(config.tasks)) {
|
|
92
|
+
// 实际执行的 tasks 往往是无参函数 这里为了保险,故主动传递参数
|
|
93
|
+
return await config.tasks(lastParams);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return await executePromiseTasks(config.tasks, lastParams);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (isParallelTasks(config)) {
|
|
100
|
+
return await Promise.all(
|
|
101
|
+
config.tasks.map((task) => {
|
|
102
|
+
if (isSimpleAsyncTask(task)) {
|
|
103
|
+
// console.log(` 并行任务遇到单独的异步函数 `);
|
|
104
|
+
return task(lastParams);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// console.log(` 并行任务遇到嵌套结构 `);
|
|
108
|
+
return executePromiseTasks(task, lastParams);
|
|
109
|
+
}),
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (isQueueTasks(config)) {
|
|
114
|
+
let res: Awaited<any>;
|
|
115
|
+
for await (const task of config.tasks) {
|
|
116
|
+
if (isSimpleAsyncTask(task)) {
|
|
117
|
+
// console.log(` 串行任务遇到单独的异步函数 `);
|
|
118
|
+
|
|
119
|
+
res = await task(lastParams);
|
|
120
|
+
lastParams = res;
|
|
121
|
+
// console.log(` 串行任务 单独 res `, res);
|
|
122
|
+
} else {
|
|
123
|
+
res = await executePromiseTasks(task, lastParams);
|
|
124
|
+
lastParams = res;
|
|
125
|
+
// console.log(` 串行任务 配置 res `, res);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return res;
|
|
130
|
+
}
|
|
131
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -2,5 +2,8 @@ export * from "./rmmv-class-expand-tools.ts";
|
|
|
2
2
|
export * from "./conditions.ts";
|
|
3
3
|
export * from "./Prettify.ts";
|
|
4
4
|
export * from "./unplugin-vue-router/index.ts";
|
|
5
|
+
export * from "./define-promise-tasks.ts";
|
|
6
|
+
export * from "./simple-promise-tools.ts";
|
|
7
|
+
export * from "./vueuse/useAxios.ts";
|
|
5
8
|
|
|
6
9
|
export * from "./types/pnpm-workspace.yaml.shim.ts";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// import { uniqueId } from "lodash-es";
|
|
2
|
+
// const getCounter = () => uniqueId();
|
|
3
|
+
|
|
4
|
+
/** 创建简单的异步任务 */
|
|
5
|
+
export function generateSimpleAsyncTask<T extends (...args: any) => any>(func: T) {
|
|
6
|
+
// const taskId = getCounter();
|
|
7
|
+
|
|
8
|
+
return function (...args: any) {
|
|
9
|
+
// consola.info(` 这是第 ${taskId} 个异步任务 `);
|
|
10
|
+
// consola.start(" 这里是新创建的异步函数 检查参数: ", ...args);
|
|
11
|
+
|
|
12
|
+
return new Promise<ReturnType<T>>((resolve, reject) => {
|
|
13
|
+
// consola.start(" 内部promise 检查参数: ", ...args);
|
|
14
|
+
resolve(func(...args));
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type SimpleAsyncTask = ReturnType<typeof generateSimpleAsyncTask>;
|
|
20
|
+
|
|
21
|
+
export const initFlag = <const>"initFlag";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 以队列串行的形式 串行运行异步函数
|
|
25
|
+
* @see https://github.com/ascoders/weekly/blob/master/前沿技术/77.精读《用%20Reduce%20实现%20Promise%20串行执行》.md
|
|
26
|
+
* @version 1
|
|
27
|
+
*/
|
|
28
|
+
async function runPromiseByQueueV1<T>(promises: ((...args: any) => Promise<T>)[]) {
|
|
29
|
+
promises.reduce(
|
|
30
|
+
async function (previousPromise, nextPromise, currentIndex) {
|
|
31
|
+
const response = await previousPromise;
|
|
32
|
+
// consola.log(` reduce串行函数 currentIndex= ${currentIndex} res =`, response);
|
|
33
|
+
return await nextPromise(response);
|
|
34
|
+
},
|
|
35
|
+
Promise.resolve(initFlag) as Promise<any>,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 以队列串行的形式 串行运行异步函数
|
|
41
|
+
* @version 2
|
|
42
|
+
*/
|
|
43
|
+
export async function runPromiseByQueue<T>(promises: ((...args: any) => Promise<T>)[]) {
|
|
44
|
+
let response: typeof initFlag | Awaited<T> = initFlag;
|
|
45
|
+
for await (const promise of promises) {
|
|
46
|
+
response = await promise(response);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 以并行的形式 并发运行异步函数
|
|
52
|
+
*/
|
|
53
|
+
export async function runPromiseByConcurrency<T>(promises: ((...args: any) => Promise<T>)[]) {
|
|
54
|
+
await Promise.all(promises.map((promise) => promise()));
|
|
55
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { RequiredPick } from "type-plus";
|
|
2
|
+
import type { AxiosRequestConfig, AxiosResponse, AxiosInstance } from "axios";
|
|
3
|
+
import type { UseAxiosOptions, UseAxiosReturn } from "@vueuse/integrations/useAxios";
|
|
4
|
+
|
|
5
|
+
/** 拓展的类型参数 用于约束必填的字段 */
|
|
6
|
+
export type KeyAxiosRequestConfig<D = any> = keyof AxiosRequestConfig<D>;
|
|
7
|
+
|
|
8
|
+
/** 填写key值的帮助类型 */
|
|
9
|
+
export type KeyHelper<K extends KeyAxiosRequestConfig> = K;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 创建 AxiosRequestConfig 的各种变种类型
|
|
13
|
+
* @description
|
|
14
|
+
* 目前需要给 AxiosRequestConfig 添加必填属性
|
|
15
|
+
*
|
|
16
|
+
* 故需要本工具创建各种变种类型
|
|
17
|
+
*
|
|
18
|
+
* @example CreateAxiosRequestConfig<"url", D>
|
|
19
|
+
*/
|
|
20
|
+
export type CreateAxiosRequestConfig<K extends keyof Target, D = any, Target = AxiosRequestConfig<D>> = RequiredPick<
|
|
21
|
+
Target,
|
|
22
|
+
K
|
|
23
|
+
>;
|
|
24
|
+
|
|
25
|
+
/** 拓展K泛型后的类型 */
|
|
26
|
+
export interface StrictUseAxiosReturn<
|
|
27
|
+
T,
|
|
28
|
+
/**
|
|
29
|
+
* 拓展的类型参数 用于约束必填的字段
|
|
30
|
+
* @description
|
|
31
|
+
* 这里不需要提供默认的取值
|
|
32
|
+
*/
|
|
33
|
+
K extends KeyAxiosRequestConfig<D>,
|
|
34
|
+
R,
|
|
35
|
+
D,
|
|
36
|
+
> extends UseAxiosReturn<T, R, D> {
|
|
37
|
+
/**
|
|
38
|
+
* Manually call the axios request
|
|
39
|
+
*/
|
|
40
|
+
execute: (
|
|
41
|
+
url?: string | CreateAxiosRequestConfig<K, D>,
|
|
42
|
+
config?: CreateAxiosRequestConfig<K, D>,
|
|
43
|
+
) => Promise<StrictUseAxiosReturn<T, K, R, D>>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 拓展类型参数后的 useAxios 函数
|
|
48
|
+
* @description
|
|
49
|
+
* 在我们的封装中 使用本类型
|
|
50
|
+
*/
|
|
51
|
+
export declare function useAxios<
|
|
52
|
+
T = any,
|
|
53
|
+
/** 拓展的类型参数 用于约束必填的字段 */
|
|
54
|
+
K extends KeyAxiosRequestConfig<D> = "url",
|
|
55
|
+
R = AxiosResponse<T>,
|
|
56
|
+
D = any,
|
|
57
|
+
>(
|
|
58
|
+
url: string,
|
|
59
|
+
config: AxiosRequestConfig<D>,
|
|
60
|
+
instance: AxiosInstance,
|
|
61
|
+
options?: UseAxiosOptions,
|
|
62
|
+
): StrictUseAxiosReturn<T, K, R, D> & Promise<StrictUseAxiosReturn<T, K, R, D>>;
|
|
63
|
+
|
|
64
|
+
/** 包装器的参数 */
|
|
65
|
+
export interface UseAxiosWrapperParams<
|
|
66
|
+
/**
|
|
67
|
+
* 业务数据类型
|
|
68
|
+
* @description
|
|
69
|
+
* 必须先填写业务类型
|
|
70
|
+
*/
|
|
71
|
+
T = any,
|
|
72
|
+
/**
|
|
73
|
+
* AxiosRequestConfig 默认必填的字段
|
|
74
|
+
* @description
|
|
75
|
+
* 用于约束其他类型的字段
|
|
76
|
+
*
|
|
77
|
+
* 然后才能填写必传的参数类型
|
|
78
|
+
*
|
|
79
|
+
* 默认为 必填url请求地址的 config 请求配置
|
|
80
|
+
*/
|
|
81
|
+
K extends KeyAxiosRequestConfig<D> = "url",
|
|
82
|
+
/**
|
|
83
|
+
* UseAxiosOptions 的派生类型
|
|
84
|
+
*/
|
|
85
|
+
UseAxiosOptionsLike extends UseAxiosOptions = UseAxiosOptions,
|
|
86
|
+
/**
|
|
87
|
+
* AxiosRequestConfig 用的类型
|
|
88
|
+
* @description
|
|
89
|
+
* 最后才可以传递此类型
|
|
90
|
+
*/
|
|
91
|
+
D = any,
|
|
92
|
+
> {
|
|
93
|
+
/**
|
|
94
|
+
* axios的配置类型
|
|
95
|
+
* @description
|
|
96
|
+
* 默认为 必填url请求地址的 config 请求配置
|
|
97
|
+
*/
|
|
98
|
+
config: CreateAxiosRequestConfig<K, D>;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* axios实例
|
|
102
|
+
* @description
|
|
103
|
+
* 对于包装器函数而言 必须传递有意义的请求实例
|
|
104
|
+
*/
|
|
105
|
+
instance: AxiosInstance;
|
|
106
|
+
|
|
107
|
+
/** useAxios 的选项配置 */
|
|
108
|
+
options: UseAxiosOptionsLike;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* useAxios 的包装函数
|
|
113
|
+
* @description
|
|
114
|
+
* 其本质是对 useAxios 函数的封装,仅仅是包装了参数层
|
|
115
|
+
*
|
|
116
|
+
* 预期设计成一个万能的 通用的请求函数
|
|
117
|
+
*/
|
|
118
|
+
export function useAxiosWrapper<T, K extends KeyAxiosRequestConfig, D = any>(params: UseAxiosWrapperParams) {
|
|
119
|
+
const {
|
|
120
|
+
config: { url },
|
|
121
|
+
config,
|
|
122
|
+
instance,
|
|
123
|
+
options,
|
|
124
|
+
} = params;
|
|
125
|
+
return useAxios<T, K, AxiosResponse<T>, D>(url, config, instance, options);
|
|
126
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -33,21 +33,16 @@
|
|
|
33
33
|
"typedoc",
|
|
34
34
|
"typedoc-plugin-markdown",
|
|
35
35
|
],
|
|
36
|
-
"paths": {
|
|
37
|
-
"@/*": [
|
|
38
|
-
"./src/*"
|
|
39
|
-
]
|
|
40
|
-
}
|
|
41
36
|
},
|
|
42
37
|
"include": [
|
|
43
38
|
"./src/**/*.ts",
|
|
44
|
-
"./tests/**/*.ts",
|
|
45
39
|
"./src/**/*.js",
|
|
46
|
-
"./tests/**/*.
|
|
47
|
-
//
|
|
48
|
-
"./tests/with-types/types/CanNewTypeByClass.d.ts",
|
|
40
|
+
// "./tests/**/*.ts",
|
|
41
|
+
// "./tests/**/*.js",
|
|
49
42
|
],
|
|
50
43
|
"exclude": [
|
|
44
|
+
// 测试用例的全部文件 交由本项目根目录下的 tsconfig.json 处理
|
|
45
|
+
"src/tests/**/*.ts",
|
|
51
46
|
"notuse-typedoc.config.cjs"
|
|
52
47
|
]
|
|
53
48
|
}
|