@aws-amplify/storage 5.4.1 → 5.5.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/lib/Storage.d.ts +4 -1
- package/lib/Storage.js +32 -17
- package/lib/Storage.js.map +1 -1
- package/lib/providers/AWSS3Provider.d.ts +10 -1
- package/lib/providers/AWSS3Provider.js +81 -12
- package/lib/providers/AWSS3Provider.js.map +1 -1
- package/lib/types/AWSS3Provider.d.ts +13 -1
- package/lib/types/Provider.d.ts +5 -1
- package/lib/types/Storage.d.ts +10 -4
- package/lib-esm/Storage.d.ts +4 -1
- package/lib-esm/Storage.js +32 -17
- package/lib-esm/Storage.js.map +1 -1
- package/lib-esm/providers/AWSS3Provider.d.ts +10 -1
- package/lib-esm/providers/AWSS3Provider.js +81 -12
- package/lib-esm/providers/AWSS3Provider.js.map +1 -1
- package/lib-esm/types/AWSS3Provider.d.ts +13 -1
- package/lib-esm/types/Provider.d.ts +5 -1
- package/lib-esm/types/Storage.d.ts +10 -4
- package/package.json +2 -2
- package/src/Storage.ts +43 -17
- package/src/providers/AWSS3Provider.ts +84 -0
- package/src/types/AWSS3Provider.ts +15 -0
- package/src/types/Provider.ts +19 -2
- package/src/types/Storage.ts +38 -5
package/src/Storage.ts
CHANGED
|
@@ -23,6 +23,8 @@ import {
|
|
|
23
23
|
StorageListOutput,
|
|
24
24
|
StorageCopyOutput,
|
|
25
25
|
UploadTask,
|
|
26
|
+
StorageGetPropertiesConfig,
|
|
27
|
+
StorageGetPropertiesOutput,
|
|
26
28
|
} from './types';
|
|
27
29
|
import axios, { CancelTokenSource } from 'axios';
|
|
28
30
|
import { PutObjectCommandInput } from '@aws-sdk/client-s3';
|
|
@@ -246,22 +248,22 @@ export class Storage {
|
|
|
246
248
|
config?: StorageCopyConfig<T>
|
|
247
249
|
): StorageCopyOutput<T> {
|
|
248
250
|
const provider = config?.provider || DEFAULT_PROVIDER;
|
|
249
|
-
const
|
|
251
|
+
const plugin = this._pluggables.find(
|
|
250
252
|
pluggable => pluggable.getProviderName() === provider
|
|
251
253
|
);
|
|
252
|
-
if (
|
|
254
|
+
if (plugin === undefined) {
|
|
253
255
|
logger.debug('No plugin found with providerName', provider);
|
|
254
256
|
return Promise.reject(
|
|
255
257
|
'No plugin found in Storage for the provider'
|
|
256
258
|
) as StorageCopyOutput<T>;
|
|
257
259
|
}
|
|
258
260
|
const cancelTokenSource = this.getCancellableTokenSource();
|
|
259
|
-
if (typeof
|
|
261
|
+
if (typeof plugin.copy !== 'function') {
|
|
260
262
|
return Promise.reject(
|
|
261
|
-
`.copy is not implemented on provider ${
|
|
263
|
+
`.copy is not implemented on provider ${plugin.getProviderName()}`
|
|
262
264
|
) as StorageCopyOutput<T>;
|
|
263
265
|
}
|
|
264
|
-
const responsePromise =
|
|
266
|
+
const responsePromise = plugin.copy(src, dest, {
|
|
265
267
|
...config,
|
|
266
268
|
cancelTokenSource,
|
|
267
269
|
});
|
|
@@ -285,17 +287,17 @@ export class Storage {
|
|
|
285
287
|
T extends StorageProvider | { [key: string]: any; download?: boolean }
|
|
286
288
|
>(key: string, config?: StorageGetConfig<T>): StorageGetOutput<T> {
|
|
287
289
|
const provider = config?.provider || DEFAULT_PROVIDER;
|
|
288
|
-
const
|
|
290
|
+
const plugin = this._pluggables.find(
|
|
289
291
|
pluggable => pluggable.getProviderName() === provider
|
|
290
292
|
);
|
|
291
|
-
if (
|
|
293
|
+
if (plugin === undefined) {
|
|
292
294
|
logger.debug('No plugin found with providerName', provider);
|
|
293
295
|
return Promise.reject(
|
|
294
296
|
'No plugin found in Storage for the provider'
|
|
295
297
|
) as StorageGetOutput<T>;
|
|
296
298
|
}
|
|
297
299
|
const cancelTokenSource = this.getCancellableTokenSource();
|
|
298
|
-
const responsePromise =
|
|
300
|
+
const responsePromise = plugin.get(key, {
|
|
299
301
|
...config,
|
|
300
302
|
cancelTokenSource,
|
|
301
303
|
});
|
|
@@ -307,6 +309,30 @@ export class Storage {
|
|
|
307
309
|
return axios.isCancel(error);
|
|
308
310
|
}
|
|
309
311
|
|
|
312
|
+
public getProperties<T extends StorageProvider | { [key: string]: any }>(
|
|
313
|
+
key: string,
|
|
314
|
+
config?: StorageGetPropertiesConfig<T>
|
|
315
|
+
): StorageGetPropertiesOutput<T> {
|
|
316
|
+
const provider = config?.provider || DEFAULT_PROVIDER;
|
|
317
|
+
const plugin = this._pluggables.find(
|
|
318
|
+
pluggable => pluggable.getProviderName() === provider
|
|
319
|
+
);
|
|
320
|
+
if (plugin === undefined) {
|
|
321
|
+
logger.debug('No plugin found with providerName', provider);
|
|
322
|
+
throw new Error('No plugin found with providerName');
|
|
323
|
+
}
|
|
324
|
+
const cancelTokenSource = this.getCancellableTokenSource();
|
|
325
|
+
if (typeof plugin.getProperties !== 'function') {
|
|
326
|
+
return Promise.reject(
|
|
327
|
+
`.getProperties is not implemented on provider ${plugin.getProviderName()}`
|
|
328
|
+
) as StorageGetPropertiesOutput<T>;
|
|
329
|
+
}
|
|
330
|
+
const responsePromise = plugin?.getProperties(key, {
|
|
331
|
+
...config,
|
|
332
|
+
});
|
|
333
|
+
this.updateRequestToBeCancellable(responsePromise, cancelTokenSource);
|
|
334
|
+
return responsePromise as StorageGetPropertiesOutput<T>;
|
|
335
|
+
}
|
|
310
336
|
/**
|
|
311
337
|
* Put a file in storage bucket specified to configure method
|
|
312
338
|
* @param key - key of the object
|
|
@@ -326,17 +352,17 @@ export class Storage {
|
|
|
326
352
|
config?: StoragePutConfig<T>
|
|
327
353
|
): StoragePutOutput<T> {
|
|
328
354
|
const provider = config?.provider || DEFAULT_PROVIDER;
|
|
329
|
-
const
|
|
355
|
+
const plugin = this._pluggables.find(
|
|
330
356
|
pluggable => pluggable.getProviderName() === provider
|
|
331
357
|
);
|
|
332
|
-
if (
|
|
358
|
+
if (plugin === undefined) {
|
|
333
359
|
logger.debug('No plugin found with providerName', provider);
|
|
334
360
|
return Promise.reject(
|
|
335
361
|
'No plugin found in Storage for the provider'
|
|
336
362
|
) as StoragePutOutput<T>;
|
|
337
363
|
}
|
|
338
364
|
const cancelTokenSource = this.getCancellableTokenSource();
|
|
339
|
-
const response =
|
|
365
|
+
const response = plugin.put(key, object, {
|
|
340
366
|
...config,
|
|
341
367
|
cancelTokenSource,
|
|
342
368
|
});
|
|
@@ -361,16 +387,16 @@ export class Storage {
|
|
|
361
387
|
config?: StorageRemoveConfig<T>
|
|
362
388
|
): StorageRemoveOutput<T> {
|
|
363
389
|
const provider = config?.provider || DEFAULT_PROVIDER;
|
|
364
|
-
const
|
|
390
|
+
const plugin = this._pluggables.find(
|
|
365
391
|
pluggable => pluggable.getProviderName() === provider
|
|
366
392
|
);
|
|
367
|
-
if (
|
|
393
|
+
if (plugin === undefined) {
|
|
368
394
|
logger.debug('No plugin found with providerName', provider);
|
|
369
395
|
return Promise.reject(
|
|
370
396
|
'No plugin found in Storage for the provider'
|
|
371
397
|
) as StorageRemoveOutput<T>;
|
|
372
398
|
}
|
|
373
|
-
return
|
|
399
|
+
return plugin.remove(key, config) as StorageRemoveOutput<T>;
|
|
374
400
|
}
|
|
375
401
|
|
|
376
402
|
/**
|
|
@@ -388,16 +414,16 @@ export class Storage {
|
|
|
388
414
|
config?: StorageListConfig<T>
|
|
389
415
|
): StorageListOutput<T> {
|
|
390
416
|
const provider = config?.provider || DEFAULT_PROVIDER;
|
|
391
|
-
const
|
|
417
|
+
const plugin = this._pluggables.find(
|
|
392
418
|
pluggable => pluggable.getProviderName() === provider
|
|
393
419
|
);
|
|
394
|
-
if (
|
|
420
|
+
if (plugin === undefined) {
|
|
395
421
|
logger.debug('No plugin found with providerName', provider);
|
|
396
422
|
return Promise.reject(
|
|
397
423
|
'No plugin found in Storage for the provider'
|
|
398
424
|
) as StorageListOutput<T>;
|
|
399
425
|
}
|
|
400
|
-
return
|
|
426
|
+
return plugin.list(path, config) as StorageListOutput<T>;
|
|
401
427
|
}
|
|
402
428
|
}
|
|
403
429
|
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
GetObjectCommandInput,
|
|
22
22
|
ListObjectsV2Request,
|
|
23
23
|
HeadObjectCommand,
|
|
24
|
+
HeadObjectCommandInput,
|
|
24
25
|
} from '@aws-sdk/client-s3';
|
|
25
26
|
import { formatUrl } from '@aws-sdk/util-format-url';
|
|
26
27
|
import { createRequest } from '@aws-sdk/util-create-request';
|
|
@@ -49,6 +50,8 @@ import {
|
|
|
49
50
|
UploadTask,
|
|
50
51
|
S3ClientOptions,
|
|
51
52
|
S3ProviderListOutput,
|
|
53
|
+
S3ProviderGetPropertiesOutput,
|
|
54
|
+
S3ProviderGetPropertiesConfig,
|
|
52
55
|
} from '../types';
|
|
53
56
|
import { StorageErrorStrings } from '../common/StorageErrorStrings';
|
|
54
57
|
import { dispatchStorageEvent } from '../common/StorageUtils';
|
|
@@ -498,6 +501,87 @@ export class AWSS3Provider implements StorageProvider {
|
|
|
498
501
|
}
|
|
499
502
|
}
|
|
500
503
|
|
|
504
|
+
/**
|
|
505
|
+
* Get Properties of the object
|
|
506
|
+
*
|
|
507
|
+
* @param {string} key - key of the object
|
|
508
|
+
* @param {S3ProviderGetPropertiesConfig} [config] - Optional configuration for the underlying S3 command
|
|
509
|
+
* @return {Promise<S3ProviderGetPropertiesOutput>} - A promise resolves to contentType,
|
|
510
|
+
* contentLength, eTag, lastModified, metadata
|
|
511
|
+
*/
|
|
512
|
+
public async getProperties(
|
|
513
|
+
key: string,
|
|
514
|
+
config?: S3ProviderGetPropertiesConfig
|
|
515
|
+
): Promise<S3ProviderGetPropertiesOutput> {
|
|
516
|
+
const credentialsOK = await this._ensureCredentials();
|
|
517
|
+
if (!credentialsOK || !this._isWithCredentials(this._config)) {
|
|
518
|
+
throw new Error(StorageErrorStrings.NO_CREDENTIALS);
|
|
519
|
+
}
|
|
520
|
+
const opt = Object.assign({}, this._config, config);
|
|
521
|
+
const {
|
|
522
|
+
bucket,
|
|
523
|
+
track = false,
|
|
524
|
+
SSECustomerAlgorithm,
|
|
525
|
+
SSECustomerKey,
|
|
526
|
+
SSECustomerKeyMD5,
|
|
527
|
+
} = opt;
|
|
528
|
+
const prefix = this._prefix(opt);
|
|
529
|
+
const final_key = prefix + key;
|
|
530
|
+
const emitter = new events.EventEmitter();
|
|
531
|
+
const s3 = this._createNewS3Client(opt, emitter);
|
|
532
|
+
logger.debug(`getProperties ${key} from ${final_key}`);
|
|
533
|
+
|
|
534
|
+
const params: HeadObjectCommandInput = {
|
|
535
|
+
Bucket: bucket,
|
|
536
|
+
Key: final_key,
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
if (SSECustomerAlgorithm) {
|
|
540
|
+
params.SSECustomerAlgorithm = SSECustomerAlgorithm;
|
|
541
|
+
}
|
|
542
|
+
if (SSECustomerKey) {
|
|
543
|
+
params.SSECustomerKey = SSECustomerKey;
|
|
544
|
+
}
|
|
545
|
+
if (SSECustomerKeyMD5) {
|
|
546
|
+
params.SSECustomerKeyMD5 = SSECustomerKeyMD5;
|
|
547
|
+
}
|
|
548
|
+
// See: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-s3/classes/headobjectcommand.html
|
|
549
|
+
|
|
550
|
+
const headObjectCommand = new HeadObjectCommand(params);
|
|
551
|
+
try {
|
|
552
|
+
const response = await s3.send(headObjectCommand);
|
|
553
|
+
const getPropertiesResponse: S3ProviderGetPropertiesOutput = {
|
|
554
|
+
contentLength: response.ContentLength,
|
|
555
|
+
contentType: response.ContentType,
|
|
556
|
+
eTag: response.ETag,
|
|
557
|
+
lastModified: response.LastModified,
|
|
558
|
+
metadata: response.Metadata,
|
|
559
|
+
};
|
|
560
|
+
dispatchStorageEvent(
|
|
561
|
+
track,
|
|
562
|
+
'getProperties',
|
|
563
|
+
{ method: 'getProperties', result: 'success' },
|
|
564
|
+
null,
|
|
565
|
+
`getProperties successful for ${key}`
|
|
566
|
+
);
|
|
567
|
+
return getPropertiesResponse;
|
|
568
|
+
} catch (error) {
|
|
569
|
+
if (error.$metadata.httpStatusCode === 404) {
|
|
570
|
+
dispatchStorageEvent(
|
|
571
|
+
track,
|
|
572
|
+
'getProperties',
|
|
573
|
+
{
|
|
574
|
+
method: 'getProperties',
|
|
575
|
+
result: 'failed',
|
|
576
|
+
},
|
|
577
|
+
null,
|
|
578
|
+
`${key} not found`
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
throw error;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
501
585
|
/**
|
|
502
586
|
* Put a file in S3 bucket specified to configure method
|
|
503
587
|
* @param key - key of the object
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
CopyObjectRequest,
|
|
6
6
|
_Object,
|
|
7
7
|
DeleteObjectCommandOutput,
|
|
8
|
+
HeadObjectRequest,
|
|
8
9
|
} from '@aws-sdk/client-s3';
|
|
9
10
|
import { StorageOptions, StorageAccessLevel } from './Storage';
|
|
10
11
|
import {
|
|
@@ -51,6 +52,12 @@ export type S3ProviderGetConfig = CommonStorageOptions & {
|
|
|
51
52
|
validateObjectExistence?: boolean;
|
|
52
53
|
};
|
|
53
54
|
|
|
55
|
+
export type S3ProviderGetPropertiesConfig = CommonStorageOptions & {
|
|
56
|
+
SSECustomerAlgorithm?: HeadObjectRequest['SSECustomerAlgorithm'];
|
|
57
|
+
SSECustomerKey?: HeadObjectRequest['SSECustomerKey'];
|
|
58
|
+
SSECustomerKeyMD5?: HeadObjectRequest['SSECustomerKeyMD5'];
|
|
59
|
+
};
|
|
60
|
+
|
|
54
61
|
export type S3ProviderGetOuput<T> = T extends { download: true }
|
|
55
62
|
? GetObjectCommandOutput
|
|
56
63
|
: string;
|
|
@@ -173,6 +180,14 @@ export type S3ProviderCopyOutput = {
|
|
|
173
180
|
key: string;
|
|
174
181
|
};
|
|
175
182
|
|
|
183
|
+
export type S3ProviderGetPropertiesOutput = {
|
|
184
|
+
contentType: string;
|
|
185
|
+
contentLength: number;
|
|
186
|
+
eTag: string;
|
|
187
|
+
lastModified: Date;
|
|
188
|
+
metadata: Record<string, string>;
|
|
189
|
+
};
|
|
190
|
+
|
|
176
191
|
export type PutResult = {
|
|
177
192
|
key: string;
|
|
178
193
|
};
|
package/src/types/Provider.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
StorageCopySource,
|
|
3
|
+
StorageCopyDestination,
|
|
4
|
+
StorageCopyConfig,
|
|
5
|
+
} from './Storage';
|
|
2
6
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
7
|
// SPDX-License-Identifier: Apache-2.0
|
|
4
8
|
export interface StorageProvider {
|
|
@@ -20,6 +24,9 @@ export interface StorageProvider {
|
|
|
20
24
|
// get object/pre-signed url from storage
|
|
21
25
|
get(key: string, options?): Promise<string | Object>;
|
|
22
26
|
|
|
27
|
+
// get properties of object
|
|
28
|
+
getProperties?(key: string, options?): Promise<Object>;
|
|
29
|
+
|
|
23
30
|
// upload storage object
|
|
24
31
|
put(key: string, object, options?): Promise<Object> | UploadTask;
|
|
25
32
|
|
|
@@ -52,4 +59,14 @@ export interface StorageProviderWithCopy extends StorageProvider {
|
|
|
52
59
|
): Promise<any>;
|
|
53
60
|
}
|
|
54
61
|
|
|
55
|
-
export
|
|
62
|
+
export interface StorageProviderWithGetProperties extends StorageProvider {
|
|
63
|
+
getProperties(key: string, options?): Promise<Object>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export type StorageProviderApi =
|
|
67
|
+
| 'copy'
|
|
68
|
+
| 'get'
|
|
69
|
+
| 'put'
|
|
70
|
+
| 'remove'
|
|
71
|
+
| 'list'
|
|
72
|
+
| 'getProperties';
|
package/src/types/Storage.ts
CHANGED
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
S3ProviderListOutput,
|
|
16
16
|
S3ProviderCopyOutput,
|
|
17
17
|
S3ProviderPutOutput,
|
|
18
|
+
S3ProviderGetPropertiesOutput,
|
|
19
|
+
StorageProviderWithGetProperties,
|
|
18
20
|
} from '../';
|
|
19
21
|
|
|
20
22
|
type Tail<T extends any[]> = ((...t: T) => void) extends (
|
|
@@ -69,13 +71,26 @@ export type StorageCopyDestination = Omit<StorageCopyTarget, 'identityId'>;
|
|
|
69
71
|
* config.
|
|
70
72
|
*/
|
|
71
73
|
type StorageOperationConfig<
|
|
72
|
-
T extends
|
|
74
|
+
T extends
|
|
75
|
+
| StorageProvider
|
|
76
|
+
| StorageProviderWithCopy
|
|
77
|
+
| StorageProviderWithGetProperties,
|
|
73
78
|
U extends StorageProviderApi
|
|
74
79
|
> = ReturnType<T['getProviderName']> extends 'AWSS3'
|
|
75
80
|
? LastParameter<AWSS3Provider[U]> // check if it has 'copy' function because 'copy' is optional
|
|
81
|
+
: T extends StorageProviderWithGetProperties & StorageProviderWithCopy
|
|
82
|
+
? LastParameter<T[U]> & {
|
|
83
|
+
provider: ReturnType<T['getProviderName']>;
|
|
84
|
+
}
|
|
76
85
|
: T extends StorageProviderWithCopy
|
|
77
|
-
? LastParameter<T[U]> & {
|
|
78
|
-
|
|
86
|
+
? LastParameter<T[Exclude<U, 'getProperties'>]> & {
|
|
87
|
+
provider: ReturnType<T['getProviderName']>;
|
|
88
|
+
}
|
|
89
|
+
: T extends StorageProviderWithGetProperties
|
|
90
|
+
? LastParameter<T[Exclude<U, 'copy'>]> & {
|
|
91
|
+
provider: ReturnType<T['getProviderName']>;
|
|
92
|
+
}
|
|
93
|
+
: LastParameter<T[Exclude<U, 'copy' | 'getProperties'>]> & {
|
|
79
94
|
provider: ReturnType<T['getProviderName']>;
|
|
80
95
|
};
|
|
81
96
|
|
|
@@ -87,6 +102,14 @@ export type StorageGetConfig<T extends Record<string, any>> =
|
|
|
87
102
|
T
|
|
88
103
|
>;
|
|
89
104
|
|
|
105
|
+
export type StorageGetPropertiesConfig<T extends Record<string, any>> =
|
|
106
|
+
T extends StorageProviderWithGetProperties
|
|
107
|
+
? StorageOperationConfig<T, 'getProperties'>
|
|
108
|
+
: StorageOperationConfigMap<
|
|
109
|
+
StorageOperationConfig<AWSS3Provider, 'getProperties'>,
|
|
110
|
+
T
|
|
111
|
+
>;
|
|
112
|
+
|
|
90
113
|
export type StoragePutConfig<T extends Record<string, any>> =
|
|
91
114
|
T extends StorageProvider
|
|
92
115
|
? StorageOperationConfig<T, 'put'>
|
|
@@ -132,9 +155,13 @@ type PickProviderOutput<
|
|
|
132
155
|
> = T extends StorageProvider
|
|
133
156
|
? T['getProviderName'] extends 'AWSS3'
|
|
134
157
|
? DefaultOutput
|
|
135
|
-
: T extends StorageProviderWithCopy
|
|
158
|
+
: T extends StorageProviderWithCopy & StorageProviderWithGetProperties
|
|
136
159
|
? ReturnType<T[api]>
|
|
137
|
-
:
|
|
160
|
+
: T extends StorageProviderWithCopy
|
|
161
|
+
? ReturnType<T[Exclude<api, 'getProperties'>]>
|
|
162
|
+
: T extends StorageProviderWithGetProperties
|
|
163
|
+
? ReturnType<T[Exclude<api, 'copy'>]>
|
|
164
|
+
: ReturnType<T[Exclude<api, 'copy' | 'getProperties'>]>
|
|
138
165
|
: T extends { provider: string }
|
|
139
166
|
? T extends { provider: 'AWSS3' }
|
|
140
167
|
? DefaultOutput
|
|
@@ -168,6 +195,12 @@ export type StorageCopyOutput<T> = PickProviderOutput<
|
|
|
168
195
|
'copy'
|
|
169
196
|
>;
|
|
170
197
|
|
|
198
|
+
export type StorageGetPropertiesOutput<T> = PickProviderOutput<
|
|
199
|
+
Promise<S3ProviderGetPropertiesOutput>,
|
|
200
|
+
T,
|
|
201
|
+
'getProperties'
|
|
202
|
+
>;
|
|
203
|
+
|
|
171
204
|
/**
|
|
172
205
|
* Utility type to allow custom provider to use any config keys, if provider is set to AWSS3 then it should use
|
|
173
206
|
* AWSS3Provider's config.
|