@nsnanocat/util 1.8.0 → 1.8.2

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/lib/done.mjs CHANGED
@@ -32,29 +32,12 @@ export function done(object = {}) {
32
32
  $done(object);
33
33
  break;
34
34
  case "Shadowrocket":
35
- default:
36
35
  Console.log("🚩 执行结束!");
37
36
  $done(object);
38
37
  break;
39
38
  case "Quantumult X":
40
39
  if (object.policy) _.set(object, "opts.policy", object.policy);
41
- // 移除不可写字段
42
- object["auto-redirect"] = undefined;
43
- object["auto-cookie"] = undefined;
44
- object["binary-mode"] = undefined;
45
- object.charset = undefined;
46
- object.host = undefined;
47
- object.insecure = undefined;
48
- object.method = undefined; // 1.4.x 不可写
49
- object.ok = undefined; // 来自fetch()的响应对象, 不可写
50
- object.opt = undefined; // $task.fetch() 参数, 不可写
51
- object.path = undefined; // 可写, 但会与 url 冲突
52
- object.policy = undefined;
53
- object["policy-descriptor"] = undefined;
54
- object.scheme = undefined;
55
- object.sessionIndex = undefined;
56
- object.statusCode = undefined;
57
- object.timeout = undefined;
40
+ object = _.pick(object, ["status", "url", "headers", "body", "bodyBytes"]);
58
41
  switch (typeof object.status) {
59
42
  case "number":
60
43
  object.status = StatusCodes[object.status];
@@ -77,6 +60,7 @@ export function done(object = {}) {
77
60
  $done(object);
78
61
  break;
79
62
  case "Node.js":
63
+ default:
80
64
  Console.log("🚩 执行结束!");
81
65
  process.exit(1);
82
66
  break;
package/package.json CHANGED
@@ -36,5 +36,5 @@
36
36
  "devDependencies": {
37
37
  "typescript": "^5.6.3"
38
38
  },
39
- "version": "1.8.0"
39
+ "version": "1.8.2"
40
40
  }
@@ -8,32 +8,42 @@ import { Lodash as _ } from "./Lodash.mjs";
8
8
  * @link https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API
9
9
  * @export
10
10
  * @async
11
- * @param {object|string} request
12
- * @param {object} [option]
11
+ * @param {object|string} resource
12
+ * @param {object} [options]
13
13
  * @returns {Promise<object>}
14
14
  */
15
- export async function fetch(request, option) {
15
+ export async function fetch(resource, options = {}) {
16
16
  // 初始化参数
17
- switch (request.constructor) {
18
- case Object:
19
- request = { ...option, ...request };
17
+ switch (typeof resource) {
18
+ case "object":
19
+ resource = { ...options, ...resource };
20
20
  break;
21
- case String:
22
- request = { ...option, url: request };
21
+ case "string":
22
+ resource = { ...options, url: resource };
23
23
  break;
24
+ case "undefined":
25
+ default:
26
+ throw new TypeError(`${Function.name}: 参数类型错误, resource 必须为对象或字符串`);
24
27
  }
25
28
  // 自动判断请求方法
26
- if (!request.method) {
27
- request.method = "GET";
28
- if (request.body ?? request.bodyBytes) request.method = "POST";
29
+ if (!resource.method) {
30
+ resource.method = "GET";
31
+ if (resource.body ?? resource.bodyBytes) resource.method = "POST";
29
32
  }
30
33
  // 移除请求头中的部分参数, 让其自动生成
31
- delete request.headers?.Host;
32
- delete request.headers?.[":authority"];
33
- delete request.headers?.["Content-Length"];
34
- delete request.headers?.["content-length"];
34
+ delete resource.headers?.Host;
35
+ delete resource.headers?.[":authority"];
36
+ delete resource.headers?.["Content-Length"];
37
+ delete resource.headers?.["content-length"];
35
38
  // 定义请求方法(小写)
36
- const method = request.method.toLocaleLowerCase();
39
+ const method = resource.method.toLocaleLowerCase();
40
+ // 转换请求超时时间参数
41
+ if (!resource.timeout) resource.timeout = 5;
42
+ if (resource.timeout) {
43
+ resource.timeout = Number.parseInt(resource.timeout, 10);
44
+ // 转换为秒,大于500视为毫秒,小于等于500视为秒
45
+ if (resource.timeout > 500) resource.timeout = Math.round(resource.timeout / 1000);
46
+ }
37
47
  // 判断平台
38
48
  switch ($app) {
39
49
  case "Loon":
@@ -43,41 +53,40 @@ export async function fetch(request, option) {
43
53
  case "Shadowrocket":
44
54
  default:
45
55
  // 转换请求参数
46
- if (request.timeout) {
47
- request.timeout = Number.parseInt(request.timeout, 10);
56
+ if (resource.timeout) {
48
57
  switch ($app) {
49
58
  case "Loon":
59
+ resource.timeout = resource.timeout * 1000;
60
+ break;
50
61
  case "Shadowrocket":
51
62
  case "Stash":
52
63
  case "Egern":
53
- default:
54
- request.timeout = request.timeout / 1000;
55
- break;
56
64
  case "Surge":
65
+ default:
57
66
  break;
58
67
  }
59
68
  }
60
- if (request.policy) {
69
+ if (resource.policy) {
61
70
  switch ($app) {
62
71
  case "Loon":
63
- request.node = request.policy;
72
+ resource.node = resource.policy;
64
73
  break;
65
74
  case "Stash":
66
- _.set(request, "headers.X-Stash-Selected-Proxy", encodeURI(request.policy));
75
+ _.set(resource, "headers.X-Stash-Selected-Proxy", encodeURI(resource.policy));
67
76
  break;
68
77
  case "Shadowrocket":
69
- _.set(request, "headers.X-Surge-Proxy", request.policy);
78
+ _.set(resource, "headers.X-Surge-Proxy", resource.policy);
70
79
  break;
71
80
  }
72
81
  }
73
- if (typeof request.redirection === "boolean") request["auto-redirect"] = request.redirection;
82
+ if (typeof resource.redirection === "boolean") resource["auto-redirect"] = resource.redirection;
74
83
  // 转换请求体
75
- if (request.bodyBytes && !request.body) {
76
- request.body = request.bodyBytes;
77
- request.bodyBytes = undefined;
84
+ if (resource.bodyBytes && !resource.body) {
85
+ resource.body = resource.bodyBytes;
86
+ resource.bodyBytes = undefined;
78
87
  }
79
88
  // 判断是否请求二进制响应体
80
- switch ((request.headers?.Accept || request.headers?.accept)?.split(";")?.[0]) {
89
+ switch ((resource.headers?.Accept || resource.headers?.accept)?.split(";")?.[0]) {
81
90
  case "application/protobuf":
82
91
  case "application/x-protobuf":
83
92
  case "application/vnd.google.protobuf":
@@ -85,19 +94,19 @@ export async function fetch(request, option) {
85
94
  case "application/grpc":
86
95
  case "application/grpc+proto":
87
96
  case "application/octet-stream":
88
- request["binary-mode"] = true;
97
+ resource["binary-mode"] = true;
89
98
  break;
90
99
  }
91
100
  // 发送请求
92
101
  return await new Promise((resolve, reject) => {
93
- $httpClient[method](request, (error, response, body) => {
102
+ $httpClient[method](resource, (error, response, body) => {
94
103
  if (error) reject(error);
95
104
  else {
96
105
  response.ok = /^2\d\d$/.test(response.status);
97
106
  response.statusCode = response.status;
98
107
  if (body) {
99
108
  response.body = body;
100
- if (request["binary-mode"] == true) response.bodyBytes = body;
109
+ if (resource["binary-mode"] == true) response.bodyBytes = body;
101
110
  }
102
111
  resolve(response);
103
112
  }
@@ -105,51 +114,58 @@ export async function fetch(request, option) {
105
114
  });
106
115
  case "Quantumult X":
107
116
  // 转换请求参数
108
- if (request.policy) _.set(request, "opts.policy", request.policy);
109
- if (typeof request["auto-redirect"] === "boolean") _.set(request, "opts.redirection", request["auto-redirect"]);
117
+ if (resource.policy) _.set(resource, "opts.policy", resource.policy);
118
+ if (typeof resource["auto-redirect"] === "boolean") _.set(resource, "opts.redirection", resource["auto-redirect"]);
110
119
  // 转换请求体
111
- if (request.body instanceof ArrayBuffer) {
112
- request.bodyBytes = request.body;
113
- request.body = undefined;
114
- } else if (ArrayBuffer.isView(request.body)) {
115
- request.bodyBytes = request.body.buffer.slice(request.body.byteOffset, request.body.byteLength + request.body.byteOffset);
116
- request.body = undefined;
117
- } else if (request.body) request.bodyBytes = undefined;
120
+ if (resource.body instanceof ArrayBuffer) {
121
+ resource.bodyBytes = resource.body;
122
+ resource.body = undefined;
123
+ } else if (ArrayBuffer.isView(resource.body)) {
124
+ resource.bodyBytes = resource.body.buffer.slice(resource.body.byteOffset, resource.body.byteLength + resource.body.byteOffset);
125
+ resource.body = undefined;
126
+ } else if (resource.body) resource.bodyBytes = undefined;
118
127
  // 发送请求
119
- return await $task.fetch(request).then(
120
- response => {
121
- response.ok = /^2\d\d$/.test(response.statusCode);
122
- response.status = response.statusCode;
123
- switch ((response.headers?.["Content-Type"] ?? response.headers?.["content-type"])?.split(";")?.[0]) {
124
- case "application/protobuf":
125
- case "application/x-protobuf":
126
- case "application/vnd.google.protobuf":
127
- case "application/vnd.apple.flatbuffer":
128
- case "application/grpc":
129
- case "application/grpc+proto":
130
- case "application/octet-stream":
131
- response.body = response.bodyBytes;
132
- break;
133
- case undefined:
134
- default:
135
- break;
136
- }
137
- response.bodyBytes = undefined;
138
- return response;
139
- },
140
- reason => Promise.reject(reason.error),
141
- );
128
+ return Promise.race([
129
+ await $task.fetch(resource).then(
130
+ response => {
131
+ response.ok = /^2\d\d$/.test(response.statusCode);
132
+ response.status = response.statusCode;
133
+ switch ((response.headers?.["Content-Type"] ?? response.headers?.["content-type"])?.split(";")?.[0]) {
134
+ case "application/protobuf":
135
+ case "application/x-protobuf":
136
+ case "application/vnd.google.protobuf":
137
+ case "application/vnd.apple.flatbuffer":
138
+ case "application/grpc":
139
+ case "application/grpc+proto":
140
+ case "application/octet-stream":
141
+ response.body = response.bodyBytes;
142
+ break;
143
+ case undefined:
144
+ default:
145
+ break;
146
+ }
147
+ response.bodyBytes = undefined;
148
+ return response;
149
+ },
150
+ reason => Promise.reject(reason.error),
151
+ ),
152
+ new Promise((resolve, reject) => {
153
+ setTimeout(() => {
154
+ reject(new Error(`${Function.name}: 请求超时, 请检查网络后重试`));
155
+ }, resource.timeout);
156
+ }),
157
+ ]);
142
158
  case "Node.js": {
143
159
  const iconv = require("iconv-lite");
144
160
  const got = globalThis.got ? globalThis.got : require("got");
145
161
  const cktough = globalThis.cktough ? globalThis.cktough : require("tough-cookie");
146
162
  const ckjar = globalThis.ckjar ? globalThis.ckjar : new cktough.CookieJar();
147
- if (request) {
148
- request.headers = request.headers ? request.headers : {};
149
- if (undefined === request.headers.Cookie && undefined === request.cookieJar) request.cookieJar = ckjar;
163
+ if (resource) {
164
+ resource.headers = resource.headers ? resource.headers : {};
165
+ if (undefined === resource.headers.Cookie && undefined === resource.cookieJar) resource.cookieJar = ckjar;
150
166
  }
151
- const { url, ...option } = request;
152
- return await got[method](url, option)
167
+ const { url, ...options } = resource;
168
+ return await got[method](url, options)
153
169
  .on("redirect", (response, nextOpts) => {
154
170
  try {
155
171
  if (response.headers["set-cookie"]) {