@whitesev/utils 2.11.10 → 2.11.12

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.
@@ -45,14 +45,22 @@ declare class Utils {
45
45
  asyncReplaceAll(string: string, pattern: RegExp | string, asyncFn: (item: string) => Promise<string>): Promise<string>;
46
46
  /**
47
47
  * ajax劫持库,支持xhr和fetch劫持。
48
- * + 来源:https://bbs.tampermonkey.net.cn/thread-3284-1-1.html
49
- * + 作者:cxxjackie
50
- * + 版本:1.4.8
51
- * + 旧版本:1.2.4
52
- * + 文档:https://scriptcat.org/zh-CN/script-show-page/637/
53
- * @param useOldVersion 是否使用旧版本,默认false
48
+ * + 来源: https://bbs.tampermonkey.net.cn/thread-3284-1-1.html
49
+ * + 作者: cxxjackie
50
+ * + 实现方式: Proxy
51
+ * + 版本: `1.4.8`
52
+ * + 文档: https://scriptcat.org/zh-CN/script-show-page/637/
54
53
  */
55
- ajaxHooker: (useOldVersion?: boolean) => UtilsAjaxHookResult;
54
+ ajaxHooker: () => UtilsAjaxHookResult;
55
+ /**
56
+ * ajax劫持库,支持xhr和fetch劫持。
57
+ * + 来源: https://bbs.tampermonkey.net.cn/thread-3284-1-1.html
58
+ * + 作者: cxxjackie
59
+ * + 实现方式: Object.defineProperty
60
+ * + 版本: `1.2.4`
61
+ * + 文档: https://scriptcat.org/zh-CN/script-show-page/637/
62
+ */
63
+ oldAjaxHooker: () => UtilsAjaxHookResult;
56
64
  /**
57
65
  * 根据坐标点击canvas元素的内部位置
58
66
  * @param canvasElement 画布元素
@@ -1002,9 +1010,14 @@ declare class Utils {
1002
1010
  */
1003
1011
  config?: MutationObserverInit;
1004
1012
  /**
1005
- * 是否主动触发一次
1013
+ * (可选)是否主动触发一次
1006
1014
  */
1007
1015
  immediate?: boolean;
1016
+ /**
1017
+ * (可选)是否仅触发一次
1018
+ * @default false
1019
+ */
1020
+ once?: boolean;
1008
1021
  /**
1009
1022
  * 触发的回调函数
1010
1023
  */
@@ -1012,7 +1025,7 @@ declare class Utils {
1012
1025
  }): MutationObserver;
1013
1026
  /**
1014
1027
  * 使用观察器观察元素出现在视图内,出现的话触发回调
1015
- * @param target 目标元素
1028
+ * @param $el 目标元素
1016
1029
  * @param callback 触发的回调
1017
1030
  * @param options 观察器配置
1018
1031
  * @example
@@ -1020,7 +1033,12 @@ declare class Utils {
1020
1033
  * console.log("该元素出现在视图内");
1021
1034
  * }))
1022
1035
  */
