@aws-amplify/storage 4.4.3 → 4.4.4-in-app-messaging.35

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.
Files changed (78) hide show
  1. package/CHANGELOG.md +28 -352
  2. package/dist/aws-amplify-storage.js +6523 -5062
  3. package/dist/aws-amplify-storage.js.map +1 -1
  4. package/dist/aws-amplify-storage.min.js +5 -5
  5. package/dist/aws-amplify-storage.min.js.map +1 -1
  6. package/lib/Storage.d.ts +3 -1
  7. package/lib/Storage.js +25 -21
  8. package/lib/Storage.js.map +1 -1
  9. package/lib/common/S3ClientUtils.d.ts +33 -0
  10. package/lib/common/S3ClientUtils.js +179 -0
  11. package/lib/common/S3ClientUtils.js.map +1 -0
  12. package/lib/common/StorageConstants.d.ts +4 -0
  13. package/lib/common/StorageConstants.js +10 -0
  14. package/lib/common/StorageConstants.js.map +1 -0
  15. package/lib/common/StorageErrorStrings.d.ts +5 -1
  16. package/lib/common/StorageErrorStrings.js +5 -0
  17. package/lib/common/StorageErrorStrings.js.map +1 -1
  18. package/lib/common/StorageUtils.d.ts +4 -0
  19. package/lib/common/StorageUtils.js +41 -0
  20. package/lib/common/StorageUtils.js.map +1 -0
  21. package/lib/providers/AWSS3Provider.d.ts +9 -6
  22. package/lib/providers/AWSS3Provider.js +197 -149
  23. package/lib/providers/AWSS3Provider.js.map +1 -1
  24. package/lib/providers/AWSS3ProviderManagedUpload.d.ts +3 -10
  25. package/lib/providers/AWSS3ProviderManagedUpload.js +41 -109
  26. package/lib/providers/AWSS3ProviderManagedUpload.js.map +1 -1
  27. package/lib/providers/AWSS3UploadTask.d.ts +107 -0
  28. package/lib/providers/AWSS3UploadTask.js +610 -0
  29. package/lib/providers/AWSS3UploadTask.js.map +1 -0
  30. package/lib/providers/axios-http-handler.d.ts +5 -1
  31. package/lib/providers/axios-http-handler.js +28 -5
  32. package/lib/providers/axios-http-handler.js.map +1 -1
  33. package/lib/types/AWSS3Provider.d.ts +24 -4
  34. package/lib/types/Provider.d.ts +7 -1
  35. package/lib/types/Storage.d.ts +8 -8
  36. package/lib-esm/Storage.d.ts +3 -1
  37. package/lib-esm/Storage.js +25 -21
  38. package/lib-esm/Storage.js.map +1 -1
  39. package/lib-esm/common/S3ClientUtils.d.ts +33 -0
  40. package/lib-esm/common/S3ClientUtils.js +177 -0
  41. package/lib-esm/common/S3ClientUtils.js.map +1 -0
  42. package/lib-esm/common/StorageConstants.d.ts +4 -0
  43. package/lib-esm/common/StorageConstants.js +8 -0
  44. package/lib-esm/common/StorageConstants.js.map +1 -0
  45. package/lib-esm/common/StorageErrorStrings.d.ts +5 -1
  46. package/lib-esm/common/StorageErrorStrings.js +5 -0
  47. package/lib-esm/common/StorageErrorStrings.js.map +1 -1
  48. package/lib-esm/common/StorageUtils.d.ts +4 -0
  49. package/lib-esm/common/StorageUtils.js +39 -0
  50. package/lib-esm/common/StorageUtils.js.map +1 -0
  51. package/lib-esm/providers/AWSS3Provider.d.ts +9 -6
  52. package/lib-esm/providers/AWSS3Provider.js +192 -144
  53. package/lib-esm/providers/AWSS3Provider.js.map +1 -1
  54. package/lib-esm/providers/AWSS3ProviderManagedUpload.d.ts +3 -10
  55. package/lib-esm/providers/AWSS3ProviderManagedUpload.js +44 -112
  56. package/lib-esm/providers/AWSS3ProviderManagedUpload.js.map +1 -1
  57. package/lib-esm/providers/AWSS3UploadTask.d.ts +107 -0
  58. package/lib-esm/providers/AWSS3UploadTask.js +605 -0
  59. package/lib-esm/providers/AWSS3UploadTask.js.map +1 -0
  60. package/lib-esm/providers/axios-http-handler.d.ts +5 -1
  61. package/lib-esm/providers/axios-http-handler.js +28 -5
  62. package/lib-esm/providers/axios-http-handler.js.map +1 -1
  63. package/lib-esm/types/AWSS3Provider.d.ts +24 -4
  64. package/lib-esm/types/Provider.d.ts +7 -1
  65. package/lib-esm/types/Storage.d.ts +8 -8
  66. package/package.json +3 -3
  67. package/src/Storage.ts +85 -27
  68. package/src/common/S3ClientUtils.ts +168 -0
  69. package/src/common/StorageConstants.ts +10 -0
  70. package/src/common/StorageErrorStrings.ts +5 -0
  71. package/src/common/StorageUtils.ts +51 -0
  72. package/src/providers/AWSS3Provider.ts +251 -88
  73. package/src/providers/AWSS3ProviderManagedUpload.ts +346 -397
  74. package/src/providers/AWSS3UploadTask.ts +543 -0
  75. package/src/providers/axios-http-handler.ts +221 -186
  76. package/src/types/AWSS3Provider.ts +48 -7
  77. package/src/types/Provider.ts +18 -3
  78. package/src/types/Storage.ts +9 -9
