@nsnanocat/util 2.1.7 → 2.2.3
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/README.md +12 -8
- package/lib/app.mjs +25 -18
- package/lib/done.mjs +5 -1
- package/package.json +3 -2
- package/polyfill/fetch.mjs +83 -38
- package/types/nsnanocat-util.d.ts +9 -1
package/README.md
CHANGED
|
@@ -116,7 +116,7 @@ import {
|
|
|
116
116
|
### `lib/app.mjs` 与 `lib/environment.mjs`(平台识别与环境)
|
|
117
117
|
|
|
118
118
|
#### `$app`
|
|
119
|
-
- 类型:`"Quantumult X" | "Loon" | "Shadowrocket" | "
|
|
119
|
+
- 类型:`"Quantumult X" | "Loon" | "Shadowrocket" | "Egern" | "Surge" | "Stash" | "Node.js" | undefined`
|
|
120
120
|
- 角色:核心模块。库内所有存在平台行为差异的模块都会先读取 `$app` 再分流(如 `done`、`notification`、`fetch`、`Storage`、`Console`、`environment`)。
|
|
121
121
|
- 读取方式:
|
|
122
122
|
|
|
@@ -130,10 +130,12 @@ console.log(appName);
|
|
|
130
130
|
1. 存在 `$task` -> `Quantumult X`
|
|
131
131
|
2. 存在 `$loon` -> `Loon`
|
|
132
132
|
3. 存在 `$rocket` -> `Shadowrocket`
|
|
133
|
-
4. 存在 `
|
|
134
|
-
5. 存在 `
|
|
135
|
-
6. 存在 `$environment` 且有 `
|
|
136
|
-
7. 存在
|
|
133
|
+
4. 存在 `Egern` -> `Egern`
|
|
134
|
+
5. 存在 `$environment` 且有 `surge-version` -> `Surge`
|
|
135
|
+
6. 存在 `$environment` 且有 `stash-version` -> `Stash`
|
|
136
|
+
7. 存在 `process.versions.node` -> `Node.js`
|
|
137
|
+
8. 默认回落 -> `undefined`
|
|
138
|
+
- 实现细节:内部使用 `'key' in globalThis` 检测平台标记,避免 `Object.keys(globalThis)` 漏掉不可枚举全局变量;因此在 Workers / Vercel 风格全局对象存在时,只要 `process.versions.node` 可用,仍会识别为 `Node.js`。
|
|
137
139
|
|
|
138
140
|
#### `$environment` / `environment()`
|
|
139
141
|
- 路径:`lib/environment.mjs`(未从包主入口导出)
|
|
@@ -221,6 +223,7 @@ console.log($argument); // { mode: "on", a: { b: "1" } }
|
|
|
221
223
|
- Quantumult X 会丢弃未在白名单内的字段。
|
|
222
224
|
- Quantumult X 的 `status` 在部分场景要求完整状态行(如 `HTTP/1.1 200 OK`),本库会在传入数字状态码时自动拼接(依赖 `StatusTexts`)。
|
|
223
225
|
- Node.js 不调用 `$done`,而是直接退出进程,且退出码固定为 `1`。
|
|
226
|
+
- 未识别平台(`$app === undefined`)只记录结束日志,不会尝试调用 `$done` 或退出进程。
|
|
224
227
|
|
|
225
228
|
### `lib/notification.mjs`
|
|
226
229
|
|
|
@@ -381,6 +384,7 @@ const store = getStorage("@my_box", ["YouTube", "Global"], database);
|
|
|
381
384
|
- `timeout`
|
|
382
385
|
- `policy`
|
|
383
386
|
- `redirection` / `auto-redirect`
|
|
387
|
+
- `auto-cookie`(仅 Node.js 分支识别;默认启用,传入 `false` / `0` / `-1` 可关闭)
|
|
384
388
|
|
|
385
389
|
说明:下表是各 App 原生 HTTP 接口的差异补充,以及本库 `fetch` 的内部映射方式。调用方使用统一入参即可。
|
|
386
390
|
|
|
@@ -394,7 +398,7 @@ const store = getStorage("@my_box", ["YouTube", "Global"], database);
|
|
|
394
398
|
| Egern | `$httpClient[method]` | 秒 | 无专门映射 | `auto-redirect` | 同上 |
|
|
395
399
|
| Shadowrocket | `$httpClient[method]` | 秒 | `headers.X-Surge-Proxy` | `auto-redirect` | 同上 |
|
|
396
400
|
| Quantumult X | `$task.fetch` | 毫秒(内部乘 1000) | `opts.policy` | `opts.redirection` | `body(ArrayBuffer/TypedArray)` 转 `bodyBytes`;响应按 `Content-Type` 恢复到 `body` |
|
|
397
|
-
| Node.js | `fetch`
|
|
401
|
+
| Node.js | `globalThis.fetch`(不存在时回退 `node-fetch`);默认按需包裹 `fetch-cookie` | 毫秒(内部乘 1000) | 无 | `redirect: follow/manual` | 返回 `body`(UTF-8 string) + `bodyBytes`(ArrayBuffer) |
|
|
398
402
|
|
|
399
403
|
返回对象(统一后)常见字段:
|
|
400
404
|
- `ok`
|
|
@@ -408,7 +412,8 @@ const store = getStorage("@my_box", ["YouTube", "Global"], database);
|
|
|
408
412
|
不可用/差异点:
|
|
409
413
|
- `policy` 在 Surge / Egern / Node.js 分支没有额外适配逻辑。
|
|
410
414
|
- `redirection` 在部分平台会映射为 `auto-redirect` 或 `opts.redirection`。
|
|
411
|
-
- Node.js
|
|
415
|
+
- Node.js 分支优先复用 `globalThis.fetch`;若不存在则回退到 `node-fetch`,并在 `auto-cookie` 未关闭时按需包裹 `fetch-cookie`。
|
|
416
|
+
- 传入 `timeout` 时,`5` 和 `5000` 都会被接受;库会先将用户输入归一化,再按平台要求转换为秒或毫秒。
|
|
412
417
|
- 返回结构是统一兼容结构,不等同于浏览器 `Response` 对象。
|
|
413
418
|
|
|
414
419
|
### `polyfill/Storage.mjs`
|
|
@@ -631,7 +636,6 @@ console.log(value); // 1
|
|
|
631
636
|
|
|
632
637
|
- `lib/argument.mjs` 为 `$argument` 标准化模块,`import` 时会按规则重写全局 `$argument`。
|
|
633
638
|
- `lib/done.mjs` 在 Node.js 固定 `process.exit(1)`。
|
|
634
|
-
- `polyfill/fetch.mjs` 的超时保护使用了 `Promise.race`,但当前实现里请求 Promise 先被 `await`,可能导致超时行为与预期不完全一致。
|
|
635
639
|
- `Storage.removeItem("@a.b")` 分支存在未声明变量写入风险;如要大量使用路径删除,建议先本地验证。
|
|
636
640
|
- `lib/runScript.mjs` 未从包主入口导出,需要按文件路径直接导入。
|
|
637
641
|
|
package/lib/app.mjs
CHANGED
|
@@ -1,36 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* Current runtime platform name.
|
|
2
|
+
* 当前运行平台名称(脚本平台优先,模块系统次之)。
|
|
3
|
+
* Current runtime platform name (script platform first, module system second).
|
|
4
4
|
*
|
|
5
5
|
* 识别顺序:
|
|
6
6
|
* Detection order:
|
|
7
7
|
* 1) `$task` -> Quantumult X
|
|
8
8
|
* 2) `$loon` -> Loon
|
|
9
9
|
* 3) `$rocket` -> Shadowrocket
|
|
10
|
-
* 4) `
|
|
11
|
-
* 5) `
|
|
12
|
-
* 6) `$environment["
|
|
13
|
-
* 7)
|
|
10
|
+
* 4) `Egern` -> Egern
|
|
11
|
+
* 5) `$environment["surge-version"]` -> Surge
|
|
12
|
+
* 6) `$environment["stash-version"]` -> Stash
|
|
13
|
+
* 7) `process.versions.node` -> Node.js
|
|
14
|
+
* 8) 默认回落 -> undefined
|
|
15
|
+
* default fallback -> undefined
|
|
14
16
|
*
|
|
15
|
-
*
|
|
17
|
+
* 说明:
|
|
18
|
+
* Notes:
|
|
19
|
+
* - 使用 `'key' in globalThis`,避免 `Object.keys` 对不可枚举全局变量漏检。
|
|
20
|
+
* - Use `'key' in globalThis` to avoid missing non-enumerable globals with `Object.keys`.
|
|
21
|
+
*
|
|
22
|
+
* @type {("Quantumult X" | "Loon" | "Shadowrocket" | "Egern" | "Surge" | "Stash" | "Node.js" | undefined)}
|
|
16
23
|
*/
|
|
17
24
|
export const $app = (() => {
|
|
18
|
-
const
|
|
25
|
+
const has = (key) => key in globalThis;
|
|
19
26
|
switch (true) {
|
|
20
|
-
case
|
|
27
|
+
case has("$task"):
|
|
21
28
|
return "Quantumult X";
|
|
22
|
-
case
|
|
29
|
+
case has("$loon"):
|
|
23
30
|
return "Loon";
|
|
24
|
-
case
|
|
31
|
+
case has("$rocket"):
|
|
25
32
|
return "Shadowrocket";
|
|
26
|
-
case
|
|
27
|
-
return "Node.js";
|
|
28
|
-
case keys.includes("Egern"):
|
|
33
|
+
case has("Egern"):
|
|
29
34
|
return "Egern";
|
|
30
|
-
case
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return
|
|
35
|
+
case Boolean(globalThis.$environment?.["surge-version"]):
|
|
36
|
+
return "Surge";
|
|
37
|
+
case Boolean(globalThis.$environment?.["stash-version"]):
|
|
38
|
+
return "Stash";
|
|
39
|
+
case Boolean(globalThis.process?.versions?.node):
|
|
40
|
+
return "Node.js";
|
|
34
41
|
default:
|
|
35
42
|
return undefined;
|
|
36
43
|
}
|
package/lib/done.mjs
CHANGED
|
@@ -26,6 +26,8 @@ import { StatusTexts } from "../polyfill/StatusTexts.mjs";
|
|
|
26
26
|
* - This is the call entry and native `$done` differences are handled internally
|
|
27
27
|
* - Node.js 不调用 `$done`,而是直接退出进程
|
|
28
28
|
* - Node.js does not call `$done`; it exits the process directly
|
|
29
|
+
* - 未识别平台仅记录结束日志,不会强制退出
|
|
30
|
+
* - Unknown runtimes only log completion and do not force an exit
|
|
29
31
|
*
|
|
30
32
|
* @param {DonePayload} [object={}] 统一响应对象 / Unified response object.
|
|
31
33
|
* @returns {void}
|
|
@@ -79,9 +81,11 @@ export function done(object = {}) {
|
|
|
79
81
|
$done(object);
|
|
80
82
|
break;
|
|
81
83
|
case "Node.js":
|
|
82
|
-
default:
|
|
83
84
|
Console.log("🚩 执行结束!");
|
|
84
85
|
process.exit(1);
|
|
85
86
|
break;
|
|
87
|
+
default:
|
|
88
|
+
Console.log("🚩 执行结束!");
|
|
89
|
+
break;
|
|
86
90
|
}
|
|
87
91
|
}
|
package/package.json
CHANGED
|
@@ -35,11 +35,12 @@
|
|
|
35
35
|
"types"
|
|
36
36
|
],
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"
|
|
38
|
+
"@biomejs/biome": "2.4.6",
|
|
39
|
+
"typescript": "^5.9.3"
|
|
39
40
|
},
|
|
40
41
|
"publishConfig": {
|
|
41
42
|
"registry": "https://registry.npmjs.org/",
|
|
42
43
|
"access": "public"
|
|
43
44
|
},
|
|
44
|
-
"version": "2.
|
|
45
|
+
"version": "2.2.3"
|
|
45
46
|
}
|
package/polyfill/fetch.mjs
CHANGED
|
@@ -17,6 +17,7 @@ import { StatusTexts } from "./StatusTexts.mjs";
|
|
|
17
17
|
* @property {string} [policy] 指定策略 / Preferred policy.
|
|
18
18
|
* @property {boolean} [redirection] 是否跟随重定向 / Whether to follow redirects.
|
|
19
19
|
* @property {boolean} ["auto-redirect"] 平台重定向字段 / Platform redirect flag.
|
|
20
|
+
* @property {boolean|number|string} ["auto-cookie"] Node.js Cookie 开关 / Node.js Cookie toggle.
|
|
20
21
|
* @property {Record<string, any>} [opts] 平台扩展字段 / Platform extension fields.
|
|
21
22
|
*/
|
|
22
23
|
|
|
@@ -56,6 +57,8 @@ import { StatusTexts } from "./StatusTexts.mjs";
|
|
|
56
57
|
* Known differences from Web `fetch`:
|
|
57
58
|
* - 支持 `policy`、`auto-redirect` 等平台扩展字段
|
|
58
59
|
* - Supports platform extension fields like `policy` and `auto-redirect`
|
|
60
|
+
* - Node.js 分支默认启用 Cookie 透传,可通过 `auto-cookie` 关闭
|
|
61
|
+
* - Node.js enables Cookie forwarding by default and can disable it via `auto-cookie`
|
|
59
62
|
* - 非浏览器平台通过 `$httpClient/$task` 实现,不是原生 Fetch 实现
|
|
60
63
|
* - Non-browser platforms use `$httpClient/$task` instead of native Fetch engine
|
|
61
64
|
* - 返回结构包含 `statusCode/bodyBytes` 等兼容字段
|
|
@@ -69,7 +72,8 @@ import { StatusTexts } from "./StatusTexts.mjs";
|
|
|
69
72
|
* @returns {Promise<FetchResponse>}
|
|
70
73
|
*/
|
|
71
74
|
export async function fetch(resource, options = {}) {
|
|
72
|
-
//
|
|
75
|
+
// 初始化参数。
|
|
76
|
+
// Initialize request input.
|
|
73
77
|
switch (typeof resource) {
|
|
74
78
|
case "object":
|
|
75
79
|
resource = { ...options, ...resource };
|
|
@@ -81,26 +85,53 @@ export async function fetch(resource, options = {}) {
|
|
|
81
85
|
default:
|
|
82
86
|
throw new TypeError(`${Function.name}: 参数类型错误, resource 必须为对象或字符串`);
|
|
83
87
|
}
|
|
84
|
-
//
|
|
88
|
+
// 自动判断请求方法。
|
|
89
|
+
// Infer the HTTP method automatically.
|
|
85
90
|
if (!resource.method) {
|
|
86
91
|
resource.method = "GET";
|
|
87
92
|
if (resource.body ?? resource.bodyBytes) resource.method = "POST";
|
|
88
93
|
}
|
|
89
|
-
//
|
|
94
|
+
// 移除需要由底层实现自动生成的请求头。
|
|
95
|
+
// Remove headers that should be generated by the underlying runtime.
|
|
90
96
|
delete resource.headers?.Host;
|
|
91
97
|
delete resource.headers?.[":authority"];
|
|
92
98
|
delete resource.headers?.["Content-Length"];
|
|
93
99
|
delete resource.headers?.["content-length"];
|
|
94
|
-
//
|
|
100
|
+
// 统一请求方法为小写,方便后续索引平台 API。
|
|
101
|
+
// Normalize the method to lowercase for platform API lookups.
|
|
95
102
|
const method = resource.method.toLocaleLowerCase();
|
|
96
|
-
//
|
|
103
|
+
// 默认请求超时时间为 5 秒。
|
|
104
|
+
// Default request timeout to 5 seconds.
|
|
97
105
|
if (!resource.timeout) resource.timeout = 5;
|
|
106
|
+
// 智能矫正请求超时时间,兼容用户输入的秒或毫秒。
|
|
107
|
+
// Normalize timeout input so both seconds and milliseconds are accepted.
|
|
98
108
|
if (resource.timeout) {
|
|
99
109
|
resource.timeout = Number.parseInt(resource.timeout, 10);
|
|
100
|
-
//
|
|
110
|
+
// 统一先转换为秒,大于 500 视为毫秒输入。
|
|
111
|
+
// Convert to seconds first and treat values above 500 as milliseconds.
|
|
101
112
|
if (resource.timeout > 500) resource.timeout = Math.round(resource.timeout / 1000);
|
|
102
113
|
}
|
|
103
|
-
//
|
|
114
|
+
// 某些平台要求毫秒级超时,进行二次换算。
|
|
115
|
+
// Some platforms expect timeout in milliseconds, so convert again.
|
|
116
|
+
if (resource.timeout) {
|
|
117
|
+
switch ($app) {
|
|
118
|
+
case "Loon":
|
|
119
|
+
case "Quantumult X":
|
|
120
|
+
case "Node.js":
|
|
121
|
+
// 这些平台要求毫秒,因此把秒重新换算为毫秒。
|
|
122
|
+
// These platforms expect milliseconds, so convert seconds back to milliseconds.
|
|
123
|
+
resource.timeout = resource.timeout * 1000;
|
|
124
|
+
break;
|
|
125
|
+
case "Shadowrocket":
|
|
126
|
+
case "Stash":
|
|
127
|
+
case "Egern":
|
|
128
|
+
case "Surge":
|
|
129
|
+
default:
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// 根据当前平台选择请求实现。
|
|
134
|
+
// Select the request engine for the current platform.
|
|
104
135
|
switch ($app) {
|
|
105
136
|
case "Loon":
|
|
106
137
|
case "Surge":
|
|
@@ -108,20 +139,8 @@ export async function fetch(resource, options = {}) {
|
|
|
108
139
|
case "Egern":
|
|
109
140
|
case "Shadowrocket":
|
|
110
141
|
default:
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
switch ($app) {
|
|
114
|
-
case "Loon":
|
|
115
|
-
resource.timeout = resource.timeout * 1000;
|
|
116
|
-
break;
|
|
117
|
-
case "Shadowrocket":
|
|
118
|
-
case "Stash":
|
|
119
|
-
case "Egern":
|
|
120
|
-
case "Surge":
|
|
121
|
-
default:
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
142
|
+
// 转换通用请求参数到 `$httpClient` 语义。
|
|
143
|
+
// Map shared request fields to `$httpClient` semantics.
|
|
125
144
|
if (resource.policy) {
|
|
126
145
|
switch ($app) {
|
|
127
146
|
case "Loon":
|
|
@@ -136,12 +155,14 @@ export async function fetch(resource, options = {}) {
|
|
|
136
155
|
}
|
|
137
156
|
}
|
|
138
157
|
if (typeof resource.redirection === "boolean") resource["auto-redirect"] = resource.redirection;
|
|
139
|
-
//
|
|
158
|
+
// 优先把 `bodyBytes` 映射回 `$httpClient` 能接受的 `body`。
|
|
159
|
+
// Prefer mapping `bodyBytes` back to the `body` field expected by `$httpClient`.
|
|
140
160
|
if (resource.bodyBytes && !resource.body) {
|
|
141
161
|
resource.body = resource.bodyBytes;
|
|
142
162
|
resource.bodyBytes = undefined;
|
|
143
163
|
}
|
|
144
|
-
//
|
|
164
|
+
// 根据 `Accept` 推断是否需要二进制响应体。
|
|
165
|
+
// Infer whether the response should be treated as binary from `Accept`.
|
|
145
166
|
switch ((resource.headers?.Accept || resource.headers?.accept)?.split(";")?.[0]) {
|
|
146
167
|
case "application/protobuf":
|
|
147
168
|
case "application/x-protobuf":
|
|
@@ -153,9 +174,10 @@ export async function fetch(resource, options = {}) {
|
|
|
153
174
|
resource["binary-mode"] = true;
|
|
154
175
|
break;
|
|
155
176
|
}
|
|
156
|
-
//
|
|
157
|
-
|
|
158
|
-
|
|
177
|
+
// 发送 `$httpClient` 请求并归一化返回结构。
|
|
178
|
+
// Send the `$httpClient` request and normalize the response payload.
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
globalThis.$httpClient[method](resource, (error, response, body) => {
|
|
159
181
|
if (error) reject(error);
|
|
160
182
|
else {
|
|
161
183
|
response.ok = /^2\d\d$/.test(response.status);
|
|
@@ -170,11 +192,12 @@ export async function fetch(resource, options = {}) {
|
|
|
170
192
|
});
|
|
171
193
|
});
|
|
172
194
|
case "Quantumult X":
|
|
173
|
-
//
|
|
174
|
-
|
|
195
|
+
// 转换 Quantumult X 专有请求参数。
|
|
196
|
+
// Map request fields to Quantumult X specific options.
|
|
175
197
|
if (resource.policy) _.set(resource, "opts.policy", resource.policy);
|
|
176
198
|
if (typeof resource["auto-redirect"] === "boolean") _.set(resource, "opts.redirection", resource["auto-redirect"]);
|
|
177
|
-
//
|
|
199
|
+
// Quantumult X 使用 `bodyBytes` 传输二进制请求体。
|
|
200
|
+
// Quantumult X uses `bodyBytes` for binary request payloads.
|
|
178
201
|
if (resource.body instanceof ArrayBuffer) {
|
|
179
202
|
resource.bodyBytes = resource.body;
|
|
180
203
|
resource.body = undefined;
|
|
@@ -182,9 +205,10 @@ export async function fetch(resource, options = {}) {
|
|
|
182
205
|
resource.bodyBytes = resource.body.buffer.slice(resource.body.byteOffset, resource.body.byteLength + resource.body.byteOffset);
|
|
183
206
|
resource.body = undefined;
|
|
184
207
|
} else if (resource.body) resource.bodyBytes = undefined;
|
|
185
|
-
//
|
|
208
|
+
// 发送请求,并用 `Promise.race` 提供统一超时保护。
|
|
209
|
+
// Send the request and enforce timeout with `Promise.race`.
|
|
186
210
|
return Promise.race([
|
|
187
|
-
|
|
211
|
+
globalThis.$task.fetch(resource).then(
|
|
188
212
|
response => {
|
|
189
213
|
response.ok = /^2\d\d$/.test(response.statusCode);
|
|
190
214
|
response.status = response.statusCode;
|
|
@@ -215,16 +239,37 @@ export async function fetch(resource, options = {}) {
|
|
|
215
239
|
}),
|
|
216
240
|
]);
|
|
217
241
|
case "Node.js": {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
242
|
+
// Node.js 优先复用原生/宿主 `fetch`,缺失时再回退到 `node-fetch`。
|
|
243
|
+
// Reuse host `fetch` in Node.js when available and fall back to `node-fetch` otherwise.
|
|
244
|
+
if (!globalThis.fetch) globalThis.fetch = require("node-fetch");
|
|
245
|
+
switch (resource["auto-cookie"]) {
|
|
246
|
+
case undefined:
|
|
247
|
+
case "true":
|
|
248
|
+
case true:
|
|
249
|
+
case "1":
|
|
250
|
+
case 1:
|
|
251
|
+
default:
|
|
252
|
+
// 仅在尚未包裹 CookieJar 时注入 `fetch-cookie`,避免重复包装。
|
|
253
|
+
// Inject `fetch-cookie` only once when a cookie jar is not already attached.
|
|
254
|
+
if (!globalThis.fetch?.cookieJar) globalThis.fetch = require("fetch-cookie").default(globalThis.fetch);
|
|
255
|
+
break;
|
|
256
|
+
case "false":
|
|
257
|
+
case false:
|
|
258
|
+
case "0":
|
|
259
|
+
case 0:
|
|
260
|
+
case "-1":
|
|
261
|
+
case -1:
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
// 将通用字段映射到 Node.js Fetch 语义。
|
|
265
|
+
// Map shared fields to Node.js Fetch semantics.
|
|
223
266
|
resource.redirect = resource.redirection ? "follow" : "manual";
|
|
224
267
|
const { url, ...options } = resource;
|
|
225
|
-
//
|
|
268
|
+
// 发起请求并归一化响应头、文本与二进制响应体。
|
|
269
|
+
// Send the request and normalize headers, text, and binary response data.
|
|
226
270
|
return Promise.race([
|
|
227
|
-
|
|
271
|
+
globalThis
|
|
272
|
+
.fetch(url, options)
|
|
228
273
|
.then(async response => {
|
|
229
274
|
const bodyBytes = await response.arrayBuffer();
|
|
230
275
|
let headers;
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
declare module "@nsnanocat/util" {
|
|
2
|
-
export type AppName =
|
|
2
|
+
export type AppName =
|
|
3
|
+
| "Quantumult X"
|
|
4
|
+
| "Loon"
|
|
5
|
+
| "Shadowrocket"
|
|
6
|
+
| "Egern"
|
|
7
|
+
| "Surge"
|
|
8
|
+
| "Stash"
|
|
9
|
+
| "Node.js";
|
|
3
10
|
|
|
4
11
|
export const $app: AppName | undefined;
|
|
5
12
|
export const $argument: Record<string, unknown>;
|
|
@@ -54,6 +61,7 @@ declare module "@nsnanocat/util" {
|
|
|
54
61
|
policy?: string;
|
|
55
62
|
redirection?: boolean;
|
|
56
63
|
"auto-redirect"?: boolean;
|
|
64
|
+
"auto-cookie"?: boolean | number | string;
|
|
57
65
|
opts?: Record<string, unknown>;
|
|
58
66
|
[key: string]: unknown;
|
|
59
67
|
}
|