@base-web-kits/base-tools-web 1.3.3 → 1.3.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.
@@ -47,6 +47,7 @@ var baseToolsWeb = (() => {
47
47
  mod
48
48
  ));
49
49
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
50
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
50
51
  var __async = (__this, __arguments, generator) => {
51
52
  return new Promise((resolve, reject) => {
52
53
  var fulfilled = (value) => {
@@ -1771,6 +1772,262 @@ var baseToolsWeb = (() => {
1771
1772
  return base + (qs ? `?${qs}` : "") + hash;
1772
1773
  }
1773
1774
 
1775
+ // src/ts/buffer/PolyfillTextDecoder.ts
1776
+ var PolyfillTextDecoder = class {
1777
+ constructor() {
1778
+ __publicField(this, "leftOver", new Uint8Array(0));
1779
+ }
1780
+ decode(input, options) {
1781
+ var _a;
1782
+ const stream = (_a = options == null ? void 0 : options.stream) != null ? _a : false;
1783
+ let bytes;
1784
+ if (!input) {
1785
+ bytes = new Uint8Array(0);
1786
+ } else if (input instanceof ArrayBuffer) {
1787
+ bytes = new Uint8Array(input);
1788
+ } else {
1789
+ bytes = input;
1790
+ }
1791
+ if (this.leftOver.length > 0) {
1792
+ const merged = new Uint8Array(this.leftOver.length + bytes.length);
1793
+ merged.set(this.leftOver);
1794
+ merged.set(bytes, this.leftOver.length);
1795
+ bytes = merged;
1796
+ this.leftOver = new Uint8Array(0);
1797
+ }
1798
+ const len = bytes.length;
1799
+ if (len === 0) return "";
1800
+ const parts = [];
1801
+ let i = 0;
1802
+ const replacement = "\uFFFD";
1803
+ const isContinuationByte = (b) => (b & 192) === 128;
1804
+ while (i < len) {
1805
+ const byte1 = bytes[i];
1806
+ if (byte1 < 128) {
1807
+ parts.push(String.fromCharCode(byte1));
1808
+ i += 1;
1809
+ } else if (byte1 >= 194 && byte1 < 224) {
1810
+ if (i + 1 >= len) {
1811
+ if (stream) {
1812
+ this.leftOver = bytes.slice(i);
1813
+ break;
1814
+ }
1815
+ parts.push(replacement);
1816
+ break;
1817
+ }
1818
+ const byte2 = bytes[i + 1];
1819
+ if (!isContinuationByte(byte2)) {
1820
+ parts.push(replacement);
1821
+ i += 1;
1822
+ continue;
1823
+ }
1824
+ parts.push(String.fromCharCode((byte1 & 31) << 6 | byte2 & 63));
1825
+ i += 2;
1826
+ } else if (byte1 >= 224 && byte1 < 240) {
1827
+ if (i + 2 >= len) {
1828
+ if (stream) {
1829
+ this.leftOver = bytes.slice(i);
1830
+ break;
1831
+ }
1832
+ parts.push(replacement);
1833
+ break;
1834
+ }
1835
+ const byte2 = bytes[i + 1];
1836
+ const byte3 = bytes[i + 2];
1837
+ if (!isContinuationByte(byte2) || !isContinuationByte(byte3)) {
1838
+ parts.push(replacement);
1839
+ i += 1;
1840
+ continue;
1841
+ }
1842
+ if (byte1 === 224 && byte2 < 160) {
1843
+ parts.push(replacement);
1844
+ i += 3;
1845
+ continue;
1846
+ }
1847
+ if (byte1 === 237 && byte2 >= 160) {
1848
+ parts.push(replacement);
1849
+ i += 3;
1850
+ continue;
1851
+ }
1852
+ const codeUnit = (byte1 & 15) << 12 | (byte2 & 63) << 6 | byte3 & 63;
1853
+ parts.push(String.fromCharCode(codeUnit));
1854
+ i += 3;
1855
+ } else if (byte1 >= 240 && byte1 <= 244) {
1856
+ if (i + 3 >= len) {
1857
+ if (stream) {
1858
+ this.leftOver = bytes.slice(i);
1859
+ break;
1860
+ }
1861
+ parts.push(replacement);
1862
+ break;
1863
+ }
1864
+ const byte2 = bytes[i + 1];
1865
+ const byte3 = bytes[i + 2];
1866
+ const byte4 = bytes[i + 3];
1867
+ if (!isContinuationByte(byte2) || !isContinuationByte(byte3) || !isContinuationByte(byte4)) {
1868
+ parts.push(replacement);
1869
+ i += 1;
1870
+ continue;
1871
+ }
1872
+ if (byte1 === 240 && byte2 < 144) {
1873
+ parts.push(replacement);
1874
+ i += 4;
1875
+ continue;
1876
+ }
1877
+ if (byte1 === 244 && byte2 >= 144) {
1878
+ parts.push(replacement);
1879
+ i += 4;
1880
+ continue;
1881
+ }
1882
+ const codepoint = (byte1 & 7) << 18 | (byte2 & 63) << 12 | (byte3 & 63) << 6 | byte4 & 63;
1883
+ const offset = codepoint - 65536;
1884
+ parts.push(String.fromCharCode(55296 + (offset >> 10), 56320 + (offset & 1023)));
1885
+ i += 4;
1886
+ } else {
1887
+ parts.push(replacement);
1888
+ i += 1;
1889
+ }
1890
+ }
1891
+ return parts.join("");
1892
+ }
1893
+ };
1894
+ var PolyfillTextDecoder_default = PolyfillTextDecoder;
1895
+
1896
+ // src/ts/buffer/SSEParser.ts
1897
+ var SSEParser = class {
1898
+ constructor(onMessage) {
1899
+ __publicField(this, "buffer", "");
1900
+ __publicField(this, "onMessage");
1901
+ __publicField(this, "decoder");
1902
+ __publicField(this, "eventDataLines", []);
1903
+ __publicField(this, "eventType");
1904
+ __publicField(this, "eventId");
1905
+ __publicField(this, "eventRetry");
1906
+ this.onMessage = onMessage;
1907
+ this.decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf-8") : new PolyfillTextDecoder_default();
1908
+ }
1909
+ /**
1910
+ * 接收流式数据
1911
+ * @param buffer ArrayBuffer
1912
+ */
1913
+ receive(buffer) {
1914
+ const text = this.decoder.decode(new Uint8Array(buffer), { stream: true });
1915
+ this.appendText(text);
1916
+ }
1917
+ /**
1918
+ * 刷新解码器残留数据并处理尾部未换行的内容
1919
+ */
1920
+ flush() {
1921
+ const tail = this.decoder.decode(void 0, { stream: false });
1922
+ if (tail) this.appendText(tail);
1923
+ this.flushRemainder();
1924
+ }
1925
+ /**
1926
+ * 追加文本并按行拆分处理,保留不完整尾行
1927
+ * @param text 新到达的文本片段
1928
+ */
1929
+ appendText(text) {
1930
+ this.buffer += text;
1931
+ const lines = this.buffer.split(/\r?\n/);
1932
+ this.buffer = lines.pop() || "";
1933
+ this.processLines(lines);
1934
+ }
1935
+ /**
1936
+ * 处理缓冲区中剩余的尾行内容
1937
+ */
1938
+ flushRemainder() {
1939
+ if (!this.buffer.trim()) {
1940
+ this.buffer = "";
1941
+ return;
1942
+ }
1943
+ const rest = this.buffer;
1944
+ this.buffer = "";
1945
+ this.processLines([rest, ""]);
1946
+ }
1947
+ /**
1948
+ * 解析每行 SSE 数据并触发回调
1949
+ * @param lines 以换行切分后的行内容
1950
+ */
1951
+ processLines(lines) {
1952
+ for (const line of lines) {
1953
+ if (!line.trim()) {
1954
+ this.dispatchEvent();
1955
+ continue;
1956
+ }
1957
+ if (line.startsWith(":")) continue;
1958
+ const colonIndex = line.indexOf(":");
1959
+ const field = colonIndex === -1 ? line : line.slice(0, colonIndex);
1960
+ let value = colonIndex === -1 ? "" : line.slice(colonIndex + 1);
1961
+ if (value.startsWith(" ")) value = value.slice(1);
1962
+ if (field === "data") {
1963
+ this.eventDataLines.push(value);
1964
+ continue;
1965
+ }
1966
+ if (field === "event") {
1967
+ this.eventType = value || void 0;
1968
+ continue;
1969
+ }
1970
+ if (field === "id") {
1971
+ this.eventId = value || void 0;
1972
+ continue;
1973
+ }
1974
+ if (field === "retry") {
1975
+ const retry = Number(value);
1976
+ this.eventRetry = Number.isFinite(retry) ? retry : void 0;
1977
+ continue;
1978
+ }
1979
+ }
1980
+ }
1981
+ /**
1982
+ * 将当前缓存的一次 SSE 事件分发给回调
1983
+ * @description 以空行作为事件边界,将多行 data 合并后再解析;处理 "[DONE]" 结束标记;分发完成后会重置事件缓存
1984
+ */
1985
+ dispatchEvent() {
1986
+ if (!this.eventDataLines.length) {
1987
+ this.resetEvent();
1988
+ return;
1989
+ }
1990
+ const data = this.eventDataLines.join("\n");
1991
+ if (!data) {
1992
+ this.resetEvent();
1993
+ return;
1994
+ }
1995
+ if (data.trim() === "[DONE]") {
1996
+ this.safeOnMessage({ type: "DONE" });
1997
+ this.resetEvent();
1998
+ return;
1999
+ }
2000
+ let msg;
2001
+ try {
2002
+ const json = JSON.parse(data);
2003
+ msg = isPlainObject(json) ? json : { data: json };
2004
+ } catch (e) {
2005
+ msg = { raw: data };
2006
+ }
2007
+ if (this.eventType && msg.event === void 0) msg.event = this.eventType;
2008
+ if (this.eventType && msg.type === void 0) msg.type = this.eventType;
2009
+ if (this.eventId && msg.id === void 0) msg.id = this.eventId;
2010
+ if (this.eventRetry !== void 0 && msg.retry === void 0) msg.retry = this.eventRetry;
2011
+ this.safeOnMessage(msg);
2012
+ this.resetEvent();
2013
+ }
2014
+ /** 安全调用 onMessage 回调,捕获并打印错误 */
2015
+ safeOnMessage(msg) {
2016
+ try {
2017
+ this.onMessage(msg);
2018
+ } catch (onMessageError) {
2019
+ console.error("SSEParser onMessage error:", onMessageError);
2020
+ }
2021
+ }
2022
+ /** 重置当前 SSE 事件的临时缓存 */
2023
+ resetEvent() {
2024
+ this.eventDataLines = [];
2025
+ this.eventType = void 0;
2026
+ this.eventId = void 0;
2027
+ this.eventRetry = void 0;
2028
+ }
2029
+ };
2030
+
1774
2031
  // src/web/network/request.ts
1775
2032
  var requestCache = /* @__PURE__ */ new Map();
1776
2033
  function request(config) {
@@ -1792,18 +2049,16 @@ var baseToolsWeb = (() => {
1792
2049
  resMap,
1793
2050
  responseType = "json",
1794
2051
  timeout = 6e4,
1795
- onTaskReady
2052
+ onTaskReady,
2053
+ onMessage
1796
2054
  } = config;
1797
2055
  const controller = new AbortController();
1798
2056
  const signal = controller.signal;
1799
- let chunkCallback = null;
2057
+ const sseTask = { parser: onMessage ? new SSEParser(onMessage) : void 0 };
1800
2058
  const task = {
1801
- abort: () => controller.abort(),
1802
- onChunkReceived: (cb) => {
1803
- chunkCallback = cb;
1804
- },
1805
- offChunkReceived: () => {
1806
- chunkCallback = null;
2059
+ abort: () => {
2060
+ sseTask.parser = null;
2061
+ controller.abort();
1807
2062
  }
1808
2063
  };
1809
2064
  onTaskReady == null ? void 0 : onTaskReady(task);
@@ -1875,7 +2130,7 @@ var baseToolsWeb = (() => {
1875
2130
  }
1876
2131
  if (enableChunked) {
1877
2132
  if (showLoading) (_c = appConfig2.hideLoading) == null ? void 0 : _c.call(appConfig2);
1878
- const res2 = yield handleStreamResponse(response, chunkCallback);
2133
+ const res2 = yield handleStreamResponse(response, sseTask);
1879
2134
  logRequestInfo({ status: "success", config: logConfig, startTime, res: res2 });
1880
2135
  resolve(res2);
1881
2136
  return;
@@ -1976,17 +2231,25 @@ var baseToolsWeb = (() => {
1976
2231
  }
1977
2232
  return cached.res;
1978
2233
  }
1979
- function handleStreamResponse(response, chunkCallback) {
2234
+ function handleStreamResponse(response, sseTask) {
1980
2235
  return __async(this, null, function* () {
1981
2236
  if (!response.body) throw new Error("Response body is null");
2237
+ if (sseTask.parser === void 0) {
2238
+ throw new Error(
2239
+ "Stream parser missing: Please set config.onMessage when enableChunked is true"
2240
+ );
2241
+ }
1982
2242
  const reader = response.body.getReader();
1983
2243
  while (true) {
1984
2244
  const { done, value } = yield reader.read();
1985
- if (done) break;
1986
- if (chunkCallback && value) {
1987
- chunkCallback({ data: value.buffer });
2245
+ if (sseTask.parser === null) {
2246
+ yield reader.cancel();
2247
+ throw new DOMException("BodyStreamBuffer was aborted", "AbortError");
1988
2248
  }
2249
+ if (done) break;
2250
+ if (sseTask.parser && value) sseTask.parser.receive(value.buffer);
1989
2251
  }
2252
+ if (sseTask.parser) sseTask.parser.flush();
1990
2253
  return "Stream Finished";
1991
2254
  });
1992
2255
  }