@@ -1,186 +1,221 @@
1
- /*
2
- * Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5
- * the License. A copy of the License is located at
6
- *
7
- * http://aws.amazon.com/apache2.0/
8
- *
9
- * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
- * and limitations under the License.
12
- */
13
-
14
- import { HttpHandlerOptions } from '@aws-sdk/types';
15
- import { HttpHandler, HttpRequest, HttpResponse } from '@aws-sdk/protocol-http';
16
- import { buildQueryString } from '@aws-sdk/querystring-builder';
17
- import axios, {
18
- AxiosRequestConfig,
19
- Method,
20
- CancelTokenSource,
21
- AxiosTransformer,
22
- } from 'axios';
23
- import { ConsoleLogger as Logger, Platform } from '@aws-amplify/core';
24
- import { FetchHttpHandlerOptions } from '@aws-sdk/fetch-http-handler';
25
- import * as events from 'events';
26
-
27
- const logger = new Logger('axios-http-handler');
28
- export const SEND_UPLOAD_PROGRESS_EVENT = 'sendUploadProgress';
29
- export const SEND_DOWNLOAD_PROGRESS_EVENT = 'sendDownloadProgress';
30
-
31
- function isBlob(body: any): body is Blob {
32
- return typeof Blob !== 'undefined' && body instanceof Blob;
33
- }
34
-
35
- const normalizeHeaders = (
36
- headers: Record<string, string>,
37
- normalizedName: string
38
- ) => {
39
- for (const [k, v] of Object.entries(headers)) {
40
- if (
41
- k !== normalizedName &&
42
- k.toUpperCase() === normalizedName.toUpperCase()
43
- ) {
44
- headers[normalizedName] = v;
45
- delete headers[k];
46
- }
47
- }
48
- };
49
-
50
- export const reactNativeRequestTransformer: AxiosTransformer[] = [
51
- function(data, headers) {
52
- if (isBlob(data)) {
53
- normalizeHeaders(headers, 'Content-Type');
54
- normalizeHeaders(headers, 'Accept');
55
- return data;
56
- }
57
- // Axios' default transformRequest is an array
58
- return axios.defaults.transformRequest[0].call(null, data, headers);
59
- },
60
- ];
61
-
62
- export class AxiosHttpHandler implements HttpHandler {
63
- constructor(
64
- private readonly httpOptions: FetchHttpHandlerOptions = {},
65
- private readonly emitter?: events.EventEmitter,
66
- private readonly cancelTokenSource?: CancelTokenSource
67
- ) {}
68
-
69
- destroy(): void {
70
- // Do nothing. TLS and HTTP/2 connection pooling is handled by the
71
- // browser.
72
- }
73
-
74
- handle(
75
- request: HttpRequest,
76
- options: HttpHandlerOptions
77
- ): Promise<{ response: HttpResponse }> {
78
- const requestTimeoutInMs = this.httpOptions.requestTimeout;
79
- const emitter = this.emitter;
80
-
81
- let path = request.path;
82
- if (request.query) {
83
- const queryString = buildQueryString(request.query);
84
- if (queryString) {
85
- path += `?${queryString}`;
86
- }
87
- }
88
-
89
- const port = request.port;
90
- const url = `${request.protocol}//${request.hostname}${
91
- port ? `:${port}` : ''
92
- }${path}`;
93
-
94
- const axiosRequest: AxiosRequestConfig = {};
95
- axiosRequest.url = url;
96
- axiosRequest.method = request.method as Method;
97
- axiosRequest.headers = request.headers;
98
-
99
- // The host header is automatically added by the browser and adding it explicitly in the
100
- // axios request throws an error https://github.com/aws-amplify/amplify-js/issues/5376
101
- // This is because the host header is a forbidden header for the http client to set
102
- // see https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name and
103
- // https://fetch.spec.whatwg.org/#forbidden-header-name
104
- // The reason we are removing this header here instead of in the aws-sdk's client
105
- // middleware is that the host header is required to be in the request signature and if
106
- // we remove it from the middlewares, then the request fails because the header is added
107
- // by the browser but is absent from the signature.
108
- delete axiosRequest.headers['host'];
109
-
110
- if (request.body) {
111
- axiosRequest.data = request.body;
112
- } else {
113
- // Fix for https://github.com/aws-amplify/amplify-js/issues/5432
114
-
115
- // If the POST request body is empty but content-type header is set, axios is forcibly removing it
116
- // See https://github.com/axios/axios/issues/1535 and refusing to fix it https://github.com/axios/axios/issues/755
117
- // This change is a workaround to set the data as null (instead of undefined) to prevent axios from
118
- // removing the content-type header. Link for the source code
119
- // https://github.com/axios/axios/blob/dc4bc49673943e35280e5df831f5c3d0347a9393/lib/adapters/xhr.js#L121-L123
120
-
121
- if (axiosRequest.headers['Content-Type']) {
122
- axiosRequest.data = null;
123
- }
124
- }
125
- if (emitter) {
126
- axiosRequest.onUploadProgress = function(event) {
127
- emitter.emit(SEND_UPLOAD_PROGRESS_EVENT, event);
128
- logger.debug(event);
129
- };
130
- axiosRequest.onDownloadProgress = function(event) {
131
- emitter.emit(SEND_DOWNLOAD_PROGRESS_EVENT, event);
132
- logger.debug(event);
133
- };
134
- }
135
- // If a cancel token source is passed down from the provider, allows cancellation of in-flight requests
136
- if (this.cancelTokenSource) {
137
- axiosRequest.cancelToken = this.cancelTokenSource.token;
138
- }
139
-
140
- // From gamma release, aws-sdk now expects all response type to be of blob or streams
141
- axiosRequest.responseType = 'blob';
142
-
143
- // In Axios, Blobs are identified by calling Object.prototype.toString on the object. However, on React Native,
144
- // calling Object.prototype.toString on a Blob returns '[object Object]' instead of '[object Blob]', which causes
145
- // Axios to treat Blobs as generic Javascript objects. Therefore we need a to use a custom request transformer
146
- // to correctly handle Blob in React Native.
147
- if (Platform.isReactNative) {
148
- axiosRequest.transformRequest = reactNativeRequestTransformer;
149
- }
150
-
151
- const raceOfPromises = [
152
- axios
153
- .request(axiosRequest)
154
- .then(response => {
155
- return {
156
- response: new HttpResponse({
157
- headers: response.headers,
158
- statusCode: response.status,
159
- body: response.data,
160
- }),
161
- };
162
- })
163
- .catch(error => {
164
- // Error
165
- logger.error(error.message);
166
- throw error;
167
- }),
168
- requestTimeout(requestTimeoutInMs),
169
- ];
170
- return Promise.race(raceOfPromises);
171
- }
172
- }
173
-
174
- function requestTimeout(timeoutInMs: number = 0): Promise<never> {
175
- return new Promise((resolve, reject) => {
176
- if (timeoutInMs) {
177
- setTimeout(() => {
178
- const timeoutError = new Error(
179
- `Request did not complete within ${timeoutInMs} ms`
180
- );
181
- timeoutError.name = 'TimeoutError';
182
- reject(timeoutError);
183
- }, timeoutInMs);
184
- }
185
- });
186
- }
1
+ /*
2
+ * Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5
+ * the License. A copy of the License is located at
6
+ *
7
+ * http://aws.amazon.com/apache2.0/
8
+ *
9
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
+ * and limitations under the License.
12
+ */
13
+
14
+ import { HttpHandlerOptions } from '@aws-sdk/types';
15
+ import { HttpHandler, HttpRequest, HttpResponse } from '@aws-sdk/protocol-http';
16
+ import { buildQueryString } from '@aws-sdk/querystring-builder';
17
+ import axios, {
18
+ AxiosRequestConfig,
19
+ Method,
20
+ CancelTokenSource,
21
+ AxiosTransformer,
22
+ } from 'axios';
23
+ import { ConsoleLogger as Logger, Platform } from '@aws-amplify/core';
24
+ import { FetchHttpHandlerOptions } from '@aws-sdk/fetch-http-handler';
25
+ import * as events from 'events';
26
+ import { AWSS3ProviderUploadErrorStrings } from '../common/StorageErrorStrings';
27
+
28
+ const logger = new Logger('axios-http-handler');
29
+ export const SEND_UPLOAD_PROGRESS_EVENT = 'sendUploadProgress';
30
+ export const SEND_DOWNLOAD_PROGRESS_EVENT = 'sendDownloadProgress';
31
+
32
+ function isBlob(body: any): body is Blob {
33
+ return typeof Blob !== 'undefined' && body instanceof Blob;
34
+ }
35
+
36
+ const normalizeHeaders = (
37
+ headers: Record<string, string>,
38
+ normalizedName: string
39
+ ) => {
40
+ for (const [k, v] of Object.entries(headers)) {
41
+ if (
42
+ k !== normalizedName &&
43
+ k.toUpperCase() === normalizedName.toUpperCase()
44
+ ) {
45
+ headers[normalizedName] = v;
46
+ delete headers[k];
47
+ }
48
+ }
49
+ };
50
+
51
+ export const reactNativeRequestTransformer: AxiosTransformer[] = [
52
+ function(data, headers) {
53
+ if (isBlob(data)) {
54
+ normalizeHeaders(headers, 'Content-Type');
55
+ normalizeHeaders(headers, 'Accept');
56
+ return data;
57
+ }
58
+ // Axios' default transformRequest is an array
59
+ return axios.defaults.transformRequest[0].call(null, data, headers);
60
+ },
61
+ ];
62
+
63
+ export type AxiosHttpHandlerOptions = HttpHandlerOptions & {
64
+ cancelTokenSource?: CancelTokenSource;
65
+ emitter?: events.EventEmitter;
66
+ };
67
+
68
+ export class AxiosHttpHandler implements HttpHandler {
69
+ constructor(
70
+ private readonly httpOptions: FetchHttpHandlerOptions = {},
71
+ private readonly emitter?: events.EventEmitter,
72
+ private readonly cancelTokenSource?: CancelTokenSource
73
+ ) {}
74
+
75
+ destroy(): void {
76
+ // Do nothing. TLS and HTTP/2 connection pooling is handled by the
77
+ // browser.
78
+ }
79
+
80
+ handle(
81
+ request: HttpRequest,
82
+ options: AxiosHttpHandlerOptions
83
+ ): Promise<{ response: HttpResponse }> {
84
+ const requestTimeoutInMs = this.httpOptions.requestTimeout;
85
+ // prioritize the call specific event emitter, this is useful for multipart upload as each individual parts has
86
+ // their own event emitter, without having to create s3client for every individual calls.
87
+ const emitter = options.emitter || this.emitter;
88
+
89
+ let path = request.path;
90
+ if (request.query) {
91
+ const queryString = buildQueryString(request.query);
92
+ if (queryString) {
93
+ path += `?${queryString}`;
94
+ }
95
+ }
96
+
97
+ const port = request.port;
98
+ const url = `${request.protocol}//${request.hostname}${
99
+ port ? `:${port}` : ''
100
+ }${path}`;
101
+
102
+ const axiosRequest: AxiosRequestConfig = {};
103
+ axiosRequest.url = url;
104
+ axiosRequest.method = request.method as Method;
105
+ axiosRequest.headers = request.headers;
106
+
107
+ // The host header is automatically added by the browser and adding it explicitly in the
108
+ // axios request throws an error https://github.com/aws-amplify/amplify-js/issues/5376
109
+ // This is because the host header is a forbidden header for the http client to set
110
+ // see https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name and
111
+ // https://fetch.spec.whatwg.org/#forbidden-header-name
112
+ // The reason we are removing this header here instead of in the aws-sdk's client
113
+ // middleware is that the host header is required to be in the request signature and if
114
+ // we remove it from the middlewares, then the request fails because the header is added
115
+ // by the browser but is absent from the signature.
116
+ delete axiosRequest.headers['host'];
117
+
118
+ if (request.body) {
119
+ axiosRequest.data = request.body;
120
+ } else {
121
+ // Fix for https://github.com/aws-amplify/amplify-js/issues/5432
122
+
123
+ // If the POST request body is empty but content-type header is set, axios is forcibly removing it
124
+ // See https://github.com/axios/axios/issues/1535 and refusing to fix it https://github.com/axios/axios/issues/755
125
+ // This change is a workaround to set the data as null (instead of undefined) to prevent axios from
126
+ // removing the content-type header. Link for the source code
127
+ // https://github.com/axios/axios/blob/dc4bc49673943e35280e5df831f5c3d0347a9393/lib/adapters/xhr.js#L121-L123
128
+
129
+ if (
130
+ axiosRequest.headers[
131
+ Object.keys(axiosRequest.headers).find(
132
+ key => key.toLowerCase() === 'content-type'
133
+ )
134
+ ]
135
+ ) {
136
+ axiosRequest.data = null;
137
+ }
138
+ }
139
+ if (emitter) {
140
+ axiosRequest.onUploadProgress = function(event) {
141
+ emitter.emit(SEND_UPLOAD_PROGRESS_EVENT, event);
142
+ logger.debug(event);
143
+ };
144
+ axiosRequest.onDownloadProgress = function(event) {
145
+ emitter.emit(SEND_DOWNLOAD_PROGRESS_EVENT, event);
146
+ logger.debug(event);
147
+ };
148
+ }
149
+ // If a cancel token source is passed down from the provider, allows cancellation of in-flight requests
150
+ if (this.cancelTokenSource) {
151
+ axiosRequest.cancelToken = this.cancelTokenSource.token;
152
+ }
153
+
154
+ if (options.cancelTokenSource) {
155
+ axiosRequest.cancelToken = options.cancelTokenSource.token;
156
+ }
157
+
158
+ // From gamma release, aws-sdk now expects all response type to be of blob or streams
159
+ axiosRequest.responseType = 'blob';
160
+ // In Axios, Blobs are identified by calling Object.prototype.toString on the object. However, on React Native,
161
+ // calling Object.prototype.toString on a Blob returns '[object Object]' instead of '[object Blob]', which causes
162
+ // Axios to treat Blobs as generic Javascript objects. Therefore we need a to use a custom request transformer
163
+ // to correctly handle Blob in React Native.
164
+ if (Platform.isReactNative) {
165
+ axiosRequest.transformRequest = reactNativeRequestTransformer;
166
+ }
167
+
168
+ const raceOfPromises = [
169
+ axios
170
+ .request(axiosRequest)
171
+ .then(response => {
172
+ return {
173
+ response: new HttpResponse({
174
+ headers: response.headers,
175
+ statusCode: response.status,
176
+ body: response.data,
177
+ }),
178
+ };
179
+ })
180
+ .catch(error => {
181
+ // Error
182
+ if (
183
+ error.message !==
184
+ AWSS3ProviderUploadErrorStrings.UPLOAD_PAUSED_MESSAGE
185
+ ) {
186
+ logger.error(error.message);
187
+ }
188
+ // for axios' cancel error, we should re-throw it back so it's not considered an s3client error
189
+ // if we return empty, or an abitrary error HttpResponse, it will be hard to debug down the line
190
+ if (axios.isCancel(error)) {
191
+ throw error;
192
+ }
193
+ // otherwise, we should re-construct an HttpResponse from the error, so that it can be passed down to other
194
+ // aws sdk middleware (e.g retry, clock skew correction, error message serializing)
195
+ return {
196
+ response: new HttpResponse({
197
+ statusCode: error.response?.status,
198
+ body: error.response?.data,
199
+ headers: error.response?.headers,
200
+ }),
201
+ };
202
+ }),
203
+ requestTimeout(requestTimeoutInMs),
204
+ ];
205
+ return Promise.race(raceOfPromises);
206
+ }
207
+ }
208
+
209
+ function requestTimeout(timeoutInMs: number = 0): Promise<never> {
210
+ return new Promise((resolve, reject) => {
211
+ if (timeoutInMs) {
212
+ setTimeout(() => {
213
+ const timeoutError = new Error(
214
+ `Request did not complete within ${timeoutInMs} ms`
215
+ );
216
+ timeoutError.name = 'TimeoutError';
217
+ reject(timeoutError);
218
+ }, timeoutInMs);
219
+ }
220
+ });
221
+ }
@@ -7,12 +7,29 @@ import {
7
7
  DeleteObjectCommandOutput,
8
8
  } from '@aws-sdk/client-s3';
