zentao-api 0.6.4 → 0.6.6
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/dist/browser/zentao-api.global.js +26 -18
- package/dist/client/index.d.ts +4 -1
- package/dist/client/index.js +194 -17
- package/dist/index.d.ts +1 -1
- package/dist/misc/environment.d.ts +0 -2
- package/dist/misc/environment.js +43 -19
- package/dist/misc/errors.d.ts +1 -0
- package/dist/misc/errors.js +1 -0
- package/dist/modules/generated.d.ts +2045 -59
- package/dist/modules/generated.js +1027 -55
- package/dist/modules/override.js +36 -66
- package/dist/modules/query.d.ts +0 -2
- package/dist/modules/query.js +5 -15
- package/dist/modules/registry.d.ts +0 -9669
- package/dist/modules/registry.js +0 -4
- package/dist/modules/resolve.js +1 -1
- package/dist/profiles/index.js +1 -4
- package/dist/request/index.d.ts +12 -4
- package/dist/request/index.js +2 -2
- package/dist/types/client.d.ts +3 -3
- package/dist/types/module.d.ts +6 -2
- package/dist/types/options.d.ts +1 -0
- package/dist/utils/doc-helper/index.d.ts +1 -2
- package/dist/utils/doc-helper/index.js +0 -1
- package/dist/utils/doc-helper/inline.d.ts +0 -1
- package/dist/utils/doc-helper/inline.js +3 -81
- package/dist/utils/doc-helper/shared.d.ts +0 -5
- package/dist/utils/doc-helper/shared.js +0 -34
- package/dist/utils/doc-helper/types.d.ts +1 -13
- package/dist/version.js +2 -2
- package/package.json +9 -8
- package/dist/utils/doc-helper/html.d.ts +0 -3
- package/dist/utils/doc-helper/html.js +0 -442
package/dist/client/index.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export declare class ZentaoClient {
|
|
|
42
42
|
*
|
|
43
43
|
* 特殊处理:
|
|
44
44
|
* - 默认 HTTP 方法为 `GET`,`GET` 请求即使提供了 `options.body` 也不会发送,避免被部分代理/浏览器拒绝。
|
|
45
|
+
* - 不自动跟随重定向,避免把 `Token` 或请求体转发到另一个地址。
|
|
45
46
|
* - 非空响应优先按 JSON 解析;解析失败时回落为字符串原文。
|
|
46
47
|
* - 业务层失败(即响应体 `{ status: "fail" }`)不会抛出,仍按原样返回;只有 HTTP/网络/超时等传输层错误才会抛错。
|
|
47
48
|
* - `insecure` 仅在 Node.js 下可用,浏览器中传入会抛 `E_INSECURE_BROWSER`。
|
|
@@ -50,7 +51,9 @@ export declare class ZentaoClient {
|
|
|
50
51
|
* @param options - 单次请求选项,参见 {@link ClientRequestOptions}。
|
|
51
52
|
* @returns 解析后的响应体;当响应为空字符串时返回 `undefined`。
|
|
52
53
|
* @throws {ZentaoError} 可能抛出 `E_HTTP_ERROR`(非 2xx 状态)、`E_NETWORK_ERROR`(底层 fetch 失败)、
|
|
53
|
-
* `E_TIMEOUT`(超过 `timeout
|
|
54
|
+
* `E_TIMEOUT`(超过 `timeout`)、`E_ABORTED`(外部信号取消)或
|
|
55
|
+
* `E_INSECURE_BROWSER`(浏览器中开启了 `insecure`);传入 `ReadableStream` 请求体时会抛
|
|
56
|
+
* `E_INVALID_PARAM`。
|
|
54
57
|
*/
|
|
55
58
|
request(path: string, options: ClientRequestOptions & {
|
|
56
59
|
responseType: 'response';
|
package/dist/client/index.js
CHANGED
|
@@ -4,14 +4,27 @@ import { getGlobalOptions, setGlobalOptions } from '../misc/global-options.js';
|
|
|
4
4
|
import { addProfile, switchProfile } from '../profiles/index.js';
|
|
5
5
|
import { isRecord, normalizeSiteUrl } from '../utils/index.js';
|
|
6
6
|
const DEFAULT_TIMEOUT = 10000;
|
|
7
|
-
|
|
7
|
+
function appendQueryValue(search, key, value) {
|
|
8
|
+
if (value === undefined)
|
|
9
|
+
return;
|
|
10
|
+
if (Array.isArray(value)) {
|
|
11
|
+
value.forEach((item, index) => appendQueryValue(search, `${key}[${index}]`, item));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (isPlainObject(value)) {
|
|
15
|
+
for (const [childKey, childValue] of Object.entries(value)) {
|
|
16
|
+
appendQueryValue(search, `${key}[${childKey}]`, childValue);
|
|
17
|
+
}
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
search.append(key, value === null ? '' : String(value));
|
|
21
|
+
}
|
|
22
|
+
/** 拼接 API 路径与查询参数;结构化值使用 deepObject 风格的方括号键。 */
|
|
8
23
|
function buildUrl(baseUrl, path, query) {
|
|
9
24
|
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
|
|
10
25
|
const url = new URL(`${baseUrl}${normalizedPath}`);
|
|
11
26
|
for (const [key, value] of Object.entries(query ?? {})) {
|
|
12
|
-
|
|
13
|
-
continue;
|
|
14
|
-
url.searchParams.set(key, String(value));
|
|
27
|
+
appendQueryValue(url.searchParams, key, value);
|
|
15
28
|
}
|
|
16
29
|
return url.toString();
|
|
17
30
|
}
|
|
@@ -41,6 +54,9 @@ function appendFormValue(form, key, value) {
|
|
|
41
54
|
function serializeBody(body, bodyType, headers) {
|
|
42
55
|
if (body === undefined || body === null)
|
|
43
56
|
return undefined;
|
|
57
|
+
if (isInstanceOfGlobal(body, 'ReadableStream')) {
|
|
58
|
+
throw new ZentaoError('E_INVALID_PARAM', { param: 'body', value: 'ReadableStream' });
|
|
59
|
+
}
|
|
44
60
|
if (bodyType === 'form') {
|
|
45
61
|
const form = body instanceof URLSearchParams ? body : new URLSearchParams();
|
|
46
62
|
if (!(body instanceof URLSearchParams) && isPlainObject(body)) {
|
|
@@ -60,8 +76,7 @@ function serializeBody(body, bodyType, headers) {
|
|
|
60
76
|
isArrayBufferBody(body) ||
|
|
61
77
|
isInstanceOfGlobal(body, 'FormData') ||
|
|
62
78
|
isInstanceOfGlobal(body, 'URLSearchParams') ||
|
|
63
|
-
isInstanceOfGlobal(body, 'Blob')
|
|
64
|
-
isInstanceOfGlobal(body, 'ReadableStream')) {
|
|
79
|
+
isInstanceOfGlobal(body, 'Blob')) {
|
|
65
80
|
return body;
|
|
66
81
|
}
|
|
67
82
|
if (!headers.has('Content-Type')) {
|
|
@@ -71,8 +86,26 @@ function serializeBody(body, bodyType, headers) {
|
|
|
71
86
|
}
|
|
72
87
|
function createRequestSignal(timeout, externalSignal) {
|
|
73
88
|
const controller = new AbortController();
|
|
74
|
-
|
|
75
|
-
|
|
89
|
+
let timedOut = false;
|
|
90
|
+
let cleaned = false;
|
|
91
|
+
let timer;
|
|
92
|
+
const cleanup = () => {
|
|
93
|
+
if (cleaned)
|
|
94
|
+
return;
|
|
95
|
+
cleaned = true;
|
|
96
|
+
clearTimeout(timer);
|
|
97
|
+
externalSignal?.removeEventListener('abort', abortFromExternal);
|
|
98
|
+
};
|
|
99
|
+
const abortFromExternal = () => {
|
|
100
|
+
controller.abort(externalSignal?.reason);
|
|
101
|
+
cleanup();
|
|
102
|
+
};
|
|
103
|
+
timer = setTimeout(() => {
|
|
104
|
+
timedOut = true;
|
|
105
|
+
controller.abort();
|
|
106
|
+
cleanup();
|
|
107
|
+
}, timeout);
|
|
108
|
+
timer.unref?.();
|
|
76
109
|
if (externalSignal?.aborted) {
|
|
77
110
|
abortFromExternal();
|
|
78
111
|
}
|
|
@@ -81,12 +114,145 @@ function createRequestSignal(timeout, externalSignal) {
|
|
|
81
114
|
}
|
|
82
115
|
return {
|
|
83
116
|
signal: controller.signal,
|
|
84
|
-
cleanup
|
|
85
|
-
|
|
86
|
-
externalSignal?.removeEventListener('abort', abortFromExternal);
|
|
87
|
-
},
|
|
117
|
+
cleanup,
|
|
118
|
+
didTimeout: () => timedOut,
|
|
88
119
|
};
|
|
89
120
|
}
|
|
121
|
+
function keepResponseSignalUntilBodyEnds(response, cleanup, state = { branches: new Set(), cleanup, complete: false }) {
|
|
122
|
+
const branch = Symbol();
|
|
123
|
+
state.branches.add(branch);
|
|
124
|
+
let branchFinished = false;
|
|
125
|
+
const finishBranch = (bodyComplete) => {
|
|
126
|
+
if (branchFinished)
|
|
127
|
+
return;
|
|
128
|
+
branchFinished = true;
|
|
129
|
+
state.branches.delete(branch);
|
|
130
|
+
if (!state.complete && (bodyComplete || state.branches.size === 0)) {
|
|
131
|
+
state.complete = true;
|
|
132
|
+
state.cleanup();
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
let prototype = response;
|
|
136
|
+
let nativeBodyGetter;
|
|
137
|
+
while (prototype && !nativeBodyGetter) {
|
|
138
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, 'body');
|
|
139
|
+
if (descriptor?.get) {
|
|
140
|
+
nativeBodyGetter = descriptor.get.bind(response);
|
|
141
|
+
}
|
|
142
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
143
|
+
}
|
|
144
|
+
if (!nativeBodyGetter) {
|
|
145
|
+
finishBranch(true);
|
|
146
|
+
return response;
|
|
147
|
+
}
|
|
148
|
+
if (!nativeBodyGetter()) {
|
|
149
|
+
finishBranch(true);
|
|
150
|
+
return response;
|
|
151
|
+
}
|
|
152
|
+
let wrappedBody;
|
|
153
|
+
Object.defineProperty(response, 'body', {
|
|
154
|
+
configurable: true,
|
|
155
|
+
get() {
|
|
156
|
+
const nativeBody = nativeBodyGetter();
|
|
157
|
+
if (!nativeBody) {
|
|
158
|
+
wrappedBody = null;
|
|
159
|
+
finishBranch(true);
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
if (wrappedBody === undefined) {
|
|
163
|
+
let reader;
|
|
164
|
+
const getReader = () => reader ??= nativeBodyGetter().getReader();
|
|
165
|
+
wrappedBody = new ReadableStream({
|
|
166
|
+
type: 'bytes',
|
|
167
|
+
async pull(controller) {
|
|
168
|
+
let activeReader;
|
|
169
|
+
try {
|
|
170
|
+
activeReader = getReader();
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
controller.error(error);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
const chunk = await activeReader.read();
|
|
178
|
+
if (chunk.done) {
|
|
179
|
+
finishBranch(true);
|
|
180
|
+
const byobRequest = 'byobRequest' in controller ? controller.byobRequest : null;
|
|
181
|
+
controller.close();
|
|
182
|
+
byobRequest?.respond(0);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
const value = new Uint8Array(chunk.value.byteLength);
|
|
186
|
+
value.set(chunk.value);
|
|
187
|
+
controller.enqueue(value);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
finishBranch(true);
|
|
192
|
+
controller.error(error);
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
async cancel(reason) {
|
|
196
|
+
const activeReader = getReader();
|
|
197
|
+
try {
|
|
198
|
+
await activeReader.cancel(reason);
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
finishBranch(false);
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
}, { highWaterMark: 0 });
|
|
205
|
+
}
|
|
206
|
+
return wrappedBody;
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
for (const name of ['arrayBuffer', 'blob', 'formData', 'json', 'text', 'bytes']) {
|
|
210
|
+
const original = Reflect.get(response, name);
|
|
211
|
+
if (typeof original !== 'function')
|
|
212
|
+
continue;
|
|
213
|
+
Object.defineProperty(response, name, {
|
|
214
|
+
configurable: true,
|
|
215
|
+
value: (...args) => {
|
|
216
|
+
if (wrappedBody?.locked) {
|
|
217
|
+
return Promise.reject(new TypeError('Response body is locked.'));
|
|
218
|
+
}
|
|
219
|
+
const nativeBody = nativeBodyGetter();
|
|
220
|
+
const canConsume = !response.bodyUsed && !nativeBody?.locked;
|
|
221
|
+
const wrapperReader = canConsume ? response.body?.getReader() : undefined;
|
|
222
|
+
let result;
|
|
223
|
+
try {
|
|
224
|
+
result = Reflect.apply(original, response, args);
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
wrapperReader?.releaseLock();
|
|
228
|
+
throw error;
|
|
229
|
+
}
|
|
230
|
+
if (!canConsume)
|
|
231
|
+
return result;
|
|
232
|
+
return result.then((value) => {
|
|
233
|
+
wrapperReader?.releaseLock();
|
|
234
|
+
finishBranch(true);
|
|
235
|
+
return value;
|
|
236
|
+
}, (error) => {
|
|
237
|
+
wrapperReader?.releaseLock();
|
|
238
|
+
if (response.bodyUsed)
|
|
239
|
+
finishBranch(true);
|
|
240
|
+
throw error;
|
|
241
|
+
});
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
const clone = response.clone.bind(response);
|
|
246
|
+
Object.defineProperty(response, 'clone', {
|
|
247
|
+
configurable: true,
|
|
248
|
+
value: () => {
|
|
249
|
+
if (wrappedBody?.locked)
|
|
250
|
+
throw new TypeError('Response body is locked.');
|
|
251
|
+
return keepResponseSignalUntilBodyEnds(clone(), cleanup, state);
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
return response;
|
|
255
|
+
}
|
|
90
256
|
/** 按指定策略解析响应;默认优先 JSON,失败后保留原始文本。 */
|
|
91
257
|
async function parseResponse(response, responseType = 'auto') {
|
|
92
258
|
if (responseType === 'response')
|
|
@@ -151,16 +317,19 @@ export class ZentaoClient {
|
|
|
151
317
|
if (this.token) {
|
|
152
318
|
headers.set('Token', this.token);
|
|
153
319
|
}
|
|
154
|
-
const { signal, cleanup } = createRequestSignal(timeout, options.signal);
|
|
155
320
|
const init = {
|
|
156
321
|
method,
|
|
157
322
|
headers,
|
|
158
|
-
|
|
323
|
+
redirect: 'manual',
|
|
159
324
|
};
|
|
160
325
|
// GET 请求不携带 body,避免浏览器和部分代理拒绝请求。
|
|
161
326
|
if (options.body !== undefined && method !== 'GET') {
|
|
162
327
|
init.body = serializeBody(options.body, options.bodyType, headers);
|
|
163
328
|
}
|
|
329
|
+
// 先完成同步序列化,再启动计时器,避免序列化失败遗留活动 timer。
|
|
330
|
+
const { signal, cleanup, didTimeout } = createRequestSignal(timeout, options.signal);
|
|
331
|
+
init.signal = signal;
|
|
332
|
+
let keepResponseSignal = false;
|
|
164
333
|
try {
|
|
165
334
|
const response = await fetchWithInsecureTls(insecure, url, init);
|
|
166
335
|
if (!response.ok) {
|
|
@@ -174,18 +343,26 @@ export class ZentaoClient {
|
|
|
174
343
|
body: await response.text().catch(() => undefined),
|
|
175
344
|
});
|
|
176
345
|
}
|
|
177
|
-
|
|
346
|
+
if (options.responseType === 'response') {
|
|
347
|
+
keepResponseSignal = true;
|
|
348
|
+
return keepResponseSignalUntilBodyEnds(response, cleanup);
|
|
349
|
+
}
|
|
350
|
+
return await parseResponse(response, options.responseType);
|
|
178
351
|
}
|
|
179
352
|
catch (error) {
|
|
353
|
+
if (signal.aborted) {
|
|
354
|
+
throw new ZentaoError(didTimeout() ? 'E_TIMEOUT' : 'E_ABORTED', undefined, error);
|
|
355
|
+
}
|
|
180
356
|
if (error instanceof ZentaoError)
|
|
181
357
|
throw error;
|
|
182
358
|
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
183
|
-
throw new ZentaoError('
|
|
359
|
+
throw new ZentaoError('E_ABORTED', undefined, error);
|
|
184
360
|
}
|
|
185
361
|
throw new ZentaoError('E_NETWORK_ERROR', { message: error.message ?? String(error) }, error);
|
|
186
362
|
}
|
|
187
363
|
finally {
|
|
188
|
-
|
|
364
|
+
if (!keepResponseSignal)
|
|
365
|
+
cleanup();
|
|
189
366
|
}
|
|
190
367
|
}
|
|
191
368
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -6,4 +6,4 @@ export { defineModuleActions, defineModules, type DefineModulesOptions, type Exp
|
|
|
6
6
|
export { request, type BuiltinRequestName, type RequestParamsFor, type RequestResultFor, } from './request/index.js';
|
|
7
7
|
export { pickFields, pickFieldsSingle, filterData, searchData, sortData, processData, } from './utils/index.js';
|
|
8
8
|
export { BUILD, VERSION } from './version.js';
|
|
9
|
-
export type
|
|
9
|
+
export type * from './types/index.js';
|
|
@@ -4,5 +4,3 @@ export declare function isNodeRuntime(): boolean;
|
|
|
4
4
|
export declare function assertInsecureSupported(enabled: boolean | undefined): void;
|
|
5
5
|
/** 发起 fetch 请求;Node.js 下的 `insecure` 只作用于当前 HTTPS 请求。 */
|
|
6
6
|
export declare function fetchWithInsecureTls(enabled: boolean | undefined, url: string, init: RequestInit): Promise<Response>;
|
|
7
|
-
/** 保留给内部测试和兼容调用:校验 TLS 选项,但不再改写进程级环境变量。 */
|
|
8
|
-
export declare function withInsecureTls<T>(enabled: boolean | undefined, fn: () => Promise<T>): Promise<T>;
|
package/dist/misc/environment.js
CHANGED
|
@@ -61,6 +61,9 @@ async function toNodeBody(body, headers) {
|
|
|
61
61
|
}
|
|
62
62
|
return body.toString();
|
|
63
63
|
}
|
|
64
|
+
if (typeof ReadableStream !== 'undefined' && body instanceof ReadableStream) {
|
|
65
|
+
throw new ZentaoError('E_INVALID_PARAM', { param: 'body', value: 'ReadableStream' });
|
|
66
|
+
}
|
|
64
67
|
return String(body);
|
|
65
68
|
}
|
|
66
69
|
function abortError() {
|
|
@@ -82,23 +85,55 @@ async function nodeFetchWithTlsOptions(url, init, rejectUnauthorized) {
|
|
|
82
85
|
? await importNodeModule('node:https')
|
|
83
86
|
: await importNodeModule('node:http');
|
|
84
87
|
const headers = toNodeRequestHeaders(init.headers);
|
|
88
|
+
if (!hasHeader(headers, 'accept-encoding')) {
|
|
89
|
+
headers['accept-encoding'] = 'identity';
|
|
90
|
+
}
|
|
85
91
|
const body = await toNodeBody(init.body, headers);
|
|
86
92
|
return new Promise((resolve, reject) => {
|
|
87
93
|
if (init.signal?.aborted) {
|
|
88
94
|
reject(abortError());
|
|
89
95
|
return;
|
|
90
96
|
}
|
|
97
|
+
let settled = false;
|
|
98
|
+
let activeResponse;
|
|
99
|
+
const cleanup = () => {
|
|
100
|
+
init.signal?.removeEventListener('abort', abortHandler);
|
|
101
|
+
};
|
|
102
|
+
const rejectOnce = (error) => {
|
|
103
|
+
if (settled)
|
|
104
|
+
return;
|
|
105
|
+
settled = true;
|
|
106
|
+
cleanup();
|
|
107
|
+
reject(error);
|
|
108
|
+
};
|
|
109
|
+
const resolveOnce = (response) => {
|
|
110
|
+
if (settled)
|
|
111
|
+
return;
|
|
112
|
+
settled = true;
|
|
113
|
+
cleanup();
|
|
114
|
+
resolve(response);
|
|
115
|
+
};
|
|
91
116
|
const request = transport.request(parsed, {
|
|
92
117
|
method: init.method ?? 'GET',
|
|
93
118
|
headers,
|
|
94
119
|
rejectUnauthorized,
|
|
95
120
|
}, (response) => {
|
|
121
|
+
activeResponse = response;
|
|
96
122
|
const chunks = [];
|
|
123
|
+
let ended = false;
|
|
97
124
|
response.on('data', (chunk) => {
|
|
98
125
|
chunks.push(typeof chunk === 'string' ? new TextEncoder().encode(chunk) : chunk);
|
|
99
126
|
});
|
|
100
|
-
response.
|
|
101
|
-
|
|
127
|
+
response.once('aborted', () => {
|
|
128
|
+
rejectOnce(new Error('HTTP response was aborted before completion.'));
|
|
129
|
+
});
|
|
130
|
+
response.once('error', rejectOnce);
|
|
131
|
+
response.once('close', () => {
|
|
132
|
+
if (!ended)
|
|
133
|
+
rejectOnce(new Error('HTTP response closed before completion.'));
|
|
134
|
+
});
|
|
135
|
+
response.once('end', () => {
|
|
136
|
+
ended = true;
|
|
102
137
|
const responseBody = chunks.length > 0 ? concatenateChunks(chunks) : undefined;
|
|
103
138
|
const fetchResponse = new Response(responseBody, {
|
|
104
139
|
status: response.statusCode ?? 200,
|
|
@@ -106,20 +141,16 @@ async function nodeFetchWithTlsOptions(url, init, rejectUnauthorized) {
|
|
|
106
141
|
headers: toResponseHeaders(response.headers),
|
|
107
142
|
});
|
|
108
143
|
Object.defineProperty(fetchResponse, 'url', { value: url });
|
|
109
|
-
|
|
144
|
+
resolveOnce(fetchResponse);
|
|
110
145
|
});
|
|
111
146
|
});
|
|
112
|
-
const cleanup = () => {
|
|
113
|
-
init.signal?.removeEventListener('abort', abortHandler);
|
|
114
|
-
};
|
|
115
147
|
const abortHandler = () => {
|
|
116
|
-
|
|
117
|
-
|
|
148
|
+
const error = abortError();
|
|
149
|
+
rejectOnce(error);
|
|
150
|
+
activeResponse?.destroy(error);
|
|
151
|
+
request.destroy(error);
|
|
118
152
|
};
|
|
119
|
-
request.
|
|
120
|
-
cleanup();
|
|
121
|
-
reject(error);
|
|
122
|
-
});
|
|
153
|
+
request.once('error', rejectOnce);
|
|
123
154
|
init.signal?.addEventListener('abort', abortHandler, { once: true });
|
|
124
155
|
if (body !== undefined)
|
|
125
156
|
request.write(body);
|
|
@@ -139,10 +170,3 @@ export async function fetchWithInsecureTls(enabled, url, init) {
|
|
|
139
170
|
assertInsecureSupported(enabled);
|
|
140
171
|
return nodeFetchWithTlsOptions(url, init, false);
|
|
141
172
|
}
|
|
142
|
-
/** 保留给内部测试和兼容调用:校验 TLS 选项,但不再改写进程级环境变量。 */
|
|
143
|
-
export async function withInsecureTls(enabled, fn) {
|
|
144
|
-
if (!enabled)
|
|
145
|
-
return fn();
|
|
146
|
-
assertInsecureSupported(enabled);
|
|
147
|
-
return fn();
|
|
148
|
-
}
|
package/dist/misc/errors.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare const ERRORS: {
|
|
|
10
10
|
readonly E_HTTP_ERROR: "HTTP request failed: {status} {statusText}";
|
|
11
11
|
readonly E_NETWORK_ERROR: "Network request failed: {message}";
|
|
12
12
|
readonly E_TIMEOUT: "Request timed out.";
|
|
13
|
+
readonly E_ABORTED: "Request was aborted.";
|
|
13
14
|
readonly E_INSECURE_BROWSER: "The insecure option is only supported in Node.js runtimes.";
|
|
14
15
|
readonly E_LOGIN_FAILED: "ZenTao login failed.";
|
|
15
16
|
readonly E_INVALID_PROFILE: "Invalid ZenTao profile.";
|
package/dist/misc/errors.js
CHANGED
|
@@ -10,6 +10,7 @@ export const ERRORS = {
|
|
|
10
10
|
E_HTTP_ERROR: 'HTTP request failed: {status} {statusText}',
|
|
11
11
|
E_NETWORK_ERROR: 'Network request failed: {message}',
|
|
12
12
|
E_TIMEOUT: 'Request timed out.',
|
|
13
|
+
E_ABORTED: 'Request was aborted.',
|
|
13
14
|
E_INSECURE_BROWSER: 'The insecure option is only supported in Node.js runtimes.',
|
|
14
15
|
E_LOGIN_FAILED: 'ZenTao login failed.',
|
|
15
16
|
E_INVALID_PROFILE: 'Invalid ZenTao profile.',
|