@wevu/web-apis 1.2.20 → 1.2.21

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.
@@ -0,0 +1,247 @@
1
+ import { f as isUrlInstance, l as normalizeHeaderName, n as cloneArrayBuffer, o as encodeText, p as isUrlSearchParamsInstance, r as cloneArrayBufferView } from "./shared-B_5_ZEFl.mjs";
2
+ import { HeadersPolyfill, ResponsePolyfill } from "./http.mjs";
3
+ import { resolveRequestMiniProgramOptions } from "./networkDefaults.mjs";
4
+ import { FormDataPolyfill } from "./web.mjs";
5
+ import { wpi } from "@wevu/api";
6
+ //#region src/multipart.ts
7
+ const CRLF = "\r\n";
8
+ function createMultipartBoundary() {
9
+ return `----weapp-vite-formdata-${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
10
+ }
11
+ function escapeMultipartName(value) {
12
+ return String(value).replaceAll("\\", "\\\\").replaceAll("\"", "\\\"").replaceAll("\r", "%0D").replaceAll("\n", "%0A");
13
+ }
14
+ function concatArrayBuffers(buffers) {
15
+ const totalLength = buffers.reduce((sum, buffer) => sum + buffer.byteLength, 0);
16
+ const merged = new Uint8Array(totalLength);
17
+ let offset = 0;
18
+ for (const buffer of buffers) {
19
+ merged.set(new Uint8Array(buffer), offset);
20
+ offset += buffer.byteLength;
21
+ }
22
+ return merged.buffer;
23
+ }
24
+ function isBlobFormDataValue(value) {
25
+ return typeof value !== "string" && typeof value?.arrayBuffer === "function";
26
+ }
27
+ function getMultipartFilename(value) {
28
+ const name = value.name;
29
+ return typeof name === "string" && name.length > 0 ? name : "blob";
30
+ }
31
+ async function createMultipartPart(name, value) {
32
+ if (!isBlobFormDataValue(value)) return [
33
+ encodeText(`Content-Disposition: form-data; name="${escapeMultipartName(name)}"${CRLF}${CRLF}`),
34
+ encodeText(String(value)),
35
+ encodeText(CRLF)
36
+ ];
37
+ const filename = getMultipartFilename(value);
38
+ return [
39
+ encodeText([
40
+ `Content-Disposition: form-data; name="${escapeMultipartName(name)}"; filename="${escapeMultipartName(filename)}"`,
41
+ `Content-Type: ${value.type || "application/octet-stream"}`,
42
+ "",
43
+ ""
44
+ ].join(CRLF)),
45
+ await value.arrayBuffer(),
46
+ encodeText(CRLF)
47
+ ];
48
+ }
49
+ async function encodeMultipartFormData(formData) {
50
+ const boundary = createMultipartBoundary();
51
+ const buffers = [];
52
+ for (const [name, value] of formData) {
53
+ buffers.push(encodeText(`--${boundary}${CRLF}`));
54
+ buffers.push(...await createMultipartPart(name, value));
55
+ }
56
+ buffers.push(encodeText(`--${boundary}--${CRLF}`));
57
+ return {
58
+ body: concatArrayBuffers(buffers),
59
+ contentType: `multipart/form-data; boundary=${boundary}`
60
+ };
61
+ }
62
+ //#endregion
63
+ //#region src/fetch.ts
64
+ const REQUEST_METHODS = [
65
+ "GET",
66
+ "HEAD",
67
+ "OPTIONS",
68
+ "POST",
69
+ "PUT",
70
+ "DELETE",
71
+ "TRACE",
72
+ "CONNECT"
73
+ ];
74
+ const hasOwn = Object.prototype.hasOwnProperty;
75
+ function isObject(value) {
76
+ return typeof value === "object" && value !== null;
77
+ }
78
+ function createAbortError() {
79
+ if (typeof DOMException === "function") return new DOMException("The operation was aborted.", "AbortError");
80
+ const error = /* @__PURE__ */ new Error("The operation was aborted.");
81
+ error.name = "AbortError";
82
+ return error;
83
+ }
84
+ function normalizeMethod(method) {
85
+ const normalized = (method ?? "GET").toUpperCase();
86
+ if (REQUEST_METHODS.includes(normalized)) return normalized;
87
+ return "GET";
88
+ }
89
+ function setHeader(target, key, value) {
90
+ const normalizedKey = normalizeHeaderName(key);
91
+ if (!normalizedKey) return;
92
+ const nextValue = String(value);
93
+ for (const currentKey of Object.keys(target)) if (normalizeHeaderName(currentKey) === normalizedKey) delete target[currentKey];
94
+ target[key] = nextValue;
95
+ }
96
+ function hasHeader(target, key) {
97
+ const normalizedKey = normalizeHeaderName(key);
98
+ return Object.keys(target).some((currentKey) => normalizeHeaderName(currentKey) === normalizedKey);
99
+ }
100
+ function mergeHeaderSource(target, source) {
101
+ if (!source) return;
102
+ if (typeof source.forEach === "function") {
103
+ source.forEach((value, key) => {
104
+ setHeader(target, key, value);
105
+ });
106
+ return;
107
+ }
108
+ if (typeof source[Symbol.iterator] === "function") {
109
+ for (const entry of source) {
110
+ if (!entry || entry.length < 2) continue;
111
+ setHeader(target, entry[0], entry[1]);
112
+ }
113
+ return;
114
+ }
115
+ if (!isObject(source)) return;
116
+ for (const [key, value] of Object.entries(source)) {
117
+ if (Array.isArray(value)) {
118
+ setHeader(target, key, value.join(", "));
119
+ continue;
120
+ }
121
+ setHeader(target, key, value);
122
+ }
123
+ }
124
+ function toHeaderMap(source) {
125
+ const headers = {};
126
+ mergeHeaderSource(headers, source);
127
+ return headers;
128
+ }
129
+ function isRequestLikeInput(input) {
130
+ return isObject(input) && typeof input.url === "string";
131
+ }
132
+ function isFormDataInstance(value) {
133
+ return Boolean(value && typeof value === "object" && (typeof FormData !== "undefined" && value instanceof FormData || value instanceof FormDataPolyfill));
134
+ }
135
+ async function extractRequestBodyFromInput(input) {
136
+ if (!input || typeof input.clone !== "function") return;
137
+ if (input.bodyUsed) throw new TypeError("Failed to execute fetch: request body is already used");
138
+ const cloned = input.clone();
139
+ if (cloned?.arrayBuffer) return cloned.arrayBuffer();
140
+ if (cloned?.text) return cloned.text();
141
+ }
142
+ async function normalizeRequestBody(body, headers) {
143
+ if (body == null) return;
144
+ if (typeof body === "string") {
145
+ if (!hasHeader(headers, "content-type")) headers["content-type"] = "text/plain;charset=UTF-8";
146
+ return body;
147
+ }
148
+ if (isUrlSearchParamsInstance(body)) {
149
+ if (!hasHeader(headers, "content-type")) headers["content-type"] = "application/x-www-form-urlencoded;charset=UTF-8";
150
+ return body.toString();
151
+ }
152
+ if (body instanceof ArrayBuffer) return cloneArrayBuffer(body);
153
+ if (ArrayBuffer.isView(body)) return cloneArrayBufferView(body);
154
+ if (typeof Blob !== "undefined" && body instanceof Blob) {
155
+ if (body.type && !hasHeader(headers, "content-type")) headers["content-type"] = body.type;
156
+ return body.arrayBuffer();
157
+ }
158
+ if (isFormDataInstance(body)) {
159
+ const payload = await encodeMultipartFormData(body);
160
+ if (!hasHeader(headers, "content-type")) headers["content-type"] = payload.contentType;
161
+ return payload.body;
162
+ }
163
+ return String(body);
164
+ }
165
+ async function resolveRequestMeta(input, init = {}) {
166
+ const requestInput = isRequestLikeInput(input) ? input : void 0;
167
+ const url = typeof input === "string" ? input : isUrlInstance(input) ? input.toString() : requestInput?.url;
168
+ if (!url) throw new TypeError("Failed to execute fetch: invalid request url");
169
+ const method = normalizeMethod(init.method ?? requestInput?.method);
170
+ const headers = toHeaderMap(requestInput?.headers);
171
+ mergeHeaderSource(headers, init.headers);
172
+ const hasBodyInInit = hasOwn.call(init, "body");
173
+ let rawBody = hasBodyInInit ? init.body : await extractRequestBodyFromInput(requestInput);
174
+ if (!hasBodyInInit && requestInput && (method === "GET" || method === "HEAD")) rawBody = void 0;
175
+ if ((method === "GET" || method === "HEAD") && rawBody != null) throw new TypeError("Failed to execute fetch: GET/HEAD request cannot have body");
176
+ return {
177
+ miniProgram: resolveRequestMiniProgramOptions(init.miniProgram, init.miniprogram),
178
+ url,
179
+ method,
180
+ headers,
181
+ body: await normalizeRequestBody(rawBody, headers),
182
+ signal: init.signal ?? requestInput?.signal ?? null
183
+ };
184
+ }
185
+ function createFetchResponse(data, status, headers, url) {
186
+ return new ResponsePolyfill(data instanceof Uint8Array ? cloneArrayBufferView(data) : data, {
187
+ status,
188
+ headers: new HeadersPolyfill(headers),
189
+ url
190
+ });
191
+ }
192
+ function isRequestTask(value) {
193
+ return isObject(value) && typeof value.abort === "function";
194
+ }
195
+ /**
196
+ * @description 使用 @wevu/api 的 request 能力实现 fetch 语义对齐。
197
+ */
198
+ function fetch(input, init) {
199
+ return resolveRequestMeta(input, init).then((meta) => {
200
+ if (meta.signal?.aborted) return Promise.reject(createAbortError());
201
+ return new Promise((resolve, reject) => {
202
+ let settled = false;
203
+ let aborted = false;
204
+ let requestTask;
205
+ function onAbort() {
206
+ if (settled) return;
207
+ aborted = true;
208
+ requestTask?.abort();
209
+ settled = true;
210
+ if (meta.signal) meta.signal.removeEventListener("abort", onAbort);
211
+ reject(createAbortError());
212
+ }
213
+ function cleanup() {
214
+ if (meta.signal) meta.signal.removeEventListener("abort", onAbort);
215
+ }
216
+ if (meta.signal) meta.signal.addEventListener("abort", onAbort, { once: true });
217
+ const requestResult = wpi.request({
218
+ ...meta.miniProgram,
219
+ url: meta.url,
220
+ method: meta.method,
221
+ header: meta.headers,
222
+ data: meta.body,
223
+ responseType: "arraybuffer",
224
+ success: (res) => {
225
+ if (settled) return;
226
+ settled = true;
227
+ cleanup();
228
+ resolve(createFetchResponse(res.data, res.statusCode, toHeaderMap(res.header), meta.url));
229
+ },
230
+ fail: (error) => {
231
+ if (settled) return;
232
+ settled = true;
233
+ cleanup();
234
+ if (aborted) {
235
+ reject(createAbortError());
236
+ return;
237
+ }
238
+ const message = isObject(error) && typeof error.errMsg === "string" ? error.errMsg : String(error);
239
+ reject(new TypeError(message));
240
+ }
241
+ });
242
+ requestTask = isRequestTask(requestResult) ? requestResult : void 0;
243
+ });
244
+ });
245
+ }
246
+ //#endregion
247
+ export { fetch as t };
package/dist/fetch.mjs CHANGED
@@ -1,182 +1,3 @@
1
- import { f as isUrlInstance, l as normalizeHeaderName, n as cloneArrayBuffer, p as isUrlSearchParamsInstance, r as cloneArrayBufferView } from "./shared-B_5_ZEFl.mjs";
2
- import { HeadersPolyfill, ResponsePolyfill } from "./http.mjs";
3
- import { resolveRequestMiniProgramOptions } from "./networkDefaults.mjs";
4
- import { wpi } from "@wevu/api";
5
- //#region src/fetch.ts
6
- const REQUEST_METHODS = [
7
- "GET",
8
- "HEAD",
9
- "OPTIONS",
10
- "POST",
11
- "PUT",
12
- "DELETE",
13
- "TRACE",
14
- "CONNECT"
15
- ];
16
- const hasOwn = Object.prototype.hasOwnProperty;
17
- function isObject(value) {
18
- return typeof value === "object" && value !== null;
19
- }
20
- function createAbortError() {
21
- if (typeof DOMException === "function") return new DOMException("The operation was aborted.", "AbortError");
22
- const error = /* @__PURE__ */ new Error("The operation was aborted.");
23
- error.name = "AbortError";
24
- return error;
25
- }
26
- function normalizeMethod(method) {
27
- const normalized = (method ?? "GET").toUpperCase();
28
- if (REQUEST_METHODS.includes(normalized)) return normalized;
29
- return "GET";
30
- }
31
- function setHeader(target, key, value) {
32
- const normalizedKey = normalizeHeaderName(key);
33
- if (!normalizedKey) return;
34
- const nextValue = String(value);
35
- for (const currentKey of Object.keys(target)) if (normalizeHeaderName(currentKey) === normalizedKey) delete target[currentKey];
36
- target[key] = nextValue;
37
- }
38
- function hasHeader(target, key) {
39
- const normalizedKey = normalizeHeaderName(key);
40
- return Object.keys(target).some((currentKey) => normalizeHeaderName(currentKey) === normalizedKey);
41
- }
42
- function mergeHeaderSource(target, source) {
43
- if (!source) return;
44
- if (typeof source.forEach === "function") {
45
- source.forEach((value, key) => {
46
- setHeader(target, key, value);
47
- });
48
- return;
49
- }
50
- if (typeof source[Symbol.iterator] === "function") {
51
- for (const entry of source) {
52
- if (!entry || entry.length < 2) continue;
53
- setHeader(target, entry[0], entry[1]);
54
- }
55
- return;
56
- }
57
- if (!isObject(source)) return;
58
- for (const [key, value] of Object.entries(source)) {
59
- if (Array.isArray(value)) {
60
- setHeader(target, key, value.join(", "));
61
- continue;
62
- }
63
- setHeader(target, key, value);
64
- }
65
- }
66
- function toHeaderMap(source) {
67
- const headers = {};
68
- mergeHeaderSource(headers, source);
69
- return headers;
70
- }
71
- function isRequestLikeInput(input) {
72
- return isObject(input) && typeof input.url === "string";
73
- }
74
- async function extractRequestBodyFromInput(input) {
75
- if (!input || typeof input.clone !== "function") return;
76
- if (input.bodyUsed) throw new TypeError("Failed to execute fetch: request body is already used");
77
- const cloned = input.clone();
78
- if (cloned?.arrayBuffer) return cloned.arrayBuffer();
79
- if (cloned?.text) return cloned.text();
80
- }
81
- async function normalizeRequestBody(body, headers) {
82
- if (body == null) return;
83
- if (typeof body === "string") {
84
- if (!hasHeader(headers, "content-type")) headers["content-type"] = "text/plain;charset=UTF-8";
85
- return body;
86
- }
87
- if (isUrlSearchParamsInstance(body)) {
88
- if (!hasHeader(headers, "content-type")) headers["content-type"] = "application/x-www-form-urlencoded;charset=UTF-8";
89
- return body.toString();
90
- }
91
- if (body instanceof ArrayBuffer) return cloneArrayBuffer(body);
92
- if (ArrayBuffer.isView(body)) return cloneArrayBufferView(body);
93
- if (typeof Blob !== "undefined" && body instanceof Blob) {
94
- if (body.type && !hasHeader(headers, "content-type")) headers["content-type"] = body.type;
95
- return body.arrayBuffer();
96
- }
97
- if (typeof FormData !== "undefined" && body instanceof FormData) throw new TypeError("Failed to execute fetch: FormData body is not supported in request globals fetch");
98
- return String(body);
99
- }
100
- async function resolveRequestMeta(input, init = {}) {
101
- const requestInput = isRequestLikeInput(input) ? input : void 0;
102
- const url = typeof input === "string" ? input : isUrlInstance(input) ? input.toString() : requestInput?.url;
103
- if (!url) throw new TypeError("Failed to execute fetch: invalid request url");
104
- const method = normalizeMethod(init.method ?? requestInput?.method);
105
- const headers = toHeaderMap(requestInput?.headers);
106
- mergeHeaderSource(headers, init.headers);
107
- const hasBodyInInit = hasOwn.call(init, "body");
108
- let rawBody = hasBodyInInit ? init.body : await extractRequestBodyFromInput(requestInput);
109
- if (!hasBodyInInit && requestInput && (method === "GET" || method === "HEAD")) rawBody = void 0;
110
- if ((method === "GET" || method === "HEAD") && rawBody != null) throw new TypeError("Failed to execute fetch: GET/HEAD request cannot have body");
111
- return {
112
- miniProgram: resolveRequestMiniProgramOptions(init.miniProgram, init.miniprogram),
113
- url,
114
- method,
115
- headers,
116
- body: await normalizeRequestBody(rawBody, headers),
117
- signal: init.signal ?? requestInput?.signal ?? null
118
- };
119
- }
120
- function createFetchResponse(data, status, headers, url) {
121
- return new ResponsePolyfill(data instanceof Uint8Array ? cloneArrayBufferView(data) : data, {
122
- status,
123
- headers: new HeadersPolyfill(headers),
124
- url
125
- });
126
- }
127
- function isRequestTask(value) {
128
- return isObject(value) && typeof value.abort === "function";
129
- }
130
- /**
131
- * @description 使用 @wevu/api 的 request 能力实现 fetch 语义对齐。
132
- */
133
- function fetch(input, init) {
134
- return resolveRequestMeta(input, init).then((meta) => {
135
- if (meta.signal?.aborted) return Promise.reject(createAbortError());
136
- return new Promise((resolve, reject) => {
137
- let settled = false;
138
- let aborted = false;
139
- let requestTask;
140
- function onAbort() {
141
- if (settled) return;
142
- aborted = true;
143
- requestTask?.abort();
144
- settled = true;
145
- if (meta.signal) meta.signal.removeEventListener("abort", onAbort);
146
- reject(createAbortError());
147
- }
148
- function cleanup() {
149
- if (meta.signal) meta.signal.removeEventListener("abort", onAbort);
150
- }
151
- if (meta.signal) meta.signal.addEventListener("abort", onAbort, { once: true });
152
- const requestResult = wpi.request({
153
- ...meta.miniProgram,
154
- url: meta.url,
155
- method: meta.method,
156
- header: meta.headers,
157
- data: meta.body,
158
- responseType: "arraybuffer",
159
- success: (res) => {
160
- if (settled) return;
161
- settled = true;
162
- cleanup();
163
- resolve(createFetchResponse(res.data, res.statusCode, toHeaderMap(res.header), meta.url));
164
- },
165
- fail: (error) => {
166
- if (settled) return;
167
- settled = true;
168
- cleanup();
169
- if (aborted) {
170
- reject(createAbortError());
171
- return;
172
- }
173
- const message = isObject(error) && typeof error.errMsg === "string" ? error.errMsg : String(error);
174
- reject(new TypeError(message));
175
- }
176
- });
177
- requestTask = isRequestTask(requestResult) ? requestResult : void 0;
178
- });
179
- });
180
- }
181
- //#endregion
1
+ import "./http.mjs";
2
+ import { t as fetch } from "./fetch-CETKuRWs.mjs";
182
3
  export { fetch };
package/dist/index.d.mts CHANGED
@@ -4,7 +4,7 @@ import { MiniProgramNetworkDefaults, RequestGlobalsMiniProgramOptions, WebSocket
4
4
  import { URLPolyfill, URLSearchParamsPolyfill } from "./url.mjs";
5
5
  import { fetch } from "./fetch.mjs";
6
6
  import { HeadersPolyfill, RequestPolyfill, ResponsePolyfill } from "./http.mjs";
7
- import { BlobPolyfill, FormDataPolyfill } from "./web.mjs";
7
+ import { BlobPolyfill, FilePolyfill, FormDataPolyfill } from "./web.mjs";
8
8
  import { WebSocketPolyfill } from "./websocket.mjs";
9
9
  import { XMLHttpRequestPolyfill } from "./xhr.mjs";
10
10
 
@@ -94,4 +94,4 @@ declare function installRequestGlobals(options?: InstallRequestGlobalsOptions):
94
94
  */
95
95
  declare function installAbortGlobals(): Record<string, any>;
96
96
  //#endregion
97
- export { AbortControllerPolyfill, AbortSignalPolyfill, BlobPolyfill, CustomEventPolyfill, EventPolyfill, FormDataPolyfill, HeadersPolyfill, InstallRequestGlobalsOptions, InstallWebRuntimeGlobalsOptions, type MiniProgramNetworkDefaults, RequestGlobalsEventTarget, type RequestGlobalsMiniProgramOptions, RequestPolyfill, ResponsePolyfill, TextDecoderPolyfill, TextEncoderPolyfill, URLPolyfill, URLSearchParamsPolyfill, WeappInjectRequestGlobalsTarget, WeappInjectWebRuntimeGlobalsTarget, type WebSocketMiniProgramOptions, WebSocketPolyfill, XMLHttpRequestPolyfill, atobPolyfill, btoaPolyfill, cryptoPolyfill, fetch, getMiniProgramNetworkDefaults, installAbortGlobals, installRequestGlobals, installWebRuntimeGlobals, performancePolyfill, queueMicrotaskPolyfill, resetMiniProgramNetworkDefaults, setMiniProgramNetworkDefaults };
97
+ export { AbortControllerPolyfill, AbortSignalPolyfill, BlobPolyfill, CustomEventPolyfill, EventPolyfill, FilePolyfill, FormDataPolyfill, HeadersPolyfill, InstallRequestGlobalsOptions, InstallWebRuntimeGlobalsOptions, type MiniProgramNetworkDefaults, RequestGlobalsEventTarget, type RequestGlobalsMiniProgramOptions, RequestPolyfill, ResponsePolyfill, TextDecoderPolyfill, TextEncoderPolyfill, URLPolyfill, URLSearchParamsPolyfill, WeappInjectRequestGlobalsTarget, WeappInjectWebRuntimeGlobalsTarget, type WebSocketMiniProgramOptions, WebSocketPolyfill, XMLHttpRequestPolyfill, atobPolyfill, btoaPolyfill, cryptoPolyfill, fetch, getMiniProgramNetworkDefaults, installAbortGlobals, installRequestGlobals, installWebRuntimeGlobals, performancePolyfill, queueMicrotaskPolyfill, resetMiniProgramNetworkDefaults, setMiniProgramNetworkDefaults };
package/dist/index.mjs CHANGED
@@ -2,9 +2,9 @@ import { a as decodeTextFallback, c as installRequestGlobalBinding, d as resolve
2
2
  import { URLPolyfill, URLSearchParamsPolyfill } from "./url.mjs";
3
3
  import { AbortControllerPolyfill, AbortSignalPolyfill } from "./abort.mjs";
4
4
  import { HeadersPolyfill, RequestPolyfill, ResponsePolyfill } from "./http.mjs";
5
+ import { t as fetch } from "./fetch-CETKuRWs.mjs";
5
6
  import { getMiniProgramNetworkDefaults, resetMiniProgramNetworkDefaults, setMiniProgramNetworkDefaults } from "./networkDefaults.mjs";
6
- import { fetch } from "./fetch.mjs";
7
- import { BlobPolyfill, FormDataPolyfill } from "./web.mjs";
7
+ import { BlobPolyfill, FilePolyfill, FormDataPolyfill } from "./web.mjs";
8
8
  import { WebSocketPolyfill } from "./websocket.mjs";
9
9
  import { XMLHttpRequestPolyfill } from "./xhr.mjs";
10
10
  import { REQUEST_GLOBAL_ACTUALS_KEY, REQUEST_GLOBAL_PLACEHOLDER_KEY } from "@weapp-core/constants";
@@ -211,7 +211,7 @@ function resolveActualBindingTargets(targets) {
211
211
  const bindingTargets = [...targets];
212
212
  if (hasRequestRuntimeBinaryUsage(targets)) {
213
213
  bindingTargets.push("TextEncoder", "TextDecoder");
214
- bindingTargets.push("URL", "URLSearchParams", "Blob", "FormData");
214
+ bindingTargets.push("URL", "URLSearchParams", "Blob", "File", "FormData");
215
215
  }
216
216
  return [...new Set(bindingTargets)];
217
217
  }
@@ -388,6 +388,7 @@ function installUrlGlobals(host) {
388
388
  if (!hasUsableConstructor(host.URL, ["https://request-globals.invalid"]) || !patchUrlConstructor(host)) assignHostGlobal(host, "URL", URLPolyfill);
389
389
  if (!hasUsableConstructor(host.URLSearchParams, ["client=graphql-request"]) || !patchUrlSearchParamsConstructor(host)) assignHostGlobal(host, "URLSearchParams", URLSearchParamsPolyfill);
390
390
  if (!hasUsableConstructor(host.Blob)) assignHostGlobal(host, "Blob", BlobPolyfill);
391
+ if (!hasUsableConstructor(host.File, [[], "request-globals.bin"])) assignHostGlobal(host, "File", FilePolyfill);
391
392
  if (!hasUsableConstructor(host.FormData)) assignHostGlobal(host, "FormData", FormDataPolyfill);
392
393
  }
393
394
  function installGlobalBindingIfNeeded(host, target) {
@@ -455,6 +456,7 @@ function installWebRuntimeGlobals(options = {}) {
455
456
  installGlobalBindingIfNeeded(primaryHost, "URL");
456
457
  installGlobalBindingIfNeeded(primaryHost, "URLSearchParams");
457
458
  installGlobalBindingIfNeeded(primaryHost, "Blob");
459
+ installGlobalBindingIfNeeded(primaryHost, "File");
458
460
  installGlobalBindingIfNeeded(primaryHost, "FormData");
459
461
  }
460
462
  for (const target of targets) installGlobalBindingIfNeeded(primaryHost, target);
@@ -474,4 +476,4 @@ function installAbortGlobals() {
474
476
  return installWebRuntimeGlobals({ targets: ["AbortController", "AbortSignal"] });
475
477
  }
476
478
  //#endregion
477
- export { AbortControllerPolyfill, AbortSignalPolyfill, BlobPolyfill, CustomEventPolyfill, EventPolyfill, FormDataPolyfill, HeadersPolyfill, RequestGlobalsEventTarget, RequestPolyfill, ResponsePolyfill, TextDecoderPolyfill, TextEncoderPolyfill, URLPolyfill, URLSearchParamsPolyfill, WebSocketPolyfill, XMLHttpRequestPolyfill, atobPolyfill, btoaPolyfill, cryptoPolyfill, fetch, getMiniProgramNetworkDefaults, installAbortGlobals, installRequestGlobals, installWebRuntimeGlobals, performancePolyfill, queueMicrotaskPolyfill, resetMiniProgramNetworkDefaults, setMiniProgramNetworkDefaults };
479
+ export { AbortControllerPolyfill, AbortSignalPolyfill, BlobPolyfill, CustomEventPolyfill, EventPolyfill, FilePolyfill, FormDataPolyfill, HeadersPolyfill, RequestGlobalsEventTarget, RequestPolyfill, ResponsePolyfill, TextDecoderPolyfill, TextEncoderPolyfill, URLPolyfill, URLSearchParamsPolyfill, WebSocketPolyfill, XMLHttpRequestPolyfill, atobPolyfill, btoaPolyfill, cryptoPolyfill, fetch, getMiniProgramNetworkDefaults, installAbortGlobals, installRequestGlobals, installWebRuntimeGlobals, performancePolyfill, queueMicrotaskPolyfill, resetMiniProgramNetworkDefaults, setMiniProgramNetworkDefaults };
package/dist/web.d.mts CHANGED
@@ -1,24 +1,41 @@
1
1
  //#region src/web.d.ts
2
- type BlobPart = ArrayBuffer | ArrayBufferView | BlobPolyfill | string;
2
+ interface BlobLikePart {
3
+ readonly size?: number;
4
+ readonly type?: string;
5
+ arrayBuffer: () => Promise<ArrayBuffer>;
6
+ }
7
+ type BlobPart = ArrayBuffer | ArrayBufferView | BlobLikePart | string;
8
+ type FormDataEntryValue = FilePolyfill | BlobPolyfill | string;
9
+ interface BlobPropertyBag {
10
+ type?: string;
11
+ }
12
+ interface FilePropertyBag extends BlobPropertyBag {
13
+ lastModified?: number;
14
+ }
3
15
  declare class BlobPolyfill {
4
16
  readonly size: number;
5
17
  readonly type: string;
6
18
  private readonly parts;
7
- constructor(parts?: BlobPart[], options?: {
8
- type?: string;
9
- });
19
+ constructor(parts?: BlobPart[], options?: BlobPropertyBag);
10
20
  arrayBuffer(): Promise<ArrayBuffer>;
11
21
  text(): Promise<string>;
12
22
  }
13
- type FormDataEntryValue = BlobPolyfill | string;
23
+ declare class FilePolyfill extends BlobPolyfill {
24
+ readonly lastModified: number;
25
+ readonly name: string;
26
+ constructor(parts: BlobPart[] | undefined, name: string, options?: FilePropertyBag);
27
+ get [Symbol.toStringTag](): string;
28
+ }
14
29
  declare class FormDataPolyfill {
15
30
  private readonly entriesList;
16
- append(name: string, value: FormDataEntryValue): void;
31
+ append(name: string, value: string): void;
32
+ append(name: string, value: BlobLikePart, filename?: string): void;
17
33
  delete(name: string): void;
18
- get(name: string): FormDataEntryValue | null;
34
+ get(name: string): string | BlobPolyfill | null;
19
35
  getAll(name: string): FormDataEntryValue[];
20
36
  has(name: string): boolean;
21
- set(name: string, value: FormDataEntryValue): void;
37
+ set(name: string, value: string): void;
38
+ set(name: string, value: BlobLikePart, filename?: string): void;
22
39
  forEach(callback: (value: FormDataEntryValue, key: string, parent: FormDataPolyfill) => void): void;
23
40
  entries(): Generator<[string, FormDataEntryValue], void, unknown>;
24
41
  keys(): Generator<string, void, unknown>;
@@ -27,4 +44,4 @@ declare class FormDataPolyfill {
27
44
  get [Symbol.toStringTag](): string;
28
45
  }
29
46
  //#endregion
30
- export { BlobPolyfill, FormDataPolyfill };
47
+ export { BlobLikePart, BlobPart, BlobPolyfill, FilePolyfill, FormDataEntryValue, FormDataPolyfill };
package/dist/web.mjs CHANGED
@@ -7,7 +7,7 @@ function normalizeBlobPart(part) {
7
7
  if (ArrayBuffer.isView(part)) return Promise.resolve(cloneArrayBufferView(part));
8
8
  return Promise.resolve(encodeText(String(part)));
9
9
  }
10
- var BlobPolyfill = class BlobPolyfill {
10
+ var BlobPolyfill = class {
11
11
  size;
12
12
  type;
13
13
  parts;
@@ -16,7 +16,7 @@ var BlobPolyfill = class BlobPolyfill {
16
16
  this.type = options?.type ?? "";
17
17
  this.size = parts.reduce((total, part) => {
18
18
  if (typeof part === "string") return total + String(part).length;
19
- if (part instanceof BlobPolyfill) return total + part.size;
19
+ if (part && typeof part === "object" && typeof part.size === "number") return total + Number(part.size);
20
20
  if (part instanceof ArrayBuffer) return total + part.byteLength;
21
21
  if (ArrayBuffer.isView(part)) return total + part.byteLength;
22
22
  return total;
@@ -37,10 +37,39 @@ var BlobPolyfill = class BlobPolyfill {
37
37
  return decodeText(await this.arrayBuffer());
38
38
  }
39
39
  };
40
+ var FilePolyfill = class extends BlobPolyfill {
41
+ lastModified;
42
+ name;
43
+ constructor(parts = [], name, options) {
44
+ super(parts, options);
45
+ this.name = String(name);
46
+ this.lastModified = options?.lastModified ?? Date.now();
47
+ }
48
+ get [Symbol.toStringTag]() {
49
+ return "File";
50
+ }
51
+ };
52
+ function isFileLikePart(value) {
53
+ return typeof value.name === "string" && typeof value.lastModified === "number";
54
+ }
55
+ function normalizeFormDataValue(value, filename) {
56
+ if (value instanceof FilePolyfill) {
57
+ if (filename === void 0) return value;
58
+ return new FilePolyfill([value], filename, {
59
+ lastModified: value.lastModified,
60
+ type: value.type
61
+ });
62
+ }
63
+ if (typeof value !== "string") return new FilePolyfill([value], filename ?? (isFileLikePart(value) ? value.name : "blob"), {
64
+ lastModified: isFileLikePart(value) ? value.lastModified : void 0,
65
+ type: value.type
66
+ });
67
+ return String(value);
68
+ }
40
69
  var FormDataPolyfill = class {
41
70
  entriesList = [];
42
- append(name, value) {
43
- this.entriesList.push([String(name), value instanceof BlobPolyfill ? value : String(value)]);
71
+ append(name, value, filename) {
72
+ this.entriesList.push([String(name), normalizeFormDataValue(value, filename)]);
44
73
  }
45
74
  delete(name) {
46
75
  const normalizedName = String(name);
@@ -56,9 +85,13 @@ var FormDataPolyfill = class {
56
85
  has(name) {
57
86
  return this.entriesList.some((entry) => entry[0] === String(name));
58
87
  }
59
- set(name, value) {
88
+ set(name, value, filename) {
60
89
  this.delete(name);
61
- this.append(name, value);
90
+ if (typeof value === "string") {
91
+ this.append(name, value);
92
+ return;
93
+ }
94
+ this.append(name, value, filename);
62
95
  }
63
96
  forEach(callback) {
64
97
  for (const [key, value] of this.entriesList) callback(value, key, this);
@@ -80,4 +113,4 @@ var FormDataPolyfill = class {
80
113
  }
81
114
  };
82
115
  //#endregion
83
- export { BlobPolyfill, FormDataPolyfill };
116
+ export { BlobPolyfill, FilePolyfill, FormDataPolyfill };
package/dist/xhr.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { t as RequestGlobalsEventTarget, u as resolveRequestGlobalsHost } from "./shared-B_5_ZEFl.mjs";
2
2
  import { AbortControllerPolyfill } from "./abort.mjs";
3
3
  import { HeadersPolyfill, headersToObject } from "./http.mjs";
4
- import { fetch } from "./fetch.mjs";
4
+ import { t as fetch } from "./fetch-CETKuRWs.mjs";
5
5
  //#region src/xhr.ts
6
6
  function createProgressEvent(type) {
7
7
  return {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wevu/web-apis",
3
3
  "type": "module",
4
- "version": "1.2.20",
4
+ "version": "1.2.21",
5
5
  "description": "Web API polyfills and global installers for mini-program runtimes",
6
6
  "author": "ice breaker <1324318532@qq.com>",
7
7
  "license": "MIT",