9
9
  import { StorageOptions, StorageAccessLevel } from './Storage';
10
+ import {
11
+ UploadTaskCompleteEvent,
12
+ UploadTaskProgressEvent,
13
+ } from '../providers/AWSS3UploadTask';
14
+ import { UploadTask } from './Provider';
10
15
 
11
16
  type ListObjectsCommandOutputContent = _Object;
12
17
 
18
+ export interface FileMetadata {
19
+ bucket: string;
20
+ fileName: string;
21
+ key: string;
22
+ // Unix timestamp in ms
23
+ lastTouched: number;
24
+ uploadId: string;
25
+ }
26
+
13
27
  export type CommonStorageOptions = Omit<
14
28
  StorageOptions,
15
- 'credentials' | 'region' | 'bucket' | 'dangerouslyConnectToHttpEndpointForTesting'
29
+ | 'credentials'
30
+ | 'region'
31
+ | 'bucket'
32
+ | 'dangerouslyConnectToHttpEndpointForTesting'
16
33
  >;
17
34
 
18
35
  export type S3ProviderGetConfig = CommonStorageOptions & {
@@ -32,9 +49,11 @@ export type S3ProviderGetConfig = CommonStorageOptions & {
32
49
  SSECustomerKeyMD5?: GetObjectRequest['SSECustomerKeyMD5'];
33
50
  };
34
51
 
35
- export type S3ProviderGetOuput<T> = T extends { download: true } ? GetObjectCommandOutput : string;
52
+ export type S3ProviderGetOuput<T> = T extends { download: true }
53
+ ? GetObjectCommandOutput
54
+ : string;
36
55
 
37
- export type S3ProviderPutConfig = CommonStorageOptions & {
56
+ type _S3ProviderPutConfig = {
38
57
  progressCallback?: (progress: any) => any;
39
58
  provider?: 'AWSS3';
40
59
  track?: boolean;
@@ -53,13 +72,27 @@ export type S3ProviderPutConfig = CommonStorageOptions & {
53
72
  metadata?: PutObjectRequest['Metadata'];
54
73
  tagging?: PutObjectRequest['Tagging'];
55
74
  useAccelerateEndpoint?: boolean;
75
+ resumable?: boolean;
56
76
  };
57
77
 
58
- export interface S3ProviderPutOutput {
59
- key: string;
60
- }
78
+ export type ResumableUploadConfig = {
79
+ resumable: true;
80
+ progressCallback?: (progress: UploadTaskProgressEvent) => any;
81
+ completeCallback?: (event: UploadTaskCompleteEvent) => any;
82
+ errorCallback?: (err: any) => any;
83
+ };
61
84
 
62
- export type S3ProviderRemoveConfig = CommonStorageOptions & { bucket?: string; provider?: 'AWSS3' };
85
+ export type S3ProviderPutConfig = CommonStorageOptions &
86
+ (
87
+ | _S3ProviderPutConfig
88
+ // discriminated union so users won't be able to add resumable specific callbacks without the resumable flag
89
+ | (_S3ProviderPutConfig & ResumableUploadConfig)
90
+ );
91
+
92
+ export type S3ProviderRemoveConfig = CommonStorageOptions & {
93
+ bucket?: string;
94
+ provider?: 'AWSS3';
95
+ };
63
96
 
64
97
  export type S3ProviderRemoveOutput = DeleteObjectCommandOutput;
65
98
 
@@ -110,3 +143,11 @@ export type S3ProviderCopyConfig = Omit<CommonStorageOptions, 'level'> & {
110
143
  export type S3ProviderCopyOutput = {
111
144
  key: string;
112
145
  };
146
+
147
+ export type PutResult = {
148
+ key: string;
149
+ };
150
+
151
+ export type S3ProviderPutOutput<T> = T extends { resumable: true }
152
+ ? UploadTask
153
+ : Promise<PutResult>;
@@ -18,7 +18,11 @@ export interface StorageProvider {
18
18
  cancel?(request: Promise<any>): void;
19
19
 
20
20
  // copy object from src to dest
21
- copy?(src: StorageCopySource, dest: StorageCopyDestination, config?): Promise<any>;
21
+ copy?(
22
+ src: StorageCopySource,
23
+ dest: StorageCopyDestination,
24
+ config?
25
+ ): Promise<any>;
22
26
 
23
27
  // configure your provider
24
28
  configure(config: object): object;
@@ -27,7 +31,7 @@ export interface StorageProvider {
27
31
  get(key: string, options?): Promise<string | Object>;
28
32
 
29
33
  // upload storage object
30
- put(key: string, object, options?): Promise<Object>;
34
+ put(key: string, object, options?): Promise<Object> | UploadTask;
31
35
 
32
36
  // remove object
33
37
  remove(key: string, options?): Promise<any>;
@@ -42,9 +46,20 @@ export interface StorageProvider {
42
46
  getProviderName(): string;
43
47
  }
44
48
 
49
+ export interface UploadTask {
50
+ resume(): any;
51
+ pause(): any;
52
+ percent: number;
53
+ isInProgress: boolean;
54
+ }
55
+
45
56
  export interface StorageProviderWithCopy extends StorageProvider {
46
57
  // copy object from src to dest
47
- copy(src: StorageCopySource, dest: StorageCopyDestination, config?): Promise<any>;
58
+ copy(
59
+ src: StorageCopySource,
60
+ dest: StorageCopyDestination,
61
+ config?
62
+ ): Promise<any>;
48
63
  }
49
64
 
50
65
  export type StorageProviderApi = 'copy' | 'get' | 'put' | 'remove' | 'list';
@@ -21,10 +21,10 @@ import {
21
21
  AWSS3Provider,
22
22
  StorageProviderWithCopy,
23
23
  S3ProviderGetOuput,
24
- S3ProviderPutOutput,
25
24
  S3ProviderRemoveOutput,
26
25
  S3ProviderListOutput,
27
26
  S3ProviderCopyOutput,
27
+ S3ProviderPutOutput,
28
28
  } from '../';
29
29
 
30
30
  type Tail<T extends any[]> = ((...t: T) => void) extends (
@@ -124,40 +124,40 @@ type PickProviderOutput<
124
124
  api extends StorageProviderApi
125
125
  > = T extends StorageProvider
126
126
  ? T['getProviderName'] extends 'AWSS3'
127
- ? Promise<DefaultOutput>
127
+ ? DefaultOutput
128
128
  : T extends StorageProviderWithCopy
129
129
  ? ReturnType<T[api]>
130
130
  : ReturnType<T[Exclude<api, 'copy'>]>
131
131
  : T extends { provider: string }
132
132
  ? T extends { provider: 'AWSS3' }
133
- ? Promise<DefaultOutput>
133
+ ? DefaultOutput
134
134
  : Promise<any>
135
- : Promise<DefaultOutput>;
135
+ : DefaultOutput;
136
136
 
137
137
  export type StorageGetOutput<
138
138
  T extends StorageProvider | Record<string, any>
139
- > = PickProviderOutput<S3ProviderGetOuput<T>, T, 'get'>;
139
+ > = PickProviderOutput<Promise<S3ProviderGetOuput<T>>, T, 'get'>;
140
140
 
141
141
  export type StoragePutOutput<T> = PickProviderOutput<
142
- S3ProviderPutOutput,
142
+ S3ProviderPutOutput<T>,
143
143
  T,
144
144
  'put'
145
145
  >;
146
146
 
147
147
  export type StorageRemoveOutput<T> = PickProviderOutput<
148
- S3ProviderRemoveOutput,
148
+ Promise<S3ProviderRemoveOutput>,
149
149
  T,
150
150
  'remove'
151
151
  >;
152
152
 
153
153
  export type StorageListOutput<T> = PickProviderOutput<
154
- S3ProviderListOutput,
154
+ Promise<S3ProviderListOutput>,
155
155
  T,
156
156
  'list'
157
157
  >;
158
158
 
159
159
  export type StorageCopyOutput<T> = PickProviderOutput<
160
- S3ProviderCopyOutput,
160
+ Promise<S3ProviderCopyOutput>,
161
161
  T,
162
162
  'copy'
163
163
  >;