1023
- mutationVisible(target: Element | Element[], callback: (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => void, options?: IntersectionObserverInit): void;
1036
+ mutationVisible($el: Element | Element[], callback: (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => void, options?: IntersectionObserverInit & {
1037
+ /** (可选)是否主动触发一次,默认false */
1038
+ immediate?: boolean;
1039
+ /** (可选)是否仅触发一次,默认false */
1040
+ once?: boolean;
1041
+ }): IntersectionObserver;
1024
1042
  /**
1025
1043
  * 去除全局window下的Utils,返回控制权
1026
1044
  * @example
@@ -1346,8 +1364,16 @@ declare class Utils {
1346
1364
  toSearchParamsStr(obj: object | object[], addPrefix?: boolean): string;
1347
1365
  /**
1348
1366
  * 将UrlSearchParams格式的字符串转为对象
1367
+ * @param searhParamsStr 字符串或对象
1368
+ * @example
1369
+ * Utils.searchParamStrToObj("xxx=xx&xx2=xx2")
1370
+ * @example
1371
+ * Utils.searchParamStrToObj(new URLSearchParams({
1372
+ * test1: 1,
1373
+ * test2: 2
1374
+ * }))
1349
1375
  */
1350
- searchParamStrToObj<T>(searhParamsStr?: string | null | undefined): T;
1376
+ searchParamStrToObj<T = any>(searhParamsStr?: string | null | undefined | URLSearchParams): T;
1351
1377
  /**
1352
1378
  * 提供一个封装了 try-catch 的函数,可以执行传入的函数并捕获其可能抛出的错误,并通过传入的错误处理函数进行处理。
1353
1379
  * @example
@@ -1,6 +1,12 @@
1
1
  export function ajaxHooker(): {
2
- hook: (fn: any) => number;
3
- filter: (arr: any) => void;
2
+ hook: (fn: any) => {
3
+ remove: () => boolean;
4
+ };
5
+ filter: (arr: any) => {
6
+ remove: () => void;
7
+ };
4
8
  protect: () => void;
5
9
  unhook: () => void;
10
+ removeHook: (fn: (request: import("./../types/ajaxHooker.d.ts").UtilsAjaxHookRequestOptions) => void | undefined | null | Promise<void | undefined | null>, onlyRemove: boolean) => boolean;
11
+ removeFilter: () => void;
6
12
  };
@@ -1,6 +1,12 @@
1
1
  export function AjaxHooker1_2_4(): {
2
- hook: (fn: any) => number;
3
- filter: (arr: any) => void;
2
+ hook: (fn: any) => {
3
+ remove: () => boolean;
4
+ };
5
+ filter: (arr: any) => {
6
+ remove: () => void;
7
+ };
4
8
  protect: () => void;
5
9
  unhook: () => void;
10
+ removeHook: (fn: (request: import("./../types/ajaxHooker.d.ts").UtilsAjaxHookRequestOptions) => void | undefined | null | Promise<void | undefined | null>, onlyRemove: boolean) => boolean;
11
+ removeFilter: () => void;
6
12
  };
@@ -1052,30 +1052,30 @@ export declare interface HttpxRequestOption {
1052
1052
  */
1053
1053
  data?: string | FormData | object;
1054
1054
  /**
1055
- * 是否自动对data进行处理
1055
+ * 是否自动对`data`进行处理
1056
1056
  *
1057
1057
  * ## 处理以下请求类型
1058
- * + `GET` 自动进行`URLSearchParams`转换
1059
- * + `HEAD` 自动进行`URLSearchParams`转换
1060
- * + `POST` 处理`Content-Type`不为空的情况
1058
+ * + 当请求类型为`GET`,自动进行`URLSearchParams`转换
1059
+ * + 当请求类型为`HEAD`,自动进行`URLSearchParams`转换
1060
+ * + 当请求类型为`POST`,根据下面的`Content-Type`类型来处理(`Content-Type`不为空才会处理)
1061
1061
  *
1062
- * ### `application/json`
1062
+ * ### `POST` => `Content-Type` => `application/json`
1063
1063
  *
1064
- * + `string`: 不做处理
1065
- * + `FormData`: 转为`JSON`并进行`JSON.stringify`处理
1066
- * + `object`: 进行`JSON.stringify`处理
1064
+ * + `data: string`: ignore
1065
+ * + `data: object`: 进行`JSON.stringify`处理
1066
+ * + `data: FormData`: 转为`JSON`并进行`JSON.stringify`处理
1067
1067
  *
1068
- * ### `application/x-www-form-urlencoded`
1068
+ * ### `POST` => `Content-Type` => `application/x-www-form-urlencoded`
1069
1069
  *
1070
- * + `string`: 不做处理
1071
- * + `FormData`: 转为`URLSearchParams`,再转为`string`
1072
- * + `object`: 转为`URLSearchParams`,再转为`string`
1070
+ * + `data: string`: ignore
1071
+ * + `data: object`: 转为`URLSearchParams`,再转为`string`
1072
+ * + `data: FormData`: 转为`URLSearchParams`,再转为`string`
1073
1073
  *
1074
- * ### `multipart/form-data`(上传文件专用)
1074
+ * ### `POST` => `Content-Type` => `multipart/form-data`(上传文件专用)
1075
1075
  *
1076
- * + `string`: 不做处理
1077
- * + `FormData`: 移除`Content-Type`
1078
- * + `object`: 不做处理
1076
+ * + `data: string`: ignore
1077
+ * + `data: object`: ignore
1078
+ * + `data: FormData`: 移除`Content-Type`
1079
1079
  * @default true
1080
1080
  */
1081
1081
  processData?: boolean;
@@ -89,67 +89,103 @@ export declare interface UtilsAjaxHookFilterOptions {
89
89
  /** Utils.ajaxHooker */
90
90
  export declare interface UtilsAjaxHookResult {
91
91
  /**
92
- * 劫持xhr和fetch
93
- *
94
- * 提示:如果多次调用.hook方法,将会多次处理同一个请求
95
- * @example
96
- ajaxHooker.hook(request => {
97
- if (request.url === 'https://www.example.com/') {
98
- request.response = res => {
99
- console.log(res);
100
- res.responseText += 'test';
101
- };
102
- }
103
- });
104
- * @example
105
- // 异步特性无法作用于同步请求,但同步修改仍然有效
106
- // 你可以将以上所有可修改属性赋值为Promise,原请求将被阻塞直至Promise完成(若发生reject,数据将不会被修改)
107
- // 此特性可用于异步劫持。以下是一个异步修改响应数据的例子
108
- ajaxHooker.hook(request => {
109
- request.response = res => {
110
- const responseText = res.responseText; // 注意保存原数据
111
- res.responseText = new Promise(resolve => {
112
- setTimeout(() => {
113
- resolve(responseText + 'test');
114
- }, 3000);
115
- });
116
- };
117
- });
118
-
119
- // 也可以传入async回调函数以实现异步
120
- ajaxHooker.hook(async request => {
121
- request.data = await modifyData(request.data);
122
- request.response = async res => {
123
- res.responseText = await modifyResponse(res.responseText);
124
- };
125
- });
126
- */
92
+ * 劫持xhr和fetch
93
+ *
94
+ * 提示:如果多次调用.hook方法,将会多次处理同一个请求
95
+ * @example
96
+ * ajaxHooker.hook(request => {
97
+ * if (request.url === 'https://www.example.com/') {
98
+ * request.response = res => {
99
+ * console.log(res);
100
+ * res.responseText += 'test';
101
+ * };
102
+ * }
103
+ * });
104
+ * * @example
105
+ * // 异步特性无法作用于同步请求,但同步修改仍然有效
106
+ * // 你可以将以上所有可修改属性赋值为Promise,原请求将被阻塞直至Promise完成(若发生reject,数据将不会被修改)
107
+ * // 此特性可用于异步劫持。以下是一个异步修改响应数据的例子
108
+ * ajaxHooker.hook(request => {
109
+ * request.response = res => {
110
+ * const responseText = res.responseText; // 注意保存原数据
111
+ * res.responseText = new Promise(resolve => {
112
+ * setTimeout(() => {
113
+ * resolve(responseText + 'test');
114
+ * }, 3000);
115
+ * });
116
+ * };
117
+ * });
118
+ * // 也可以传入async回调函数以实现异步
119
+ * ajaxHooker.hook(async request => {
120
+ * request.data = await modifyData(request.data);
121
+ * request.response = async res => {
122
+ * res.responseText = await modifyResponse(res.responseText);
123
+ * };
124
+ * });
125
+ */
127
126
  hook(
128
- callback: (request: UtilsAjaxHookRequestOptions) => void | undefined | null | Promise<void | undefined | null>
129
- ): void;
130
- /**
131
- * 过滤
132
- * @example
133
- // 应于hook方法之前执行,此方法若尽早执行,有助于提升性能。
134
- // 为hook方法设置过滤规则,只有符合规则的请求才会触发hook。过滤规则是一个对象数组,参考下例
135
- ajaxHooker.filter([
136
- {type: 'xhr', url: 'www.example.com', method: 'GET', async: true},
137
- {url: /^http/},
138
- ]);
127
+ callback: (
128
+ /**
129
+ * hook请求的配置
130
+ */
131
+ request: UtilsAjaxHookRequestOptions,
132
+ /**
133
+ * 当前的`callback`的索引下标
134
+ */
135
+ index: number
136
+ ) => void | undefined | null | Promise<void | undefined | null>
137
+ ): {
138
+ /**
139
+ * 该函数是额外添加的,原版仅返回空值
139
140
  */
140
- filter(filterOptions: UtilsAjaxHookFilterOptions[]): void;
141
+ remove: () => boolean;
142
+ };
141
143
  /**
142
- * 阻止xhr和fetch被改写
143
- * @example
144
- // 如果库劫持失败,可能是其他代码对xhr/fetch进行了二次劫持,protect方法会尝试阻止xhr和fetch被改写。应于document-start阶段尽早执行,部分网页下可能引发错误,谨慎使用。
145
- ajaxHooker.protect();
144
+ * 过滤
145
+ *
146
+ * 注意:重复调用`.filter`设置规则会覆盖之前设置的规则
147
+ * @example
148
+ * // 应于hook方法之前执行,此方法若尽早执行,有助于提升性能。
149
+ * // 为hook方法设置过滤规则,只有符合规则的请求才会触发hook。过滤规则是一个对象数组,参考下例
150
+ * ajaxHooker.filter([
151
+ * {type: 'xhr', url: 'www.example.com', method: 'GET', async: true},
152
+ * {url: /^http/},
153
+ * ]);
154
+ */
155
+ filter(filterOptions: UtilsAjaxHookFilterOptions[]): {
156
+ /**
157
+ * 该函数是额外添加的,原版仅返回空值
146
158
  */
159
+ remove: () => void;
160
+ };
161
+ /**
162
+ * 阻止xhr和fetch被改写
163
+ * @example
164
+ * // 如果库劫持失败,可能是其他代码对xhr/fetch进行了二次劫持,protect方法会尝试阻止xhr和fetch被改写。应于document-start阶段尽早执行,部分网页下可能引发错误,谨慎使用。
165
+ * ajaxHooker.protect();
166
+ */
147
167
  protect(): void;
148
168
  /**
149
- * 取消劫持
150
- * @example
151
- // 将xhr和fetch恢复至劫持前的状态,调用此方法后,hook方法不再生效。
152
- ajaxHooker.unhook();
153
- */
169
+ * 取消劫持
170
+ * @example
171
+ * // 将xhr和fetch恢复至劫持前的状态,调用此方法后,hook方法不再生效。
172
+ * ajaxHooker.unhook();
173
+ */
154
174
  unhook(): void;
175
+ /**
176
+ * 移除通过`.hook`添加的函数
177
+ *
178
+ * @description 此函数为额外添加的增强函数
179
+ * @param fn `.hook`添加的函数
180
+ * @param onlyRemove (可选)是否仅移除一个(如果命中的话),默认false
181
+ */
182
+ removeHook(
183
+ fn: (request: UtilsAjaxHookRequestOptions) => void | undefined | null | Promise<void | undefined | null>,
184
+ onlyRemove: boolean
185
+ ): boolean;
186
+ /**
187
+ * 重置通过`.filter`设置的规则
188
+ * @description 此函数为额外添加的增强函数
189
+ */
190
+ removeFilter(): void;
155
191
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@whitesev/utils",
4
- "version": "2.11.10",
4
+ "version": "2.11.12",
5
5
  "description": "一个常用的工具库",
6
6
  "keywords": [
7
7
  "ScriptCat",
@@ -53,9 +53,8 @@
53
53
  "eslint-plugin-compat": "^6.0.2",
54
54
  "eslint-plugin-prettier": "^5.5.4",
55
55
  "globals": "^16.5.0",
56
- "oxfmt": "^0.32.0",
57
- "oxlint": "1.46.0",
58
- "rolldown": "1.0.0-beta.55",
56
+ "oxfmt": "^0.37.0",
57
+ "oxlint": "1.55.0",
59
58
  "rollup": "^4.53.5",
60
59
  "rollup-plugin-clear": "^2.0.7",
61
60
  "tslib": "^2.8.1",
package/src/Httpx.ts CHANGED
@@ -465,39 +465,39 @@ export class Httpx {
465
465
  const method = requestOption.method;
466
466
  if (method === "GET" || method === "HEAD") {
467
467
  // GET类型,data如果有,那么需要转为searchParams
468
- const urlObj = new URL(requestOption.url);
468
+ const urlInst = new URL(requestOption.url);
469
469
  let urlSearch = "";
470
- let isHandler = false;
470
+ let deleteData = false;
471
471
  if (typeof requestOption.data === "string") {
472
- isHandler = true;
472
+ deleteData = true;
473
473
  urlSearch = requestOption.data;
474
474
  } else if (typeof requestOption.data === "object") {
475
- isHandler = true;
475
+ deleteData = true;
476
476
  // URLSearchParams参数可以转普通的string:string,包括FormData
477
477
  const searchParams = new URLSearchParams(requestOption.data as Record<string, string>);
478
478
  urlSearch = searchParams.toString();
479
479
  }
480
- if (isHandler) {
480
+ if (deleteData) {
481
481
  // GET/HEAD请求不支持data参数
482
482
  // 对data进行处理了才可以删除
483
483
  Reflect.deleteProperty(requestOption, "data");
484
484
  }
485
- if (urlSearch != "") {
486
- if (urlObj.search === "") {
485
+ if (urlSearch.trim() != "") {
486
+ if (urlInst.search.trim() === "") {
487
487
  // url没有search参数,直接覆盖
488
- urlObj.search = urlSearch;
488
+ urlInst.search = urlSearch;
489
489
  } else {
490
490
  // 有search参数
491
- if (urlObj.search.endsWith("&")) {
491
+ if (urlInst.search.trim().endsWith("&")) {
492
492
  // xxx=xxx&
493
- urlObj.search = urlObj.search + urlSearch;
493
+ urlInst.search = urlInst.search + urlSearch;
494
494
  } else {
495
495
  // xxx=xxx&xxx=
496
- urlObj.search = `${urlObj.search}&${urlSearch}`;
496
+ urlInst.search = `${urlInst.search}&${urlSearch}`;
497
497
  }
498
498
  }
499
499
  }
500
- requestOption.url = urlObj.toString();
500
+ requestOption.url = urlInst.toString();
501
501
  } else if (method === "POST" && requestOption.headers != null) {
502
502
  // POST类型,data如果是FormData,那么需要转为string
503
503
  const headersKeyList = Object.keys(requestOption.headers);
@@ -508,10 +508,10 @@ export class Httpx {
508
508
  );
509
509
  });
510
510
  if (ContentTypeIndex !== -1) {
511
- const ContentTypeKey = headersKeyList[ContentTypeIndex];
512
- const ContentType = requestOption.headers[ContentTypeKey] as string;
511
+ const contentTypeKey = headersKeyList[ContentTypeIndex];
512
+ const contentType = (<string>requestOption.headers[contentTypeKey]).toLowerCase();
513
513
  // 设置了Content-Type
514
- if (ContentType.includes("application/json")) {
514
+ if (contentType.includes("application/json")) {
515
515
  // application/json
516
516
  if (requestOption.data instanceof FormData) {
517
517
  const entries: { [key: string]: any } = {};
@@ -522,15 +522,15 @@ export class Httpx {
522
522
  } else if (typeof requestOption.data === "object") {
523
523
  requestOption.data = JSON.stringify(requestOption.data);
524
524
  }
525
- } else if (ContentType.includes("application/x-www-form-urlencoded")) {
525
+ } else if (contentType.includes("application/x-www-form-urlencoded")) {
526
526
  // application/x-www-form-urlencoded
527
527
  if (typeof requestOption.data === "object") {
528
528
  requestOption.data = new URLSearchParams(requestOption.data as Record<string, string>).toString();
529
529
  }
530
- } else if (ContentType.includes("multipart/form-data")) {
530
+ } else if (contentType.includes("multipart/form-data")) {
531
531
  // multipart/form-data
532
532
  if (requestOption.data instanceof FormData) {
533
- Reflect.deleteProperty(requestOption.headers, ContentTypeKey);
533
+ Reflect.deleteProperty(requestOption.headers, contentTypeKey);
534
534
  }
535
535
  }
536
536
  }
@@ -37,12 +37,9 @@ export class LockFunction<K extends (...args: any[]) => any | Promise<any> | voi
37
37
  * 解锁
38
38
  */
39
39
  this.unlock = function () {
40
- that.#timeId = setTimeout(
41
- () => {
42
- that.#flag = false;
43
- },
44
- that.#delayTime
45
- );
40
+ that.#timeId = setTimeout(() => {
41
+ that.#flag = false;
42
+ }, that.#delayTime);
46
43
  };
47
44
  /**
48
45
  * 判断是否被锁