@base-web-kits/base-tools-web 1.1.0-alpha.0 → 1.1.0-alpha.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.
@@ -63,7 +63,7 @@ export interface RequestTask {
63
63
  /** 取消请求 */
64
64
  abort: () => void;
65
65
  /** 监听流式数据块接收事件 */
66
- onChunkReceived: (callback: ChunkCallback) => void;
66
+ onProgressUpdate: (callback: ChunkCallback) => void;
67
67
  /** 取消监听流式数据块接收事件 */
68
68
  offChunkReceived: () => void;
69
69
  }
@@ -138,7 +138,7 @@ export type ChunkCallback = (response: {
138
138
  *
139
139
  * const { task } = apiChatStream({question: '你好'}); // 发起流式请求
140
140
  *
141
- * task.onChunkReceived((res) => {
141
+ * task.onProgressUpdate((res) => {
142
142
  * console.log('ArrayBuffer', res.data); // 接收流式数据
143
143
  * });
144
144
  *
@@ -1 +1 @@
1
- {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/web/network/request.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/web/network/request.ts"],"names":[],"mappings":"AAWA,aAAa;AACb,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,MAAM,GACN,KAAK,GACL,QAAQ,GACR,SAAS,GACT,MAAM,GACN,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ;;;GAGG;AACH,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,WAAW,GACX,eAAe,GACf,IAAI,GACJ,QAAQ,GACR,eAAe,GACf,cAAc,CAAC,UAAU,CAAC,GAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,OAAO,EAAE,GACT,IAAI,CAAC;AAET;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,GAAG,IAAI,CAAC;AAEpG;;GAEG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/F;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IACnE,WAAW;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW;IACX,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,UAAU;IACV,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,WAAW;IACX,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,uDAAuD;IACvD,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC;IAEvB,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;IAEf,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAEhB,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,YAAY;IACZ,WAAW,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEjC,cAAc;IACd,WAAW,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEjC,uBAAuB;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,wBAAwB;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,sBAAsB;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEnC,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,uBAAuB;IACvB,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,MAAM,CAAC;IAE/C,WAAW;IACX,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,YAAY,CAAC;CAC5D,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW;IACX,KAAK,EAAE,MAAM,IAAI,CAAC;IAElB,kBAAkB;IAClB,gBAAgB,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAC;IAEpD,oBAAoB;IACpB,gBAAgB,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,QAAQ,EAAE;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,KAAK,IAAI,CAAC;AAKtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuEG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC;WAoM9D,WAAW;EAMxC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base-web-kits/base-tools-web",
3
- "version": "1.1.0-alpha.0",
3
+ "version": "1.1.0-alpha.2",
4
4
  "sideEffects": false,
5
5
  "description": "Independent Web utilities package built from src/web.",
6
6
  "keywords": [
@@ -113,7 +113,7 @@ export interface RequestTask {
113
113
  abort: () => void;
114
114
 
115
115
  /** 监听流式数据块接收事件 */
116
- onChunkReceived: (callback: ChunkCallback) => void;
116
+ onProgressUpdate: (callback: ChunkCallback) => void;
117
117
 
118
118
  /** 取消监听流式数据块接收事件 */
119
119
  offChunkReceived: () => void;
@@ -192,7 +192,7 @@ const requestCache = new Map<string, { res: unknown; expire: number }>();
192
192
  *
193
193
  * const { task } = apiChatStream({question: '你好'}); // 发起流式请求
194
194
  *
195
- * task.onChunkReceived((res) => {
195
+ * task.onProgressUpdate((res) => {
196
196
  * console.log('ArrayBuffer', res.data); // 接收流式数据
197
197
  * });
198
198
  *
@@ -208,7 +208,7 @@ export function request<T, D extends RequestData = RequestData>(config: RequestC
208
208
  // 构造 Task 对象
209
209
  const task: RequestTask = {
210
210
  abort: () => controller.abort(),
211
- onChunkReceived: (cb) => {
211
+ onProgressUpdate: (cb) => {
212
212
  chunkCallback = cb;
213
213
  },
214
214
  offChunkReceived: () => {
@@ -250,7 +250,13 @@ export function request<T, D extends RequestData = RequestData>(config: RequestC
250
250
  // 请求头: 过滤空值 (undefined 、null 、"" 、false 、0), 因为服务器端接收到的都是字符串
251
251
  const fillHeader = (header ? pickBy(header, (val) => !!val) : {}) as Record<string, string>;
252
252
 
253
- if (!isGet && fillData && (isObjectData || isArrayData) && !fillHeader['Content-Type']) {
253
+ // 获取 Content-Type (忽略大小写)
254
+ const contentTypeKey = Object.keys(fillHeader).find(
255
+ (k) => k.toLowerCase() === 'content-type',
256
+ );
257
+ const contentType = contentTypeKey ? fillHeader[contentTypeKey].toLowerCase() : '';
258
+
259
+ if (!isGet && fillData && (isObjectData || isArrayData) && !contentType) {
254
260
  fillHeader['Content-Type'] = 'application/json';
255
261
  }
256
262
 
@@ -258,12 +264,23 @@ export function request<T, D extends RequestData = RequestData>(config: RequestC
258
264
  const fillUrl =
259
265
  isGet && isObjectData ? appendUrlParam(url, fillData as Record<string, unknown>) : url;
260
266
 
261
- const fillBody =
262
- !isGet && fillData
263
- ? isObjectData || isArrayData
264
- ? JSON.stringify(fillData)
265
- : (fillData as BodyInit)
266
- : undefined;
267
+ let fillBody: BodyInit | null | undefined;
268
+
269
+ if (!isGet && fillData) {
270
+ if (isObjectData && contentType.includes('application/x-www-form-urlencoded')) {
271
+ // application/x-www-form-urlencoded: 转换为 URLSearchParams
272
+ fillBody = toSearchParams(fillData as Record<string, unknown>);
273
+ } else if (isObjectData && contentType.includes('multipart/form-data')) {
274
+ // multipart/form-data: 转换为 FormData
275
+ fillBody = toFormData(fillData as Record<string, unknown>);
276
+ // 删除 Content-Type, 让 fetch 自动生成 boundary
277
+ if (contentTypeKey) delete fillHeader[contentTypeKey];
278
+ } else if (isObjectData || isArrayData) {
279
+ fillBody = JSON.stringify(fillData);
280
+ } else {
281
+ fillBody = fillData as BodyInit;
282
+ }
283
+ }
267
284
 
268
285
  // 2.3 日志与缓存配置
269
286
  const logConfig = { ...config, data: fillData, header: fillHeader, url: fillUrl };
@@ -489,3 +506,49 @@ async function parseResponse(response: Response, responseType: string) {
489
506
  }
490
507
  return resData;
491
508
  }
509
+
510
+ /**
511
+ * 转换为 URLSearchParams
512
+ */
513
+ function toSearchParams(data: Record<string, unknown>) {
514
+ const params = new URLSearchParams();
515
+ for (const key in data) {
516
+ const val = data[key];
517
+ // undefined 已在 fillData 阶段过滤,此处仅需判断 null
518
+ // null 在 Form 中会被转为字符串 "null",通常不符合预期,故过滤
519
+ if (val === null) continue;
520
+ if (Array.isArray(val)) {
521
+ val.forEach((v) => params.append(key, typeof v === 'object' ? JSON.stringify(v) : String(v)));
522
+ } else {
523
+ params.append(key, typeof val === 'object' ? JSON.stringify(val) : String(val));
524
+ }
525
+ }
526
+ return params;
527
+ }
528
+
529
+ /**
530
+ * 转换为 FormData
531
+ */
532
+ function toFormData(data: Record<string, unknown>) {
533
+ const formData = new FormData();
534
+ for (const key in data) {
535
+ const val = data[key];
536
+ // undefined 已在 fillData 阶段过滤,此处仅需判断 null
537
+ // null 在 Form 中会被转为字符串 "null",通常不符合预期,故过滤
538
+ if (val === null) continue;
539
+ if (Array.isArray(val)) {
540
+ val.forEach((v) =>
541
+ formData.append(
542
+ key,
543
+ v instanceof Blob ? v : typeof v === 'object' ? JSON.stringify(v) : String(v),
544
+ ),
545
+ );
546
+ } else {
547
+ formData.append(
548
+ key,
549
+ val instanceof Blob ? val : typeof val === 'object' ? JSON.stringify(val) : String(val),
550
+ );
551
+ }
552
+ }
553
+ return formData;
554
+ }