@liveblocks/node 3.23.0-file2 → 3.23.0-file4

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/index.js CHANGED
@@ -3,7 +3,7 @@ import { detectDupes } from "@liveblocks/core";
3
3
 
4
4
  // src/version.ts
5
5
  var PKG_NAME = "@liveblocks/node";
6
- var PKG_VERSION = "3.23.0-file2";
6
+ var PKG_VERSION = "3.23.0-file4";
7
7
  var PKG_FORMAT = "esm";
8
8
 
9
9
  // src/client.ts
@@ -326,10 +326,7 @@ async function uploadStorageFile({
326
326
  if (signal?.aborted) {
327
327
  throw abortError;
328
328
  }
329
- if (err instanceof LiveblocksError && err.status === 413) {
330
- throw err;
331
- }
332
- return false;
329
+ return err instanceof LiveblocksError && err.status >= 400 && err.status < 500;
333
330
  };
334
331
  if (file.size <= STORAGE_FILE_PART_SIZE) {
335
332
  return autoRetry(
@@ -347,6 +344,17 @@ async function uploadStorageFile({
347
344
  STORAGE_FILE_RETRY_DELAYS,
348
345
  handleRetryError
349
346
  );
347
+ const partUploadController = new AbortController();
348
+ const partUploadSignal = partUploadController.signal;
349
+ const abortPartUploads = (reason) => {
350
+ partUploadController.abort(reason);
351
+ };
352
+ const handleExternalAbort = () => abortPartUploads();
353
+ if (signal?.aborted) {
354
+ handleExternalAbort();
355
+ } else {
356
+ signal?.addEventListener("abort", handleExternalAbort, { once: true });
357
+ }
350
358
  try {
351
359
  uploadId = multipartUpload.uploadId;
352
360
  if (signal?.aborted) {
@@ -354,34 +362,66 @@ async function uploadStorageFile({
354
362
  }
355
363
  const batches = chunk(splitStorageFileIntoParts(file), 5);
356
364
  for (const parts of batches) {
357
- const uploadedPartPromises = [];
365
+ const firstPartUploadFailure = {};
366
+ const partUploads$ = [];
358
367
  for (const { part, partNumber } of parts) {
359
- uploadedPartPromises.push(
368
+ partUploads$.push(
360
369
  autoRetry(
361
- () => uploadMultipartPart(multipartUpload.uploadId, partNumber, part),
370
+ () => uploadMultipartPart(
371
+ multipartUpload.uploadId,
372
+ partNumber,
373
+ part,
374
+ partUploadSignal
375
+ ),
362
376
  STORAGE_FILE_RETRY_ATTEMPTS,
363
377
  STORAGE_FILE_RETRY_DELAYS,
364
- handleRetryError
365
- )
378
+ (error) => {
379
+ if (signal?.aborted) {
380
+ throw abortError;
381
+ }
382
+ return partUploadSignal.aborted || handleRetryError(error);
383
+ }
384
+ ).catch((error) => {
385
+ if (firstPartUploadFailure.value === void 0) {
386
+ firstPartUploadFailure.value = { error };
387
+ abortPartUploads(error);
388
+ }
389
+ throw error;
390
+ })
366
391
  );
367
392
  }
368
- uploadedParts.push(...await Promise.all(uploadedPartPromises));
393
+ const settledPartUploads = await Promise.allSettled(partUploads$);
394
+ if (firstPartUploadFailure.value !== void 0) {
395
+ throw firstPartUploadFailure.value.error;
396
+ }
397
+ for (const settledPartUpload of settledPartUploads) {
398
+ if (settledPartUpload.status === "fulfilled") {
399
+ uploadedParts.push(settledPartUpload.value);
400
+ }
401
+ }
369
402
  }
370
403
  if (signal?.aborted) {
371
404
  throw abortError;
372
405
  }
373
- return completeMultipartUpload(
374
- multipartUpload.uploadId,
375
- uploadedParts.sort((a, b) => a.partNumber - b.partNumber)
406
+ const sortedParts = uploadedParts.sort(
407
+ (a, b) => a.partNumber - b.partNumber
408
+ );
409
+ return autoRetry(
410
+ () => completeMultipartUpload(multipartUpload.uploadId, sortedParts),
411
+ STORAGE_FILE_RETRY_ATTEMPTS,
412
+ STORAGE_FILE_RETRY_DELAYS,
413
+ handleRetryError
376
414
  );
377
415
  } catch (err) {
378
- if (uploadId && isAbortOrTimeoutError(err)) {
416
+ if (uploadId) {
379
417
  try {
380
418
  await abortMultipartUpload(uploadId);
381
419
  } catch {
382
420
  }
383
421
  }
384
422
  throw err;
423
+ } finally {
424
+ signal?.removeEventListener("abort", handleExternalAbort);
385
425
  }
386
426
  }
387
427
  function splitStorageFileIntoParts(file) {
@@ -397,9 +437,6 @@ function splitStorageFileIntoParts(file) {
397
437
  }
398
438
  return parts;
399
439
  }
400
- function isAbortOrTimeoutError(err) {
401
- return err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError");
402
- }
403
440
  function createAbortError(message) {
404
441
  if (typeof DOMException === "function") {
405
442
  return new DOMException(message, "AbortError");
@@ -1424,12 +1461,12 @@ var Liveblocks = class {
1424
1461
  );
1425
1462
  return await this.#readJsonResponse(res);
1426
1463
  },
1427
- uploadMultipartPart: async (uploadId, partNumber, part) => {
1464
+ uploadMultipartPart: async (uploadId, partNumber, part, signal) => {
1428
1465
  const res = await this.#putBlob(
1429
1466
  url2`/v2/rooms/${roomId}/storage/files/${fileId}/multipart/${uploadId}/${String(partNumber)}`,
1430
1467
  part,
1431
1468
  void 0,
1432
- options
1469
+ { signal }
1433
1470
  );
1434
1471
  return await this.#readJsonResponse(res);
1435
1472
  },
@@ -3286,10 +3323,10 @@ function isCustomNotificationEvent(event) {
3286
3323
  import {
3287
3324
  getMentionsFromCommentBody,
3288
3325
  isNotificationChannelEnabled,
3326
+ LiveFile as LiveFile2,
3289
3327
  LiveList,
3290
3328
  LiveMap,
3291
3329
  LiveObject as LiveObject2,
3292
- LiveFile as LiveFile2,
3293
3330
  stringifyCommentBody
3294
3331
  } from "@liveblocks/core";
3295
3332
  detectDupes(PKG_NAME, PKG_VERSION, PKG_FORMAT);