@alibarbar/common 1.1.2 → 1.1.4

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/upload.cjs CHANGED
@@ -46,6 +46,8 @@ var ChunkUploader = class {
46
46
  this.uploadedChunks = /* @__PURE__ */ new Set();
47
47
  this.status = "pending" /* PENDING */;
48
48
  this.abortController = null;
49
+ /** 进度流专用 AbortController,用于在上传结束/取消时关闭流 */
50
+ this.progressStreamAbortController = null;
49
51
  this.file = file;
50
52
  this.options = {
51
53
  chunkSize: options.chunkSize || 2 * 1024 * 1024,
@@ -153,7 +155,6 @@ var ChunkUploader = class {
153
155
  });
154
156
  if (response.code === 200 && response.data.success) {
155
157
  this.uploadedChunks.add(chunkInfo.index);
156
- await this.updateProgress();
157
158
  } else {
158
159
  throw new Error(response.message || "\u5206\u7247\u4E0A\u4F20\u5931\u8D25");
159
160
  }
@@ -188,23 +189,60 @@ var ChunkUploader = class {
188
189
  await Promise.all(tasks);
189
190
  }
190
191
  /**
191
- * 更新上传进度(仅用于回调前端显示)
192
+ * 启动进度流式接口(单次请求,通过 ReadableStream 消费多条 SSE 事件)
192
193
  */
193
- async updateProgress() {
194
+ startProgressStream() {
194
195
  if (!this.taskId) return;
195
- try {
196
- const response = await this.request(
197
- `/api/files/common/progress/${this.taskId}`,
198
- {
199
- method: "GET",
200
- headers: this.options.headers
196
+ this.progressStreamAbortController = new AbortController();
197
+ const url = `${this.options.baseURL}/api/files/common/progress/${this.taskId}`;
198
+ fetch(url, {
199
+ method: "GET",
200
+ headers: {
201
+ Accept: "text/event-stream",
202
+ ...this.options.headers
203
+ },
204
+ signal: this.progressStreamAbortController.signal
205
+ }).then(async (response) => {
206
+ if (!response.ok || !response.body) return;
207
+ const reader = response.body.getReader();
208
+ const decoder = new TextDecoder();
209
+ let buffer = "";
210
+ try {
211
+ while (true) {
212
+ const { done, value } = await reader.read();
213
+ if (done) break;
214
+ buffer += decoder.decode(value, { stream: true });
215
+ const lines = buffer.split("\n");
216
+ buffer = lines.pop() ?? "";
217
+ for (const line of lines) {
218
+ if (line.startsWith("data: ")) {
219
+ const jsonStr = line.slice(6).trim();
220
+ if (!jsonStr) continue;
221
+ try {
222
+ const apiRes = JSON.parse(jsonStr);
223
+ if (apiRes.code === 200 && apiRes.data) {
224
+ this.options.onProgress(apiRes.data);
225
+ }
226
+ } catch {
227
+ }
228
+ }
229
+ }
201
230
  }
202
- );
203
- if (response.code === 200 && response.data) {
204
- this.options.onProgress(response.data);
231
+ } finally {
232
+ reader.releaseLock();
205
233
  }
206
- } catch (error) {
207
- console.warn("\u83B7\u53D6\u4E0A\u4F20\u8FDB\u5EA6\u5931\u8D25:", error);
234
+ }).catch((error) => {
235
+ if (error?.name === "AbortError") return;
236
+ console.warn("\u8FDB\u5EA6\u6D41\u5F0F\u63A5\u53E3\u5F02\u5E38:", error);
237
+ });
238
+ }
239
+ /**
240
+ * 关闭进度流
241
+ */
242
+ closeProgressStream() {
243
+ if (this.progressStreamAbortController) {
244
+ this.progressStreamAbortController.abort();
245
+ this.progressStreamAbortController = null;
208
246
  }
209
247
  }
210
248
  /**
@@ -277,6 +315,7 @@ var ChunkUploader = class {
277
315
  this.options.onComplete(result);
278
316
  return result;
279
317
  }
318
+ this.startProgressStream();
280
319
  console.log("[\u4E0A\u4F20\u6D41\u7A0B] 2. \u51C6\u5907\u5206\u7247");
281
320
  this.prepareChunks();
282
321
  const totalChunks = this.chunks.length;
@@ -320,6 +359,8 @@ var ChunkUploader = class {
320
359
  this.options.onError(err);
321
360
  console.error("[\u4E0A\u4F20\u6D41\u7A0B] \u274C \u4E0A\u4F20\u5931\u8D25:", err);
322
361
  throw err;
362
+ } finally {
363
+ this.closeProgressStream();
323
364
  }
324
365
  }
325
366
  /**
@@ -346,6 +387,7 @@ var ChunkUploader = class {
346
387
  * 取消上传
347
388
  */
348
389
  async cancel() {
390
+ this.closeProgressStream();
349
391
  if (this.taskId && this.status === "uploading" /* UPLOADING */) {
350
392
  try {
351
393
  await this.request(`/api/files/common/cancel/${this.taskId}`, {
package/dist/upload.d.mts CHANGED
@@ -1 +1 @@
1
- export { C as ChunkUploader, c as createUploader, u as uploadFile } from './index-DchqyDBQ.mjs';
1
+ export { C as ChunkUploader, c as createUploader, u as uploadFile } from './index-j5EqxJaC.mjs';
package/dist/upload.d.ts CHANGED
@@ -1 +1 @@
1
- export { C as ChunkUploader, c as createUploader, u as uploadFile } from './index-DchqyDBQ.js';
1
+ export { C as ChunkUploader, c as createUploader, u as uploadFile } from './index-j5EqxJaC.js';
package/dist/upload.js CHANGED
@@ -44,6 +44,8 @@ var ChunkUploader = class {
44
44
  this.uploadedChunks = /* @__PURE__ */ new Set();
45
45
  this.status = "pending" /* PENDING */;
46
46
  this.abortController = null;
47
+ /** 进度流专用 AbortController,用于在上传结束/取消时关闭流 */
48
+ this.progressStreamAbortController = null;
47
49
  this.file = file;
48
50
  this.options = {
49
51
  chunkSize: options.chunkSize || 2 * 1024 * 1024,
@@ -151,7 +153,6 @@ var ChunkUploader = class {
151
153
  });
152
154
  if (response.code === 200 && response.data.success) {
153
155
  this.uploadedChunks.add(chunkInfo.index);
154
- await this.updateProgress();
155
156
  } else {
156
157
  throw new Error(response.message || "\u5206\u7247\u4E0A\u4F20\u5931\u8D25");
157
158
  }
@@ -186,23 +187,60 @@ var ChunkUploader = class {
186
187
  await Promise.all(tasks);
187
188
  }
188
189
  /**
189
- * 更新上传进度(仅用于回调前端显示)
190
+ * 启动进度流式接口(单次请求,通过 ReadableStream 消费多条 SSE 事件)
190
191
  */
191
- async updateProgress() {
192
+ startProgressStream() {
192
193
  if (!this.taskId) return;
193
- try {
194
- const response = await this.request(
195
- `/api/files/common/progress/${this.taskId}`,
196
- {
197
- method: "GET",
198
- headers: this.options.headers
194
+ this.progressStreamAbortController = new AbortController();
195
+ const url = `${this.options.baseURL}/api/files/common/progress/${this.taskId}`;
196
+ fetch(url, {
197
+ method: "GET",
198
+ headers: {
199
+ Accept: "text/event-stream",
200
+ ...this.options.headers
201
+ },
202
+ signal: this.progressStreamAbortController.signal
203
+ }).then(async (response) => {
204
+ if (!response.ok || !response.body) return;
205
+ const reader = response.body.getReader();
206
+ const decoder = new TextDecoder();
207
+ let buffer = "";
208
+ try {
209
+ while (true) {
210
+ const { done, value } = await reader.read();
211
+ if (done) break;
212
+ buffer += decoder.decode(value, { stream: true });
213
+ const lines = buffer.split("\n");
214
+ buffer = lines.pop() ?? "";
215
+ for (const line of lines) {
216
+ if (line.startsWith("data: ")) {
217
+ const jsonStr = line.slice(6).trim();
218
+ if (!jsonStr) continue;
219
+ try {
220
+ const apiRes = JSON.parse(jsonStr);
221
+ if (apiRes.code === 200 && apiRes.data) {
222
+ this.options.onProgress(apiRes.data);
223
+ }
224
+ } catch {
225
+ }
226
+ }
227
+ }
199
228
  }
200
- );
201
- if (response.code === 200 && response.data) {
202
- this.options.onProgress(response.data);
229
+ } finally {
230
+ reader.releaseLock();
203
231
  }
204
- } catch (error) {
205
- console.warn("\u83B7\u53D6\u4E0A\u4F20\u8FDB\u5EA6\u5931\u8D25:", error);
232
+ }).catch((error) => {
233
+ if (error?.name === "AbortError") return;
234
+ console.warn("\u8FDB\u5EA6\u6D41\u5F0F\u63A5\u53E3\u5F02\u5E38:", error);
235
+ });
236
+ }
237
+ /**
238
+ * 关闭进度流
239
+ */
240
+ closeProgressStream() {
241
+ if (this.progressStreamAbortController) {
242
+ this.progressStreamAbortController.abort();
243
+ this.progressStreamAbortController = null;
206
244
  }
207
245
  }
208
246
  /**
@@ -275,6 +313,7 @@ var ChunkUploader = class {
275
313
  this.options.onComplete(result);
276
314
  return result;
277
315
  }
316
+ this.startProgressStream();
278
317
  console.log("[\u4E0A\u4F20\u6D41\u7A0B] 2. \u51C6\u5907\u5206\u7247");
279
318
  this.prepareChunks();
280
319
  const totalChunks = this.chunks.length;
@@ -318,6 +357,8 @@ var ChunkUploader = class {
318
357
  this.options.onError(err);
319
358
  console.error("[\u4E0A\u4F20\u6D41\u7A0B] \u274C \u4E0A\u4F20\u5931\u8D25:", err);
320
359
  throw err;
360
+ } finally {
361
+ this.closeProgressStream();
321
362
  }
322
363
  }
323
364
  /**
@@ -344,6 +385,7 @@ var ChunkUploader = class {
344
385
  * 取消上传
345
386
  */
346
387
  async cancel() {
388
+ this.closeProgressStream();
347
389
  if (this.taskId && this.status === "uploading" /* UPLOADING */) {
348
390
  try {
349
391
  await this.request(`/api/files/common/cancel/${this.taskId}`, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alibarbar/common",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "Alibarbar 通用工具库",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -66,6 +66,11 @@
66
66
  "import": "./dist/crypto.js",
67
67
  "require": "./dist/crypto.cjs"
68
68
  },
69
+ "./helper/encryption": {
70
+ "types": "./dist/crypto.d.ts",
71
+ "import": "./dist/crypto.js",
72
+ "require": "./dist/crypto.cjs"
73
+ },
69
74
  "./network": {
70
75
  "types": "./dist/network.d.ts",
71
76
  "import": "./dist/network.js",
@@ -170,6 +175,7 @@
170
175
  "eslint-plugin-prettier": "^5.1.3",
171
176
  "husky": "^9.0.11",
172
177
  "jest": "^29.7.0",
178
+ "jest-environment-jsdom": "^30.2.0",
173
179
  "prettier": "^3.2.4",
174
180
  "qs": "^6.11.2",
175
181
  "ts-jest": "^29.1.2",
@@ -178,8 +184,10 @@
178
184
  },
179
185
  "peerDependencies": {
180
186
  "axios": "^1.7.0",
187
+ "jsencrypt": "^3.5.4",
181
188
  "qs": "^6.11.2"
182
189
  },
183
- "dependencies": {}
190
+ "dependencies": {
191
+ "jsencrypt": "^3.3.2"
192
+ }
184
193
  }
185
-