@automattic/vip 4.0.6 → 4.0.8

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.
@@ -43,6 +43,45 @@ function parseEtagHeader(etag) {
43
43
  }
44
44
  return normalizedEtag.replace(/^"(.*)"$/u, '$1');
45
45
  }
46
+ const isStreamBody = body => typeof body?.pipe === 'function';
47
+ function createProgressTransform(onChunk) {
48
+ return new _stream.Transform({
49
+ transform(chunk, _encoding, callback) {
50
+ onChunk(chunk);
51
+ callback(null, chunk);
52
+ }
53
+ });
54
+ }
55
+ function omitUnsupportedFetchHeaders(init) {
56
+ if (!init.headers) {
57
+ return init;
58
+ }
59
+ const headers = new _undici.Headers(init.headers);
60
+ headers.delete('expect');
61
+ return {
62
+ ...init,
63
+ headers
64
+ };
65
+ }
66
+ function withCauseMessage(err) {
67
+ if (!(err instanceof Error)) {
68
+ return err;
69
+ }
70
+ const cause = err.cause;
71
+ let causeMessage;
72
+ if (cause instanceof Error) {
73
+ causeMessage = cause.message;
74
+ } else if (typeof cause === 'string') {
75
+ causeMessage = cause;
76
+ }
77
+ if (!causeMessage || err.message.includes(causeMessage)) {
78
+ return err;
79
+ }
80
+ return new Error(`${err.message}: ${causeMessage}`, {
81
+ cause: err
82
+ });
83
+ }
84
+
46
85
  /**
47
86
  * Wraps `fetch` with exponential-backoff retries.
48
87
  *
@@ -58,20 +97,25 @@ function parseEtagHeader(etag) {
58
97
  * once so the underlying error surfaces instead of the misleading undici one.
59
98
  */
60
99
  async function fetchWithRetry(input, init = {}, retries = 3, createBody) {
61
- const bodyIsStream = typeof init.body?.pipe === 'function';
100
+ const bodyIsStream = isStreamBody(init.body);
62
101
  // Only retry when we can hand `fetch` a fresh, replayable body each attempt.
63
102
  const maxAttempts = createBody || !bodyIsStream ? retries : 0;
64
103
  for (let attempt = 0; attempt <= maxAttempts; attempt++) {
65
104
  const requestInit = createBody ? {
66
105
  ...init,
67
106
  body: createBody()
68
- } : init;
107
+ } : {
108
+ ...init
109
+ };
110
+ if (isStreamBody(requestInit.body) && !requestInit.duplex) {
111
+ requestInit.duplex = 'half';
112
+ }
69
113
  try {
70
114
  // eslint-disable-next-line no-await-in-loop
71
- return await (0, _undici.fetch)(input, requestInit);
115
+ return await (0, _undici.fetch)(input, omitUnsupportedFetchHeaders(requestInit));
72
116
  } catch (err) {
73
117
  if (attempt === maxAttempts) {
74
- throw err;
118
+ throw withCauseMessage(err);
75
119
  }
76
120
  // eslint-disable-next-line no-await-in-loop
77
121
  await (0, _promises3.setTimeout)(Math.pow(2, attempt) * 1000); // 1000, 2000, 4000
@@ -253,8 +297,7 @@ async function uploadUsingPutObject({
253
297
  return fileContent;
254
298
  }
255
299
  let readBytes = 0;
256
- const progressPassThrough = new _stream.PassThrough();
257
- progressPassThrough.on('data', data => {
300
+ const progressTransform = createProgressTransform(data => {
258
301
  readBytes += data.length;
259
302
  const percentage = `${Math.floor(100 * readBytes / fileSize)}%`;
260
303
  debug(percentage);
@@ -262,7 +305,7 @@ async function uploadUsingPutObject({
262
305
  progressCallback(percentage);
263
306
  }
264
307
  });
265
- return (0, _fs.createReadStream)(fileName).pipe(progressPassThrough);
308
+ return (0, _fs.createReadStream)(fileName).pipe(progressTransform);
266
309
  };
267
310
  const response = await fetchWithRetry(presignedRequest.url, fetchOptions, 3, createBody);
268
311
  if (response.status === 200) {
@@ -500,15 +543,14 @@ async function uploadParts({
500
543
  const createBody = () => {
501
544
  partBytesRead[index] = 0;
502
545
  partPercentages[index] = 0;
503
- const progressPassThrough = new _stream.PassThrough();
504
- progressPassThrough.on('data', data => {
546
+ const progressTransform = createProgressTransform(data => {
505
547
  partBytesRead[index] += data.length;
506
548
  partPercentages[index] = Math.floor(100 * partBytesRead[index] / partSize);
507
549
  });
508
550
  return (0, _fs.createReadStream)(fileMeta.fileName, {
509
551
  start,
510
552
  end
511
- }).pipe(progressPassThrough);
553
+ }).pipe(progressTransform);
512
554
  };
513
555
  await readyForPartUpload();
514
556
  const uploadResult = await uploadPart({
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "4.0.6",
3
+ "version": "4.0.8",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@automattic/vip",
9
- "version": "4.0.6",
9
+ "version": "4.0.8",
10
10
  "hasInstallScript": true,
11
11
  "license": "MIT",
12
12
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/vip",
3
- "version": "4.0.6",
3
+ "version": "4.0.8",
4
4
  "description": "The VIP Javascript library & CLI",
5
5
  "main": "index.js",
6
6
  "bin": {