@aws-sdk/lib-storage 3.186.0 → 3.188.0
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/CHANGELOG.md +8 -0
- package/dist-es/Upload.js +229 -328
- package/dist-es/bytelength.js +1 -1
- package/dist-es/chunker.js +1 -1
- package/dist-es/chunks/getChunkBuffer.js +18 -36
- package/dist-es/chunks/getChunkStream.js +22 -66
- package/dist-es/chunks/getDataReadable.js +4 -42
- package/dist-es/chunks/getDataReadableStream.js +16 -36
- package/dist-es/runtimeConfig.browser.js +4 -2
- package/dist-es/runtimeConfig.js +5 -2
- package/dist-es/runtimeConfig.native.js +4 -2
- package/dist-es/runtimeConfig.shared.js +2 -2
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [3.188.0](https://github.com/aws/aws-sdk-js-v3/compare/v3.187.0...v3.188.0) (2022-10-13)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @aws-sdk/lib-storage
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
# [3.186.0](https://github.com/aws/aws-sdk-js-v3/compare/v3.185.0...v3.186.0) (2022-10-06)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @aws-sdk/lib-storage
|
package/dist-es/Upload.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { __assign, __asyncValues, __awaiter, __extends, __generator } from "tslib";
|
|
2
1
|
import { AbortController } from "@aws-sdk/abort-controller";
|
|
3
2
|
import { CompleteMultipartUploadCommand, CreateMultipartUploadCommand, PutObjectCommand, PutObjectTaggingCommand, UploadPartCommand, } from "@aws-sdk/client-s3";
|
|
4
3
|
import { getEndpointFromInstructions, toEndpointV1, } from "@aws-sdk/middleware-endpoint";
|
|
@@ -6,350 +5,252 @@ import { extendedEncodeURIComponent } from "@aws-sdk/smithy-client";
|
|
|
6
5
|
import { EventEmitter } from "events";
|
|
7
6
|
import { byteLength } from "./bytelength";
|
|
8
7
|
import { getChunk } from "./chunker";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
_this.totalBytes = byteLength(_this.params.Body);
|
|
32
|
-
_this.bytesUploadedSoFar = 0;
|
|
33
|
-
_this.abortController = (_a = options.abortController) !== null && _a !== void 0 ? _a : new AbortController();
|
|
34
|
-
return _this;
|
|
8
|
+
const MIN_PART_SIZE = 1024 * 1024 * 5;
|
|
9
|
+
export class Upload extends EventEmitter {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
super();
|
|
12
|
+
this.MAX_PARTS = 10000;
|
|
13
|
+
this.queueSize = 4;
|
|
14
|
+
this.partSize = MIN_PART_SIZE;
|
|
15
|
+
this.leavePartsOnError = false;
|
|
16
|
+
this.tags = [];
|
|
17
|
+
this.concurrentUploaders = [];
|
|
18
|
+
this.uploadedParts = [];
|
|
19
|
+
this.isMultiPart = true;
|
|
20
|
+
this.queueSize = options.queueSize || this.queueSize;
|
|
21
|
+
this.partSize = options.partSize || this.partSize;
|
|
22
|
+
this.leavePartsOnError = options.leavePartsOnError || this.leavePartsOnError;
|
|
23
|
+
this.tags = options.tags || this.tags;
|
|
24
|
+
this.client = options.client;
|
|
25
|
+
this.params = options.params;
|
|
26
|
+
this.__validateInput();
|
|
27
|
+
this.totalBytes = byteLength(this.params.Body);
|
|
28
|
+
this.bytesUploadedSoFar = 0;
|
|
29
|
+
this.abortController = options.abortController ?? new AbortController();
|
|
35
30
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
async abort() {
|
|
32
|
+
this.abortController.abort();
|
|
33
|
+
}
|
|
34
|
+
async done() {
|
|
35
|
+
return await Promise.race([this.__doMultipartUpload(), this.__abortTimeout(this.abortController.signal)]);
|
|
36
|
+
}
|
|
37
|
+
on(event, listener) {
|
|
38
|
+
this.uploadEvent = event;
|
|
39
|
+
return super.on(event, listener);
|
|
40
|
+
}
|
|
41
|
+
async __uploadUsingPut(dataPart) {
|
|
42
|
+
this.isMultiPart = false;
|
|
43
|
+
const params = { ...this.params, Body: dataPart.data };
|
|
44
|
+
const clientConfig = this.client.config;
|
|
45
|
+
const requestHandler = clientConfig.requestHandler;
|
|
46
|
+
const eventEmitter = requestHandler instanceof EventEmitter ? requestHandler : null;
|
|
47
|
+
const uploadEventListener = (event) => {
|
|
48
|
+
this.bytesUploadedSoFar = event.loaded;
|
|
49
|
+
this.totalBytes = event.total;
|
|
50
|
+
this.__notifyProgress({
|
|
51
|
+
loaded: this.bytesUploadedSoFar,
|
|
52
|
+
total: this.totalBytes,
|
|
53
|
+
part: dataPart.partNumber,
|
|
54
|
+
Key: this.params.Key,
|
|
55
|
+
Bucket: this.params.Bucket,
|
|
41
56
|
});
|
|
57
|
+
};
|
|
58
|
+
if (eventEmitter !== null) {
|
|
59
|
+
eventEmitter.on("xhr.upload.progress", uploadEventListener);
|
|
60
|
+
}
|
|
61
|
+
const resolved = await Promise.all([this.client.send(new PutObjectCommand(params)), clientConfig?.endpoint?.()]);
|
|
62
|
+
const putResult = resolved[0];
|
|
63
|
+
let endpoint = resolved[1];
|
|
64
|
+
if (!endpoint) {
|
|
65
|
+
endpoint = toEndpointV1(await getEndpointFromInstructions(params, PutObjectCommand, {
|
|
66
|
+
...clientConfig,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
if (!endpoint) {
|
|
70
|
+
throw new Error('Could not resolve endpoint from S3 "client.config.endpoint()" nor EndpointsV2.');
|
|
71
|
+
}
|
|
72
|
+
if (eventEmitter !== null) {
|
|
73
|
+
eventEmitter.off("xhr.upload.progress", uploadEventListener);
|
|
74
|
+
}
|
|
75
|
+
const locationKey = this.params
|
|
76
|
+
.Key.split("/")
|
|
77
|
+
.map((segment) => extendedEncodeURIComponent(segment))
|
|
78
|
+
.join("/");
|
|
79
|
+
const locationBucket = extendedEncodeURIComponent(this.params.Bucket);
|
|
80
|
+
const Location = this.client.config.forcePathStyle
|
|
81
|
+
? `${endpoint.protocol}//${endpoint.hostname}/${locationBucket}/${locationKey}`
|
|
82
|
+
: `${endpoint.protocol}//${locationBucket}.${endpoint.hostname}/${locationKey}`;
|
|
83
|
+
this.singleUploadResult = {
|
|
84
|
+
...putResult,
|
|
85
|
+
Bucket: this.params.Bucket,
|
|
86
|
+
Key: this.params.Key,
|
|
87
|
+
Location,
|
|
88
|
+
};
|
|
89
|
+
const totalSize = byteLength(dataPart.data);
|
|
90
|
+
this.__notifyProgress({
|
|
91
|
+
loaded: totalSize,
|
|
92
|
+
total: totalSize,
|
|
93
|
+
part: 1,
|
|
94
|
+
Key: this.params.Key,
|
|
95
|
+
Bucket: this.params.Bucket,
|
|
42
96
|
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
97
|
+
}
|
|
98
|
+
async __createMultipartUpload() {
|
|
99
|
+
if (!this.createMultiPartPromise) {
|
|
100
|
+
const createCommandParams = { ...this.params, Body: undefined };
|
|
101
|
+
this.createMultiPartPromise = this.client.send(new CreateMultipartUploadCommand(createCommandParams));
|
|
102
|
+
}
|
|
103
|
+
const createMultipartUploadResult = await this.createMultiPartPromise;
|
|
104
|
+
this.uploadId = createMultipartUploadResult.UploadId;
|
|
105
|
+
}
|
|
106
|
+
async __doConcurrentUpload(dataFeeder) {
|
|
107
|
+
for await (const dataPart of dataFeeder) {
|
|
108
|
+
if (this.uploadedParts.length > this.MAX_PARTS) {
|
|
109
|
+
throw new Error(`Exceeded ${this.MAX_PARTS} as part of the upload to ${this.params.Key} and ${this.params.Bucket}.`);
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
if (this.abortController.signal.aborted) {
|
|
113
|
+
return;
|
|
50
114
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
};
|
|
54
|
-
Upload.prototype.on = function (event, listener) {
|
|
55
|
-
this.uploadEvent = event;
|
|
56
|
-
return _super.prototype.on.call(this, event, listener);
|
|
57
|
-
};
|
|
58
|
-
Upload.prototype.__uploadUsingPut = function (dataPart) {
|
|
59
|
-
var _a;
|
|
60
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
61
|
-
var params, clientConfig, requestHandler, eventEmitter, uploadEventListener, resolved, putResult, endpoint, _b, locationKey, locationBucket, Location, totalSize;
|
|
62
|
-
var _this = this;
|
|
63
|
-
return __generator(this, function (_c) {
|
|
64
|
-
switch (_c.label) {
|
|
65
|
-
case 0:
|
|
66
|
-
this.isMultiPart = false;
|
|
67
|
-
params = __assign(__assign({}, this.params), { Body: dataPart.data });
|
|
68
|
-
clientConfig = this.client.config;
|
|
69
|
-
requestHandler = clientConfig.requestHandler;
|
|
70
|
-
eventEmitter = requestHandler instanceof EventEmitter ? requestHandler : null;
|
|
71
|
-
uploadEventListener = function (event) {
|
|
72
|
-
_this.bytesUploadedSoFar = event.loaded;
|
|
73
|
-
_this.totalBytes = event.total;
|
|
74
|
-
_this.__notifyProgress({
|
|
75
|
-
loaded: _this.bytesUploadedSoFar,
|
|
76
|
-
total: _this.totalBytes,
|
|
77
|
-
part: dataPart.partNumber,
|
|
78
|
-
Key: _this.params.Key,
|
|
79
|
-
Bucket: _this.params.Bucket,
|
|
80
|
-
});
|
|
81
|
-
};
|
|
82
|
-
if (eventEmitter !== null) {
|
|
83
|
-
eventEmitter.on("xhr.upload.progress", uploadEventListener);
|
|
84
|
-
}
|
|
85
|
-
return [4, Promise.all([this.client.send(new PutObjectCommand(params)), (_a = clientConfig === null || clientConfig === void 0 ? void 0 : clientConfig.endpoint) === null || _a === void 0 ? void 0 : _a.call(clientConfig)])];
|
|
86
|
-
case 1:
|
|
87
|
-
resolved = _c.sent();
|
|
88
|
-
putResult = resolved[0];
|
|
89
|
-
endpoint = resolved[1];
|
|
90
|
-
if (!!endpoint) return [3, 3];
|
|
91
|
-
_b = toEndpointV1;
|
|
92
|
-
return [4, getEndpointFromInstructions(params, PutObjectCommand, __assign({}, clientConfig))];
|
|
93
|
-
case 2:
|
|
94
|
-
endpoint = _b.apply(void 0, [_c.sent()]);
|
|
95
|
-
_c.label = 3;
|
|
96
|
-
case 3:
|
|
97
|
-
if (!endpoint) {
|
|
98
|
-
throw new Error('Could not resolve endpoint from S3 "client.config.endpoint()" nor EndpointsV2.');
|
|
99
|
-
}
|
|
100
|
-
if (eventEmitter !== null) {
|
|
101
|
-
eventEmitter.off("xhr.upload.progress", uploadEventListener);
|
|
102
|
-
}
|
|
103
|
-
locationKey = this.params
|
|
104
|
-
.Key.split("/")
|
|
105
|
-
.map(function (segment) { return extendedEncodeURIComponent(segment); })
|
|
106
|
-
.join("/");
|
|
107
|
-
locationBucket = extendedEncodeURIComponent(this.params.Bucket);
|
|
108
|
-
Location = this.client.config.forcePathStyle
|
|
109
|
-
? "".concat(endpoint.protocol, "//").concat(endpoint.hostname, "/").concat(locationBucket, "/").concat(locationKey)
|
|
110
|
-
: "".concat(endpoint.protocol, "//").concat(locationBucket, ".").concat(endpoint.hostname, "/").concat(locationKey);
|
|
111
|
-
this.singleUploadResult = __assign(__assign({}, putResult), { Bucket: this.params.Bucket, Key: this.params.Key, Location: Location });
|
|
112
|
-
totalSize = byteLength(dataPart.data);
|
|
113
|
-
this.__notifyProgress({
|
|
114
|
-
loaded: totalSize,
|
|
115
|
-
total: totalSize,
|
|
116
|
-
part: 1,
|
|
117
|
-
Key: this.params.Key,
|
|
118
|
-
Bucket: this.params.Bucket,
|
|
119
|
-
});
|
|
120
|
-
return [2];
|
|
115
|
+
if (dataPart.partNumber === 1 && dataPart.lastPart) {
|
|
116
|
+
return await this.__uploadUsingPut(dataPart);
|
|
121
117
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
var createCommandParams, createMultipartUploadResult;
|
|
128
|
-
return __generator(this, function (_a) {
|
|
129
|
-
switch (_a.label) {
|
|
130
|
-
case 0:
|
|
131
|
-
if (!this.createMultiPartPromise) {
|
|
132
|
-
createCommandParams = __assign(__assign({}, this.params), { Body: undefined });
|
|
133
|
-
this.createMultiPartPromise = this.client.send(new CreateMultipartUploadCommand(createCommandParams));
|
|
134
|
-
}
|
|
135
|
-
return [4, this.createMultiPartPromise];
|
|
136
|
-
case 1:
|
|
137
|
-
createMultipartUploadResult = _a.sent();
|
|
138
|
-
this.uploadId = createMultipartUploadResult.UploadId;
|
|
139
|
-
return [2];
|
|
118
|
+
if (!this.uploadId) {
|
|
119
|
+
await this.__createMultipartUpload();
|
|
120
|
+
if (this.abortController.signal.aborted) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
140
123
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
case 1:
|
|
165
|
-
_d.trys.push([1, 7, , 8]);
|
|
166
|
-
if (this_1.abortController.signal.aborted) {
|
|
167
|
-
return [2, { value: void 0 }];
|
|
168
|
-
}
|
|
169
|
-
if (!(dataPart.partNumber === 1 && dataPart.lastPart)) return [3, 3];
|
|
170
|
-
_c = {};
|
|
171
|
-
return [4, this_1.__uploadUsingPut(dataPart)];
|
|
172
|
-
case 2: return [2, (_c.value = _d.sent(), _c)];
|
|
173
|
-
case 3:
|
|
174
|
-
if (!!this_1.uploadId) return [3, 5];
|
|
175
|
-
return [4, this_1.__createMultipartUpload()];
|
|
176
|
-
case 4:
|
|
177
|
-
_d.sent();
|
|
178
|
-
if (this_1.abortController.signal.aborted) {
|
|
179
|
-
return [2, { value: void 0 }];
|
|
180
|
-
}
|
|
181
|
-
_d.label = 5;
|
|
182
|
-
case 5:
|
|
183
|
-
partSize_1 = byteLength(dataPart.data) || 0;
|
|
184
|
-
requestHandler = this_1.client.config.requestHandler;
|
|
185
|
-
eventEmitter = requestHandler instanceof EventEmitter ? requestHandler : null;
|
|
186
|
-
lastSeenBytes_1 = 0;
|
|
187
|
-
uploadEventListener = function (event, request) {
|
|
188
|
-
var requestPartSize = Number(request.query["partNumber"]) || -1;
|
|
189
|
-
if (requestPartSize !== dataPart.partNumber) {
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
if (event.total && partSize_1) {
|
|
193
|
-
_this.bytesUploadedSoFar += event.loaded - lastSeenBytes_1;
|
|
194
|
-
lastSeenBytes_1 = event.loaded;
|
|
195
|
-
}
|
|
196
|
-
_this.__notifyProgress({
|
|
197
|
-
loaded: _this.bytesUploadedSoFar,
|
|
198
|
-
total: _this.totalBytes,
|
|
199
|
-
part: dataPart.partNumber,
|
|
200
|
-
Key: _this.params.Key,
|
|
201
|
-
Bucket: _this.params.Bucket,
|
|
202
|
-
});
|
|
203
|
-
};
|
|
204
|
-
if (eventEmitter !== null) {
|
|
205
|
-
eventEmitter.on("xhr.upload.progress", uploadEventListener);
|
|
206
|
-
}
|
|
207
|
-
return [4, this_1.client.send(new UploadPartCommand(__assign(__assign({}, this_1.params), { UploadId: this_1.uploadId, Body: dataPart.data, PartNumber: dataPart.partNumber })))];
|
|
208
|
-
case 6:
|
|
209
|
-
partResult = _d.sent();
|
|
210
|
-
if (eventEmitter !== null) {
|
|
211
|
-
eventEmitter.off("xhr.upload.progress", uploadEventListener);
|
|
212
|
-
}
|
|
213
|
-
if (this_1.abortController.signal.aborted) {
|
|
214
|
-
return [2, { value: void 0 }];
|
|
215
|
-
}
|
|
216
|
-
if (!partResult.ETag) {
|
|
217
|
-
throw new Error("Part ".concat(dataPart.partNumber, " is missing ETag in UploadPart response. Missing Bucket CORS configuration for ETag header?"));
|
|
218
|
-
}
|
|
219
|
-
this_1.uploadedParts.push(__assign(__assign(__assign(__assign({ PartNumber: dataPart.partNumber, ETag: partResult.ETag }, (partResult.ChecksumCRC32 && { ChecksumCRC32: partResult.ChecksumCRC32 })), (partResult.ChecksumCRC32C && { ChecksumCRC32C: partResult.ChecksumCRC32C })), (partResult.ChecksumSHA1 && { ChecksumSHA1: partResult.ChecksumSHA1 })), (partResult.ChecksumSHA256 && { ChecksumSHA256: partResult.ChecksumSHA256 })));
|
|
220
|
-
if (eventEmitter === null) {
|
|
221
|
-
this_1.bytesUploadedSoFar += partSize_1;
|
|
222
|
-
}
|
|
223
|
-
this_1.__notifyProgress({
|
|
224
|
-
loaded: this_1.bytesUploadedSoFar,
|
|
225
|
-
total: this_1.totalBytes,
|
|
226
|
-
part: dataPart.partNumber,
|
|
227
|
-
Key: this_1.params.Key,
|
|
228
|
-
Bucket: this_1.params.Bucket,
|
|
229
|
-
});
|
|
230
|
-
return [3, 8];
|
|
231
|
-
case 7:
|
|
232
|
-
e_2 = _d.sent();
|
|
233
|
-
if (!this_1.uploadId) {
|
|
234
|
-
throw e_2;
|
|
235
|
-
}
|
|
236
|
-
if (this_1.leavePartsOnError) {
|
|
237
|
-
throw e_2;
|
|
238
|
-
}
|
|
239
|
-
return [3, 8];
|
|
240
|
-
case 8: return [2];
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
};
|
|
244
|
-
this_1 = this;
|
|
245
|
-
dataFeeder_1 = __asyncValues(dataFeeder);
|
|
246
|
-
_b.label = 1;
|
|
247
|
-
case 1: return [4, dataFeeder_1.next()];
|
|
248
|
-
case 2:
|
|
249
|
-
if (!(dataFeeder_1_1 = _b.sent(), !dataFeeder_1_1.done)) return [3, 5];
|
|
250
|
-
return [5, _loop_1()];
|
|
251
|
-
case 3:
|
|
252
|
-
state_1 = _b.sent();
|
|
253
|
-
if (typeof state_1 === "object")
|
|
254
|
-
return [2, state_1.value];
|
|
255
|
-
_b.label = 4;
|
|
256
|
-
case 4: return [3, 1];
|
|
257
|
-
case 5: return [3, 12];
|
|
258
|
-
case 6:
|
|
259
|
-
e_1_1 = _b.sent();
|
|
260
|
-
e_1 = { error: e_1_1 };
|
|
261
|
-
return [3, 12];
|
|
262
|
-
case 7:
|
|
263
|
-
_b.trys.push([7, , 10, 11]);
|
|
264
|
-
if (!(dataFeeder_1_1 && !dataFeeder_1_1.done && (_a = dataFeeder_1.return))) return [3, 9];
|
|
265
|
-
return [4, _a.call(dataFeeder_1)];
|
|
266
|
-
case 8:
|
|
267
|
-
_b.sent();
|
|
268
|
-
_b.label = 9;
|
|
269
|
-
case 9: return [3, 11];
|
|
270
|
-
case 10:
|
|
271
|
-
if (e_1) throw e_1.error;
|
|
272
|
-
return [7];
|
|
273
|
-
case 11: return [7];
|
|
274
|
-
case 12: return [2];
|
|
124
|
+
const partSize = byteLength(dataPart.data) || 0;
|
|
125
|
+
const requestHandler = this.client.config.requestHandler;
|
|
126
|
+
const eventEmitter = requestHandler instanceof EventEmitter ? requestHandler : null;
|
|
127
|
+
let lastSeenBytes = 0;
|
|
128
|
+
const uploadEventListener = (event, request) => {
|
|
129
|
+
const requestPartSize = Number(request.query["partNumber"]) || -1;
|
|
130
|
+
if (requestPartSize !== dataPart.partNumber) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (event.total && partSize) {
|
|
134
|
+
this.bytesUploadedSoFar += event.loaded - lastSeenBytes;
|
|
135
|
+
lastSeenBytes = event.loaded;
|
|
136
|
+
}
|
|
137
|
+
this.__notifyProgress({
|
|
138
|
+
loaded: this.bytesUploadedSoFar,
|
|
139
|
+
total: this.totalBytes,
|
|
140
|
+
part: dataPart.partNumber,
|
|
141
|
+
Key: this.params.Key,
|
|
142
|
+
Bucket: this.params.Bucket,
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
if (eventEmitter !== null) {
|
|
146
|
+
eventEmitter.on("xhr.upload.progress", uploadEventListener);
|
|
275
147
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
case 0:
|
|
285
|
-
dataFeeder = getChunk(this.params.Body, this.partSize);
|
|
286
|
-
for (index = 0; index < this.queueSize; index++) {
|
|
287
|
-
currentUpload = this.__doConcurrentUpload(dataFeeder);
|
|
288
|
-
this.concurrentUploaders.push(currentUpload);
|
|
289
|
-
}
|
|
290
|
-
return [4, Promise.all(this.concurrentUploaders)];
|
|
291
|
-
case 1:
|
|
292
|
-
_a.sent();
|
|
293
|
-
if (this.abortController.signal.aborted) {
|
|
294
|
-
throw Object.assign(new Error("Upload aborted."), { name: "AbortError" });
|
|
295
|
-
}
|
|
296
|
-
if (!this.isMultiPart) return [3, 3];
|
|
297
|
-
this.uploadedParts.sort(function (a, b) { return a.PartNumber - b.PartNumber; });
|
|
298
|
-
uploadCompleteParams = __assign(__assign({}, this.params), { Body: undefined, UploadId: this.uploadId, MultipartUpload: {
|
|
299
|
-
Parts: this.uploadedParts,
|
|
300
|
-
} });
|
|
301
|
-
return [4, this.client.send(new CompleteMultipartUploadCommand(uploadCompleteParams))];
|
|
302
|
-
case 2:
|
|
303
|
-
result = _a.sent();
|
|
304
|
-
return [3, 4];
|
|
305
|
-
case 3:
|
|
306
|
-
result = this.singleUploadResult;
|
|
307
|
-
_a.label = 4;
|
|
308
|
-
case 4:
|
|
309
|
-
if (!this.tags.length) return [3, 6];
|
|
310
|
-
return [4, this.client.send(new PutObjectTaggingCommand(__assign(__assign({}, this.params), { Tagging: {
|
|
311
|
-
TagSet: this.tags,
|
|
312
|
-
} })))];
|
|
313
|
-
case 5:
|
|
314
|
-
_a.sent();
|
|
315
|
-
_a.label = 6;
|
|
316
|
-
case 6: return [2, result];
|
|
148
|
+
const partResult = await this.client.send(new UploadPartCommand({
|
|
149
|
+
...this.params,
|
|
150
|
+
UploadId: this.uploadId,
|
|
151
|
+
Body: dataPart.data,
|
|
152
|
+
PartNumber: dataPart.partNumber,
|
|
153
|
+
}));
|
|
154
|
+
if (eventEmitter !== null) {
|
|
155
|
+
eventEmitter.off("xhr.upload.progress", uploadEventListener);
|
|
317
156
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
157
|
+
if (this.abortController.signal.aborted) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (!partResult.ETag) {
|
|
161
|
+
throw new Error(`Part ${dataPart.partNumber} is missing ETag in UploadPart response. Missing Bucket CORS configuration for ETag header?`);
|
|
162
|
+
}
|
|
163
|
+
this.uploadedParts.push({
|
|
164
|
+
PartNumber: dataPart.partNumber,
|
|
165
|
+
ETag: partResult.ETag,
|
|
166
|
+
...(partResult.ChecksumCRC32 && { ChecksumCRC32: partResult.ChecksumCRC32 }),
|
|
167
|
+
...(partResult.ChecksumCRC32C && { ChecksumCRC32C: partResult.ChecksumCRC32C }),
|
|
168
|
+
...(partResult.ChecksumSHA1 && { ChecksumSHA1: partResult.ChecksumSHA1 }),
|
|
169
|
+
...(partResult.ChecksumSHA256 && { ChecksumSHA256: partResult.ChecksumSHA256 }),
|
|
170
|
+
});
|
|
171
|
+
if (eventEmitter === null) {
|
|
172
|
+
this.bytesUploadedSoFar += partSize;
|
|
173
|
+
}
|
|
174
|
+
this.__notifyProgress({
|
|
175
|
+
loaded: this.bytesUploadedSoFar,
|
|
176
|
+
total: this.totalBytes,
|
|
177
|
+
part: dataPart.partNumber,
|
|
178
|
+
Key: this.params.Key,
|
|
179
|
+
Bucket: this.params.Bucket,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
catch (e) {
|
|
183
|
+
if (!this.uploadId) {
|
|
184
|
+
throw e;
|
|
185
|
+
}
|
|
186
|
+
if (this.leavePartsOnError) {
|
|
187
|
+
throw e;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async __doMultipartUpload() {
|
|
193
|
+
const dataFeeder = getChunk(this.params.Body, this.partSize);
|
|
194
|
+
for (let index = 0; index < this.queueSize; index++) {
|
|
195
|
+
const currentUpload = this.__doConcurrentUpload(dataFeeder);
|
|
196
|
+
this.concurrentUploaders.push(currentUpload);
|
|
197
|
+
}
|
|
198
|
+
await Promise.all(this.concurrentUploaders);
|
|
199
|
+
if (this.abortController.signal.aborted) {
|
|
200
|
+
throw Object.assign(new Error("Upload aborted."), { name: "AbortError" });
|
|
201
|
+
}
|
|
202
|
+
let result;
|
|
203
|
+
if (this.isMultiPart) {
|
|
204
|
+
this.uploadedParts.sort((a, b) => a.PartNumber - b.PartNumber);
|
|
205
|
+
const uploadCompleteParams = {
|
|
206
|
+
...this.params,
|
|
207
|
+
Body: undefined,
|
|
208
|
+
UploadId: this.uploadId,
|
|
209
|
+
MultipartUpload: {
|
|
210
|
+
Parts: this.uploadedParts,
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
result = await this.client.send(new CompleteMultipartUploadCommand(uploadCompleteParams));
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
result = this.singleUploadResult;
|
|
217
|
+
}
|
|
218
|
+
if (this.tags.length) {
|
|
219
|
+
await this.client.send(new PutObjectTaggingCommand({
|
|
220
|
+
...this.params,
|
|
221
|
+
Tagging: {
|
|
222
|
+
TagSet: this.tags,
|
|
223
|
+
},
|
|
224
|
+
}));
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
__notifyProgress(progress) {
|
|
322
229
|
if (this.uploadEvent) {
|
|
323
230
|
this.emit(this.uploadEvent, progress);
|
|
324
231
|
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
return
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
reject(abortError);
|
|
334
|
-
};
|
|
335
|
-
})];
|
|
336
|
-
});
|
|
232
|
+
}
|
|
233
|
+
async __abortTimeout(abortSignal) {
|
|
234
|
+
return new Promise((resolve, reject) => {
|
|
235
|
+
abortSignal.onabort = () => {
|
|
236
|
+
const abortError = new Error("Upload aborted.");
|
|
237
|
+
abortError.name = "AbortError";
|
|
238
|
+
reject(abortError);
|
|
239
|
+
};
|
|
337
240
|
});
|
|
338
|
-
}
|
|
339
|
-
|
|
241
|
+
}
|
|
242
|
+
__validateInput() {
|
|
340
243
|
if (!this.params) {
|
|
341
|
-
throw new Error(
|
|
244
|
+
throw new Error(`InputError: Upload requires params to be passed to upload.`);
|
|
342
245
|
}
|
|
343
246
|
if (!this.client) {
|
|
344
|
-
throw new Error(
|
|
247
|
+
throw new Error(`InputError: Upload requires a AWS client to do uploads with.`);
|
|
345
248
|
}
|
|
346
249
|
if (this.partSize < MIN_PART_SIZE) {
|
|
347
|
-
throw new Error(
|
|
250
|
+
throw new Error(`EntityTooSmall: Your proposed upload partsize [${this.partSize}] is smaller than the minimum allowed size [${MIN_PART_SIZE}] (5MB)`);
|
|
348
251
|
}
|
|
349
252
|
if (this.queueSize < 1) {
|
|
350
|
-
throw new Error(
|
|
253
|
+
throw new Error(`Queue size: Must have at least one uploading queue.`);
|
|
351
254
|
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
}(EventEmitter));
|
|
355
|
-
export { Upload };
|
|
255
|
+
}
|
|
256
|
+
}
|
package/dist-es/bytelength.js
CHANGED
package/dist-es/chunker.js
CHANGED
|
@@ -4,7 +4,7 @@ import { getChunkBuffer } from "./chunks/getChunkBuffer";
|
|
|
4
4
|
import { getChunkStream } from "./chunks/getChunkStream";
|
|
5
5
|
import { getDataReadable } from "./chunks/getDataReadable";
|
|
6
6
|
import { getDataReadableStream } from "./chunks/getDataReadableStream";
|
|
7
|
-
export
|
|
7
|
+
export const getChunk = (data, partSize) => {
|
|
8
8
|
if (data instanceof Buffer) {
|
|
9
9
|
return getChunkBuffer(data, partSize);
|
|
10
10
|
}
|
|
@@ -1,37 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
case 3:
|
|
20
|
-
_a.sent();
|
|
21
|
-
partNumber += 1;
|
|
22
|
-
startByte = endByte;
|
|
23
|
-
endByte = startByte + partSize;
|
|
24
|
-
return [3, 1];
|
|
25
|
-
case 4: return [4, __await({
|
|
26
|
-
partNumber: partNumber,
|
|
27
|
-
data: data.slice(startByte),
|
|
28
|
-
lastPart: true,
|
|
29
|
-
})];
|
|
30
|
-
case 5: return [4, _a.sent()];
|
|
31
|
-
case 6:
|
|
32
|
-
_a.sent();
|
|
33
|
-
return [2];
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
});
|
|
1
|
+
export async function* getChunkBuffer(data, partSize) {
|
|
2
|
+
let partNumber = 1;
|
|
3
|
+
let startByte = 0;
|
|
4
|
+
let endByte = partSize;
|
|
5
|
+
while (endByte < data.byteLength) {
|
|
6
|
+
yield {
|
|
7
|
+
partNumber,
|
|
8
|
+
data: data.slice(startByte, endByte),
|
|
9
|
+
};
|
|
10
|
+
partNumber += 1;
|
|
11
|
+
startByte = endByte;
|
|
12
|
+
endByte = startByte + partSize;
|
|
13
|
+
}
|
|
14
|
+
yield {
|
|
15
|
+
partNumber,
|
|
16
|
+
data: data.slice(startByte),
|
|
17
|
+
lastPart: true,
|
|
18
|
+
};
|
|
37
19
|
}
|
|
@@ -1,68 +1,24 @@
|
|
|
1
|
-
import { __asyncGenerator, __asyncValues, __await, __generator } from "tslib";
|
|
2
1
|
import { Buffer } from "buffer";
|
|
3
|
-
export function getChunkStream(data, partSize, getNextData) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (!(currentBuffer.length >= partSize)) return [3, 7];
|
|
26
|
-
dataChunk = currentBuffer.chunks.length > 1 ? Buffer.concat(currentBuffer.chunks) : currentBuffer.chunks[0];
|
|
27
|
-
return [4, __await({
|
|
28
|
-
partNumber: partNumber,
|
|
29
|
-
data: dataChunk.slice(0, partSize),
|
|
30
|
-
})];
|
|
31
|
-
case 5: return [4, _d.sent()];
|
|
32
|
-
case 6:
|
|
33
|
-
_d.sent();
|
|
34
|
-
currentBuffer.chunks = [dataChunk.slice(partSize)];
|
|
35
|
-
currentBuffer.length = currentBuffer.chunks[0].length;
|
|
36
|
-
partNumber += 1;
|
|
37
|
-
return [3, 4];
|
|
38
|
-
case 7: return [3, 2];
|
|
39
|
-
case 8: return [3, 15];
|
|
40
|
-
case 9:
|
|
41
|
-
e_1_1 = _d.sent();
|
|
42
|
-
e_1 = { error: e_1_1 };
|
|
43
|
-
return [3, 15];
|
|
44
|
-
case 10:
|
|
45
|
-
_d.trys.push([10, , 13, 14]);
|
|
46
|
-
if (!(_b && !_b.done && (_c = _a.return))) return [3, 12];
|
|
47
|
-
return [4, __await(_c.call(_a))];
|
|
48
|
-
case 11:
|
|
49
|
-
_d.sent();
|
|
50
|
-
_d.label = 12;
|
|
51
|
-
case 12: return [3, 14];
|
|
52
|
-
case 13:
|
|
53
|
-
if (e_1) throw e_1.error;
|
|
54
|
-
return [7];
|
|
55
|
-
case 14: return [7];
|
|
56
|
-
case 15: return [4, __await({
|
|
57
|
-
partNumber: partNumber,
|
|
58
|
-
data: Buffer.concat(currentBuffer.chunks),
|
|
59
|
-
lastPart: true,
|
|
60
|
-
})];
|
|
61
|
-
case 16: return [4, _d.sent()];
|
|
62
|
-
case 17:
|
|
63
|
-
_d.sent();
|
|
64
|
-
return [2];
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
});
|
|
2
|
+
export async function* getChunkStream(data, partSize, getNextData) {
|
|
3
|
+
let partNumber = 1;
|
|
4
|
+
const currentBuffer = { chunks: [], length: 0 };
|
|
5
|
+
for await (const datum of getNextData(data)) {
|
|
6
|
+
currentBuffer.chunks.push(datum);
|
|
7
|
+
currentBuffer.length += datum.length;
|
|
8
|
+
while (currentBuffer.length >= partSize) {
|
|
9
|
+
const dataChunk = currentBuffer.chunks.length > 1 ? Buffer.concat(currentBuffer.chunks) : currentBuffer.chunks[0];
|
|
10
|
+
yield {
|
|
11
|
+
partNumber,
|
|
12
|
+
data: dataChunk.slice(0, partSize),
|
|
13
|
+
};
|
|
14
|
+
currentBuffer.chunks = [dataChunk.slice(partSize)];
|
|
15
|
+
currentBuffer.length = currentBuffer.chunks[0].length;
|
|
16
|
+
partNumber += 1;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
yield {
|
|
20
|
+
partNumber,
|
|
21
|
+
data: Buffer.concat(currentBuffer.chunks),
|
|
22
|
+
lastPart: true,
|
|
23
|
+
};
|
|
68
24
|
}
|
|
@@ -1,44 +1,6 @@
|
|
|
1
|
-
import { __asyncGenerator, __asyncValues, __await, __generator } from "tslib";
|
|
2
1
|
import { Buffer } from "buffer";
|
|
3
|
-
export function getDataReadable(data) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return __generator(this, function (_b) {
|
|
8
|
-
switch (_b.label) {
|
|
9
|
-
case 0:
|
|
10
|
-
_b.trys.push([0, 7, 8, 13]);
|
|
11
|
-
data_1 = __asyncValues(data);
|
|
12
|
-
_b.label = 1;
|
|
13
|
-
case 1: return [4, __await(data_1.next())];
|
|
14
|
-
case 2:
|
|
15
|
-
if (!(data_1_1 = _b.sent(), !data_1_1.done)) return [3, 6];
|
|
16
|
-
chunk = data_1_1.value;
|
|
17
|
-
return [4, __await(Buffer.from(chunk))];
|
|
18
|
-
case 3: return [4, _b.sent()];
|
|
19
|
-
case 4:
|
|
20
|
-
_b.sent();
|
|
21
|
-
_b.label = 5;
|
|
22
|
-
case 5: return [3, 1];
|
|
23
|
-
case 6: return [3, 13];
|
|
24
|
-
case 7:
|
|
25
|
-
e_1_1 = _b.sent();
|
|
26
|
-
e_1 = { error: e_1_1 };
|
|
27
|
-
return [3, 13];
|
|
28
|
-
case 8:
|
|
29
|
-
_b.trys.push([8, , 11, 12]);
|
|
30
|
-
if (!(data_1_1 && !data_1_1.done && (_a = data_1.return))) return [3, 10];
|
|
31
|
-
return [4, __await(_a.call(data_1))];
|
|
32
|
-
case 9:
|
|
33
|
-
_b.sent();
|
|
34
|
-
_b.label = 10;
|
|
35
|
-
case 10: return [3, 12];
|
|
36
|
-
case 11:
|
|
37
|
-
if (e_1) throw e_1.error;
|
|
38
|
-
return [7];
|
|
39
|
-
case 12: return [7];
|
|
40
|
-
case 13: return [2];
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
});
|
|
2
|
+
export async function* getDataReadable(data) {
|
|
3
|
+
for await (const chunk of data) {
|
|
4
|
+
yield Buffer.from(chunk);
|
|
5
|
+
}
|
|
44
6
|
}
|
|
@@ -1,38 +1,18 @@
|
|
|
1
|
-
import { __asyncGenerator, __await, __generator } from "tslib";
|
|
2
1
|
import { Buffer } from "buffer";
|
|
3
|
-
export function getDataReadableStream(data) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (!done) return [3, 5];
|
|
20
|
-
return [4, __await(void 0)];
|
|
21
|
-
case 4: return [2, _b.sent()];
|
|
22
|
-
case 5: return [4, __await(Buffer.from(value))];
|
|
23
|
-
case 6: return [4, _b.sent()];
|
|
24
|
-
case 7:
|
|
25
|
-
_b.sent();
|
|
26
|
-
return [3, 2];
|
|
27
|
-
case 8: return [3, 11];
|
|
28
|
-
case 9:
|
|
29
|
-
e_1 = _b.sent();
|
|
30
|
-
throw e_1;
|
|
31
|
-
case 10:
|
|
32
|
-
reader.releaseLock();
|
|
33
|
-
return [7];
|
|
34
|
-
case 11: return [2];
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
});
|
|
2
|
+
export async function* getDataReadableStream(data) {
|
|
3
|
+
const reader = data.getReader();
|
|
4
|
+
try {
|
|
5
|
+
while (true) {
|
|
6
|
+
const { done, value } = await reader.read();
|
|
7
|
+
if (done)
|
|
8
|
+
return;
|
|
9
|
+
yield Buffer.from(value);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
throw e;
|
|
14
|
+
}
|
|
15
|
+
finally {
|
|
16
|
+
reader.releaseLock();
|
|
17
|
+
}
|
|
38
18
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import { __assign } from "tslib";
|
|
2
1
|
import { ClientSharedValues } from "./runtimeConfig.shared";
|
|
3
|
-
export
|
|
2
|
+
export const ClientDefaultValues = {
|
|
3
|
+
...ClientSharedValues,
|
|
4
|
+
runtime: "browser",
|
|
5
|
+
};
|
package/dist-es/runtimeConfig.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import { __assign } from "tslib";
|
|
2
1
|
import { lstatSync } from "fs";
|
|
3
2
|
import { ClientSharedValues } from "./runtimeConfig.shared";
|
|
4
|
-
export
|
|
3
|
+
export const ClientDefaultValues = {
|
|
4
|
+
...ClientSharedValues,
|
|
5
|
+
runtime: "node",
|
|
6
|
+
lstatSync,
|
|
7
|
+
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import { __assign } from "tslib";
|
|
2
1
|
import { ClientDefaultValues as BrowserDefaults } from "./runtimeConfig.browser";
|
|
3
|
-
export
|
|
2
|
+
export const ClientDefaultValues = {
|
|
3
|
+
...BrowserDefaults,
|
|
4
|
+
runtime: "react-native",
|
|
5
|
+
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
lstatSync:
|
|
1
|
+
export const ClientSharedValues = {
|
|
2
|
+
lstatSync: () => { },
|
|
3
3
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws-sdk/lib-storage",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.188.0",
|
|
4
4
|
"description": "Storage higher order operation",
|
|
5
5
|
"main": "./dist-cjs/index.js",
|
|
6
6
|
"module": "./dist-es/index.js",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
},
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@aws-sdk/middleware-endpoint": "3.
|
|
28
|
-
"@aws-sdk/smithy-client": "3.
|
|
27
|
+
"@aws-sdk/middleware-endpoint": "3.188.0",
|
|
28
|
+
"@aws-sdk/smithy-client": "3.188.0",
|
|
29
29
|
"buffer": "5.6.0",
|
|
30
30
|
"events": "3.3.0",
|
|
31
31
|
"stream-browserify": "3.0.0",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"@aws-sdk/client-s3": "^3.0.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@aws-sdk/abort-controller": "3.
|
|
40
|
-
"@aws-sdk/client-s3": "3.
|
|
41
|
-
"@aws-sdk/types": "3.
|
|
39
|
+
"@aws-sdk/abort-controller": "3.188.0",
|
|
40
|
+
"@aws-sdk/client-s3": "3.188.0",
|
|
41
|
+
"@aws-sdk/types": "3.188.0",
|
|
42
42
|
"@tsconfig/recommended": "1.0.1",
|
|
43
43
|
"@types/node": "^14.11.2",
|
|
44
44
|
"concurrently": "7.0.0",
|