@aws-amplify/storage 6.11.2-unstable.5a0e006.0 → 6.11.2-unstable.b6d4c7a.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.
Files changed (110) hide show
  1. package/dist/cjs/internals/apis/remove.js +13 -12
  2. package/dist/cjs/internals/apis/remove.js.map +1 -1
  3. package/dist/cjs/providers/s3/apis/internal/remove.js +53 -29
  4. package/dist/cjs/providers/s3/apis/internal/remove.js.map +1 -1
  5. package/dist/cjs/providers/s3/apis/remove.js +6 -1
  6. package/dist/cjs/providers/s3/apis/remove.js.map +1 -1
  7. package/dist/cjs/providers/s3/apis/server/remove.js +6 -1
  8. package/dist/cjs/providers/s3/apis/server/remove.js.map +1 -1
  9. package/dist/cjs/providers/s3/utils/client/s3data/deleteObjects.js +70 -0
  10. package/dist/cjs/providers/s3/utils/client/s3data/deleteObjects.js.map +1 -0
  11. package/dist/cjs/providers/s3/utils/client/s3data/index.js +3 -1
  12. package/dist/cjs/providers/s3/utils/client/s3data/index.js.map +1 -1
  13. package/dist/cjs/providers/s3/utils/createAbortableTask.js +35 -0
  14. package/dist/cjs/providers/s3/utils/createAbortableTask.js.map +1 -0
  15. package/dist/cjs/providers/s3/utils/deleteFolderContents.js +80 -0
  16. package/dist/cjs/providers/s3/utils/deleteFolderContents.js.map +1 -0
  17. package/dist/cjs/providers/s3/utils/generateDeleteObjectsXml.js +38 -0
  18. package/dist/cjs/providers/s3/utils/generateDeleteObjectsXml.js.map +1 -0
  19. package/dist/cjs/providers/s3/utils/index.js +13 -1
  20. package/dist/cjs/providers/s3/utils/index.js.map +1 -1
  21. package/dist/cjs/providers/s3/utils/isPathFolder.js +38 -0
  22. package/dist/cjs/providers/s3/utils/isPathFolder.js.map +1 -0
  23. package/dist/cjs/providers/s3/utils/resolveFinalKey.js +22 -0
  24. package/dist/cjs/providers/s3/utils/resolveFinalKey.js.map +1 -0
  25. package/dist/cjs/providers/s3/utils/validateRemovePath.js +21 -0
  26. package/dist/cjs/providers/s3/utils/validateRemovePath.js.map +1 -0
  27. package/dist/esm/internals/apis/remove.d.ts +2 -1
  28. package/dist/esm/internals/apis/remove.mjs +13 -12
  29. package/dist/esm/internals/apis/remove.mjs.map +1 -1
  30. package/dist/esm/providers/s3/apis/internal/copy.mjs +8 -7
  31. package/dist/esm/providers/s3/apis/internal/copy.mjs.map +1 -1
  32. package/dist/esm/providers/s3/apis/internal/downloadData.d.ts +1 -1
  33. package/dist/esm/providers/s3/apis/internal/downloadData.mjs +6 -5
  34. package/dist/esm/providers/s3/apis/internal/downloadData.mjs.map +1 -1
  35. package/dist/esm/providers/s3/apis/internal/getProperties.mjs +7 -6
  36. package/dist/esm/providers/s3/apis/internal/getProperties.mjs.map +1 -1
  37. package/dist/esm/providers/s3/apis/internal/getUrl.mjs +2 -1
  38. package/dist/esm/providers/s3/apis/internal/getUrl.mjs.map +1 -1
  39. package/dist/esm/providers/s3/apis/internal/list.mjs +8 -7
  40. package/dist/esm/providers/s3/apis/internal/list.mjs.map +1 -1
  41. package/dist/esm/providers/s3/apis/internal/remove.d.ts +3 -2
  42. package/dist/esm/providers/s3/apis/internal/remove.mjs +58 -27
  43. package/dist/esm/providers/s3/apis/internal/remove.mjs.map +1 -1
  44. package/dist/esm/providers/s3/apis/internal/uploadData/index.mjs +13 -0
  45. package/dist/esm/providers/s3/apis/internal/uploadData/index.mjs.map +1 -1
  46. package/dist/esm/providers/s3/apis/internal/uploadData/multipart/initialUpload.mjs +1 -0
  47. package/dist/esm/providers/s3/apis/internal/uploadData/multipart/initialUpload.mjs.map +1 -1
  48. package/dist/esm/providers/s3/apis/internal/uploadData/multipart/uploadCache.mjs +1 -0
  49. package/dist/esm/providers/s3/apis/internal/uploadData/multipart/uploadCache.mjs.map +1 -1
  50. package/dist/esm/providers/s3/apis/internal/uploadData/multipart/uploadHandlers.mjs +6 -5
  51. package/dist/esm/providers/s3/apis/internal/uploadData/multipart/uploadHandlers.mjs.map +1 -1
  52. package/dist/esm/providers/s3/apis/internal/uploadData/multipart/uploadPartExecutor.mjs +1 -0
  53. package/dist/esm/providers/s3/apis/internal/uploadData/multipart/uploadPartExecutor.mjs.map +1 -1
  54. package/dist/esm/providers/s3/apis/internal/uploadData/putObjectJob.mjs +7 -6
  55. package/dist/esm/providers/s3/apis/internal/uploadData/putObjectJob.mjs.map +1 -1
  56. package/dist/esm/providers/s3/apis/remove.d.ts +6 -6
  57. package/dist/esm/providers/s3/apis/remove.mjs +6 -1
  58. package/dist/esm/providers/s3/apis/remove.mjs.map +1 -1
  59. package/dist/esm/providers/s3/apis/server/remove.d.ts +6 -6
  60. package/dist/esm/providers/s3/apis/server/remove.mjs +6 -1
  61. package/dist/esm/providers/s3/apis/server/remove.mjs.map +1 -1
  62. package/dist/esm/providers/s3/types/index.d.ts +1 -1
  63. package/dist/esm/providers/s3/types/inputs.d.ts +24 -1
  64. package/dist/esm/providers/s3/utils/client/s3data/deleteObjects.d.ts +30 -0
  65. package/dist/esm/providers/s3/utils/client/s3data/deleteObjects.mjs +74 -0
  66. package/dist/esm/providers/s3/utils/client/s3data/deleteObjects.mjs.map +1 -0
  67. package/dist/esm/providers/s3/utils/client/s3data/index.d.ts +1 -0
  68. package/dist/esm/providers/s3/utils/client/s3data/index.mjs +1 -0
  69. package/dist/esm/providers/s3/utils/client/s3data/index.mjs.map +1 -1
  70. package/dist/esm/providers/s3/utils/client/s3data/types.d.ts +26 -0
  71. package/dist/esm/providers/s3/utils/createAbortableTask.d.ts +6 -0
  72. package/dist/esm/providers/s3/utils/createAbortableTask.mjs +33 -0
  73. package/dist/esm/providers/s3/utils/createAbortableTask.mjs.map +1 -0
  74. package/dist/esm/providers/s3/utils/deleteFolderContents.d.ts +16 -0
  75. package/dist/esm/providers/s3/utils/deleteFolderContents.mjs +90 -0
  76. package/dist/esm/providers/s3/utils/deleteFolderContents.mjs.map +1 -0
  77. package/dist/esm/providers/s3/utils/generateDeleteObjectsXml.d.ts +10 -0
  78. package/dist/esm/providers/s3/utils/generateDeleteObjectsXml.mjs +35 -0
  79. package/dist/esm/providers/s3/utils/generateDeleteObjectsXml.mjs.map +1 -0
  80. package/dist/esm/providers/s3/utils/index.d.ts +6 -0
  81. package/dist/esm/providers/s3/utils/index.mjs +6 -0
  82. package/dist/esm/providers/s3/utils/index.mjs.map +1 -1
  83. package/dist/esm/providers/s3/utils/isPathFolder.d.ts +13 -0
  84. package/dist/esm/providers/s3/utils/isPathFolder.mjs +48 -0
  85. package/dist/esm/providers/s3/utils/isPathFolder.mjs.map +1 -0
  86. package/dist/esm/providers/s3/utils/resolveFinalKey.d.ts +9 -0
  87. package/dist/esm/providers/s3/utils/resolveFinalKey.mjs +20 -0
  88. package/dist/esm/providers/s3/utils/resolveFinalKey.mjs.map +1 -0
  89. package/dist/esm/providers/s3/utils/validateRemovePath.d.ts +8 -0
  90. package/dist/esm/providers/s3/utils/validateRemovePath.mjs +18 -0
  91. package/dist/esm/providers/s3/utils/validateRemovePath.mjs.map +1 -0
  92. package/dist/esm/types/common.d.ts +3 -0
  93. package/package.json +5 -5
  94. package/src/internals/apis/remove.ts +17 -10
  95. package/src/providers/s3/apis/internal/remove.ts +96 -41
  96. package/src/providers/s3/apis/remove.ts +11 -6
  97. package/src/providers/s3/apis/server/remove.ts +11 -6
  98. package/src/providers/s3/types/index.ts +2 -0
  99. package/src/providers/s3/types/inputs.ts +24 -1
  100. package/src/providers/s3/utils/client/s3data/deleteObjects.ts +122 -0
  101. package/src/providers/s3/utils/client/s3data/index.ts +5 -0
  102. package/src/providers/s3/utils/client/s3data/types.ts +20 -0
  103. package/src/providers/s3/utils/createAbortableTask.ts +45 -0
  104. package/src/providers/s3/utils/deleteFolderContents.ts +118 -0
  105. package/src/providers/s3/utils/generateDeleteObjectsXml.ts +38 -0
  106. package/src/providers/s3/utils/index.ts +6 -0
  107. package/src/providers/s3/utils/isPathFolder.ts +50 -0
  108. package/src/providers/s3/utils/resolveFinalKey.ts +22 -0
  109. package/src/providers/s3/utils/validateRemovePath.ts +16 -0
  110. package/src/types/common.ts +5 -0
@@ -32,5 +32,8 @@ export interface TransferTask<Result> {
32
32
  */
33
33
  result: Promise<Result>;
34
34
  }
35
+ export interface NonPausableTransferTask<T> extends Omit<TransferTask<T>, 'pause' | 'resume' | 'state'> {
36
+ state: Omit<TransferTask<T>['state'], 'PAUSED'>;
37
+ }
35
38
  export type DownloadTask<Result> = Omit<TransferTask<Result>, 'pause' | 'resume'>;
36
39
  export type UploadTask<Result> = TransferTask<Result>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws-amplify/storage",
3
- "version": "6.11.2-unstable.5a0e006.0+5a0e006",
3
+ "version": "6.11.2-unstable.b6d4c7a.0+b6d4c7a",
4
4
  "description": "Storage category of aws-amplify",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.mjs",
@@ -108,12 +108,12 @@
108
108
  "./package.json": "./package.json"
109
109
  },
110
110
  "peerDependencies": {
111
- "@aws-amplify/core": "6.15.2-unstable.5a0e006.0+5a0e006"
111
+ "@aws-amplify/core": "6.15.2-unstable.b6d4c7a.0+b6d4c7a"
112
112
  },
113
113
  "devDependencies": {
114
- "@aws-amplify/core": "6.15.2-unstable.5a0e006.0+5a0e006",
115
- "@aws-amplify/react-native": "1.3.3-unstable.5a0e006.0+5a0e006",
114
+ "@aws-amplify/core": "6.15.2-unstable.b6d4c7a.0+b6d4c7a",
115
+ "@aws-amplify/react-native": "1.3.3-unstable.b6d4c7a.0+b6d4c7a",
116
116
  "@types/node": "20.14.12"
117
117
  },
118
- "gitHead": "5a0e006dc359625cc4d9f06ba7fc5b71dbb382fd"
118
+ "gitHead": "b6d4c7ac976855f530b41e95f678e96867832a11"
119
119
  }
@@ -4,22 +4,29 @@
4
4
  import { Amplify } from '@aws-amplify/core';
5
5
 
6
6
  import { remove as removeInternal } from '../../providers/s3/apis/internal/remove';
7
+ import { RemoveOperation } from '../../providers/s3/types';
7
8
  import { RemoveInput } from '../types/inputs';
8
9
  import { RemoveOutput } from '../types/outputs';
9
10
 
10
11
  /**
11
12
  * @internal
12
13
  */
13
- export const remove = (input: RemoveInput): Promise<RemoveOutput> =>
14
- removeInternal(Amplify, {
15
- path: input.path,
16
- options: {
17
- useAccelerateEndpoint: input?.options?.useAccelerateEndpoint,
18
- bucket: input?.options?.bucket,
19
- expectedBucketOwner: input?.options?.expectedBucketOwner,
20
- locationCredentialsProvider: input?.options?.locationCredentialsProvider,
21
- customEndpoint: input?.options?.customEndpoint,
14
+ export const remove = (input: RemoveInput): RemoveOperation<RemoveOutput> => {
15
+ return removeInternal(
16
+ Amplify,
17
+ {
18
+ path: input.path,
19
+ options: {
20
+ useAccelerateEndpoint: input?.options?.useAccelerateEndpoint,
21
+ bucket: input?.options?.bucket,
22
+ expectedBucketOwner: input?.options?.expectedBucketOwner,
23
+ locationCredentialsProvider:
24
+ input?.options?.locationCredentialsProvider,
25
+ customEndpoint: input?.options?.customEndpoint,
26
+ onProgress: input?.options?.onProgress,
27
+ },
22
28
  },
23
29
  // Type casting is necessary because `removeInternal` supports both Gen1 and Gen2 signatures, but here
24
30
  // given in input can only be Gen2 signature, the return can only ben Gen2 signature.
25
- }) as Promise<RemoveOutput>;
31
+ ) as RemoveOperation<RemoveOutput>;
32
+ };
@@ -4,58 +4,113 @@
4
4
  import { AmplifyClassV6 } from '@aws-amplify/core';
5
5
  import { StorageAction } from '@aws-amplify/core/internals/utils';
6
6
 
7
- import { RemoveInput, RemoveOutput, RemoveWithPathOutput } from '../../types';
8
7
  import {
8
+ RemoveInput,
9
+ RemoveOperation,
10
+ RemoveOutput,
11
+ RemoveWithPathOutput,
12
+ } from '../../types';
13
+ import {
14
+ deleteFolderContents,
15
+ isPathFolder,
16
+ resolveFinalKey,
9
17
  resolveS3ConfigAndInput,
10
18
  validateBucketOwnerID,
19
+ validateRemovePath,
11
20
  validateStorageOperationInput,
12
21
  } from '../../utils';
13
22
  import { deleteObject } from '../../utils/client/s3data';
14
23
  import { getStorageUserAgentValue } from '../../utils/userAgent';
15
- import { logger } from '../../../../utils';
16
24
  import { STORAGE_INPUT_KEY } from '../../utils/constants';
25
+ import { createAbortableTask } from '../../utils/createAbortableTask';
17
26
  // TODO: Remove this interface when we move to public advanced APIs.
18
27
  import { RemoveInput as RemoveWithPathInputWithAdvancedOptions } from '../../../../internals';
28
+ import { CanceledError } from '../../../../errors/CanceledError';
19
29
 
20
- export const remove = async (
30
+ export function remove(
31
+ amplify: AmplifyClassV6,
32
+ input: RemoveInput,
33
+ ): RemoveOperation<RemoveOutput>;
34
+ export function remove(
35
+ amplify: AmplifyClassV6,
36
+ input: RemoveWithPathInputWithAdvancedOptions,
37
+ ): RemoveOperation<RemoveWithPathOutput>;
38
+ export function remove(
21
39
  amplify: AmplifyClassV6,
22
40
  input: RemoveInput | RemoveWithPathInputWithAdvancedOptions,
23
- ): Promise<RemoveOutput | RemoveWithPathOutput> => {
24
- const { s3Config, keyPrefix, bucket, identityId } =
25
- await resolveS3ConfigAndInput(amplify, input);
26
-
27
- const { inputType, objectKey } = validateStorageOperationInput(
28
- input,
29
- identityId,
30
- );
31
- validateBucketOwnerID(input.options?.expectedBucketOwner);
32
-
33
- let finalKey;
34
- if (inputType === STORAGE_INPUT_KEY) {
35
- finalKey = `${keyPrefix}${objectKey}`;
36
- logger.debug(`remove "${objectKey}" from "${finalKey}".`);
37
- } else {
38
- finalKey = objectKey;
39
- logger.debug(`removing object in path "${finalKey}"`);
40
- }
41
-
42
- await deleteObject(
43
- {
44
- ...s3Config,
45
- userAgentValue: getStorageUserAgentValue(StorageAction.Remove),
46
- },
47
- {
48
- Bucket: bucket,
49
- Key: finalKey,
50
- ExpectedBucketOwner: input.options?.expectedBucketOwner,
51
- },
52
- );
53
-
54
- return inputType === STORAGE_INPUT_KEY
55
- ? {
56
- key: objectKey,
41
+ ): RemoveOperation<RemoveOutput | RemoveWithPathOutput> {
42
+ return createAbortableTask(executeRemove(amplify, input));
43
+ }
44
+
45
+ const executeRemove =
46
+ (
47
+ amplify: AmplifyClassV6,
48
+ input: RemoveInput | RemoveWithPathInputWithAdvancedOptions,
49
+ ) =>
50
+ async (abortController: AbortController) => {
51
+ try {
52
+ const { s3Config, keyPrefix, bucket, identityId } =
53
+ await resolveS3ConfigAndInput(amplify, input);
54
+
55
+ const { inputType, objectKey } = validateStorageOperationInput(
56
+ input,
57
+ identityId,
58
+ );
59
+
60
+ validateBucketOwnerID(input.options?.expectedBucketOwner);
61
+
62
+ const finalKey = resolveFinalKey(inputType, objectKey, keyPrefix);
63
+
64
+ validateRemovePath(finalKey);
65
+
66
+ const isFolder =
67
+ finalKey.endsWith('/') ||
68
+ (await isPathFolder({
69
+ s3Config,
70
+ bucket,
71
+ key: finalKey,
72
+ expectedBucketOwner: input.options?.expectedBucketOwner,
73
+ }));
74
+
75
+ if (isFolder) {
76
+ return deleteFolderContents({
77
+ s3Config,
78
+ bucket,
79
+ folderKey: finalKey,
80
+ expectedBucketOwner: input.options?.expectedBucketOwner,
81
+ onProgress: (input as any).options?.onProgress,
82
+ abortSignal: abortController.signal,
83
+ });
84
+ } else {
85
+ if (abortController.signal.aborted) {
86
+ throw new CanceledError({ message: 'Operation was cancelled' });
87
+ }
88
+
89
+ await deleteObject(
90
+ {
91
+ ...s3Config,
92
+ userAgentValue: getStorageUserAgentValue(StorageAction.Remove),
93
+ abortSignal: abortController.signal,
94
+ },
95
+ {
96
+ Bucket: bucket,
97
+ Key: finalKey,
98
+ ExpectedBucketOwner: input.options?.expectedBucketOwner,
99
+ },
100
+ );
101
+
102
+ const result =
103
+ inputType === STORAGE_INPUT_KEY
104
+ ? { key: objectKey }
105
+ : { path: objectKey };
106
+
107
+ return result;
108
+ }
109
+ } catch (error) {
110
+ if (abortController.signal.aborted) {
111
+ throw new CanceledError({ message: 'Operation was cancelled' });
57
112
  }
58
- : {
59
- path: objectKey,
60
- };
61
- };
113
+
114
+ throw error;
115
+ }
116
+ };
@@ -5,6 +5,7 @@ import { Amplify } from '@aws-amplify/core';
5
5
 
6
6
  import {
7
7
  RemoveInput,
8
+ RemoveOperation,
8
9
  RemoveOutput,
9
10
  RemoveWithPathInput,
10
11
  RemoveWithPathOutput,
@@ -13,29 +14,33 @@ import {
13
14
  import { remove as removeInternal } from './internal/remove';
14
15
 
15
16
  /**
16
- * Remove a file from your S3 bucket.
17
+ * Remove a file or folder from your S3 bucket.
17
18
  * @param input - The `RemoveWithPathInput` object.
18
- * @return Output containing the removed object path.
19
+ * @return Operation handle with result promise and cancellation capability.
19
20
  * @throws service: `S3Exception` - S3 service errors thrown while while removing the object.
20
21
  * @throws validation: `StorageValidationErrorCode` - Validation errors thrown
21
22
  * when there is no path or path is empty or path has a leading slash.
22
23
  */
23
24
  export function remove(
24
25
  input: RemoveWithPathInput,
25
- ): Promise<RemoveWithPathOutput>;
26
+ ): RemoveOperation<RemoveWithPathOutput>;
26
27
  /**
27
28
  * @deprecated The `key` and `accessLevel` parameters are deprecated and may be removed in the next major version.
28
29
  * Please use {@link https://docs.amplify.aws/react/build-a-backend/storage/remove | path} instead.
29
30
  *
30
31
  * Remove a file from your S3 bucket.
31
32
  * @param input - The `RemoveInput` object.
32
- * @return Output containing the removed object key
33
+ * @return Operation handle with result promise and cancellation capability.
33
34
  * @throws service: `S3Exception` - S3 service errors thrown while while removing the object
34
35
  * @throws validation: `StorageValidationErrorCode` - Validation errors thrown
35
36
  * when there is no key or its empty.
36
37
  */
37
- export function remove(input: RemoveInput): Promise<RemoveOutput>;
38
+ export function remove(input: RemoveInput): RemoveOperation<RemoveOutput>;
38
39
 
39
40
  export function remove(input: RemoveInput | RemoveWithPathInput) {
40
- return removeInternal(Amplify, input);
41
+ if ('key' in input) {
42
+ return removeInternal(Amplify, input);
43
+ } else {
44
+ return removeInternal(Amplify, input);
45
+ }
41
46
  }
@@ -8,6 +8,7 @@ import {
8
8
 
9
9
  import {
10
10
  RemoveInput,
11
+ RemoveOperation,
11
12
  RemoveOutput,
12
13
  RemoveWithPathInput,
13
14
  RemoveWithPathOutput,
@@ -15,10 +16,10 @@ import {
15
16
  import { remove as removeInternal } from '../internal/remove';
16
17
 
17
18
  /**
18
- * Remove a file from your S3 bucket.
19
+ * Remove a file or folder from your S3 bucket.
19
20
  * @param input - The `RemoveWithPathInput` object.
20
21
  * @param contextSpec - The context spec used to get the Amplify server context.
21
- * @return Output containing the removed object path.
22
+ * @return Operation handle with result promise and cancellation capability.
22
23
  * @throws service: `S3Exception` - S3 service errors thrown while while removing the object.
23
24
  * @throws validation: `StorageValidationErrorCode` - Validation errors thrown
24
25
  * when there is no path or path is empty or path has a leading slash.
@@ -26,7 +27,7 @@ import { remove as removeInternal } from '../internal/remove';
26
27
  export function remove(
27
28
  contextSpec: AmplifyServer.ContextSpec,
28
29
  input: RemoveWithPathInput,
29
- ): Promise<RemoveWithPathOutput>;
30
+ ): RemoveOperation<RemoveWithPathOutput>;
30
31
  /**
31
32
  * @deprecated The `key` and `accessLevel` parameters are deprecated and may be removed in the next major version.
32
33
  * Please use {@link https://docs.amplify.aws/react/build-a-backend/storage/remove | path} instead.
@@ -34,7 +35,7 @@ export function remove(
34
35
  * Remove a file from your S3 bucket.
35
36
  * @param input - The `RemoveInput` object.
36
37
  * @param contextSpec - The context spec used to get the Amplify server context.
37
- * @return Output containing the removed object key
38
+ * @return Operation handle with result promise and cancellation capability.
38
39
  * @throws service: `S3Exception` - S3 service errors thrown while while removing the object
39
40
  * @throws validation: `StorageValidationErrorCode` - Validation errors thrown
40
41
  * when there is no key or its empty.
@@ -42,11 +43,15 @@ export function remove(
42
43
  export function remove(
43
44
  contextSpec: AmplifyServer.ContextSpec,
44
45
  input: RemoveInput,
45
- ): Promise<RemoveOutput>;
46
+ ): RemoveOperation<RemoveOutput>;
46
47
 
47
48
  export function remove(
48
49
  contextSpec: AmplifyServer.ContextSpec,
49
50
  input: RemoveInput | RemoveWithPathInput,
50
51
  ) {
51
- return removeInternal(getAmplifyServerContext(contextSpec).amplify, input);
52
+ if ('key' in input) {
53
+ return removeInternal(getAmplifyServerContext(contextSpec).amplify, input);
54
+ } else {
55
+ return removeInternal(getAmplifyServerContext(contextSpec).amplify, input);
56
+ }
52
57
  }
@@ -47,6 +47,8 @@ export {
47
47
  GetUrlWithPathInput,
48
48
  RemoveWithPathInput,
49
49
  RemoveInput,
50
+ RemoveOperation,
51
+ ProgressInfo,
50
52
  DownloadDataInput,
51
53
  DownloadDataWithPathInput,
52
54
  UploadDataInput,
@@ -17,6 +17,7 @@ import {
17
17
  StorageUploadDataInputWithKey,
18
18
  StorageUploadDataInputWithPath,
19
19
  } from '../../../types';
20
+ import { NonPausableTransferTask } from '../../../types/common';
20
21
  import {
21
22
  CopyDestinationWithKeyOptions,
22
23
  CopySourceWithKeyOptions,
@@ -107,9 +108,31 @@ export type RemoveInput = StorageRemoveInputWithKey<RemoveOptions>;
107
108
  * Input type with path for S3 remove API.
108
109
  */
109
110
  export type RemoveWithPathInput = StorageRemoveInputWithPath<
110
- Omit<RemoveOptions, 'accessLevel'>
111
+ Omit<RemoveOptions, 'accessLevel'> & {
112
+ /** Callback function invoked after each batch completes, providing progress updates with file counts and error details. */
113
+ onProgress?(progress: ProgressInfo): void;
114
+ }
111
115
  >;
112
116
 
117
+ /**
118
+ * Represents an ongoing remove operation with cancellation and state tracking capabilities
119
+ * @template T - The type of the result (RemoveWithPathOutput | RemoveOutput)
120
+ */
121
+ export interface RemoveOperation<T> extends NonPausableTransferTask<T> {
122
+ then: Promise<T>['then'];
123
+ catch: Promise<T>['catch'];
124
+ finally: Promise<T>['finally'];
125
+ }
126
+
127
+ export interface ProgressInfo {
128
+ deleted?: { path: string }[];
129
+ failed?: {
130
+ path: string;
131
+ code: string;
132
+ message: string;
133
+ }[];
134
+ }
135
+
113
136
  /**
114
137
  * @deprecated Use {@link DownloadDataWithPathInput} instead.
115
138
  * Input type for S3 downloadData API.
@@ -0,0 +1,122 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import {
5
+ Endpoint,
6
+ HttpRequest,
7
+ HttpResponse,
8
+ parseMetadata,
9
+ } from '@aws-amplify/core/internals/aws-client-utils';
10
+ import {
11
+ AmplifyUrl,
12
+ AmplifyUrlSearchParams,
13
+ } from '@aws-amplify/core/internals/utils';
14
+ import { composeServiceApi } from '@aws-amplify/core/internals/aws-client-utils/composers';
15
+
16
+ import {
17
+ assignStringVariables,
18
+ buildStorageServiceError,
19
+ s3TransferHandler,
20
+ validateS3RequiredParameter,
21
+ } from '../utils';
22
+ import { generateDeleteObjectsXml } from '../../generateDeleteObjectsXml';
23
+ import { calculateContentMd5 } from '../../md5';
24
+
25
+ import type {
26
+ DeleteObjectsCommandInput,
27
+ DeleteObjectsCommandOutput,
28
+ } from './types';
29
+ import { defaultConfig, parseXmlError } from './base';
30
+
31
+ export type DeleteObjectsInput = Pick<
32
+ DeleteObjectsCommandInput,
33
+ 'Bucket' | 'Delete' | 'ExpectedBucketOwner'
34
+ > & {
35
+ ContentMD5?: string;
36
+ };
37
+
38
+ export type DeleteObjectsOutput = DeleteObjectsCommandOutput;
39
+
40
+ const deleteObjectsSerializer = async (
41
+ input: DeleteObjectsInput,
42
+ endpoint: Endpoint,
43
+ ): Promise<HttpRequest> => {
44
+ const url = new AmplifyUrl(endpoint.url.toString());
45
+ validateS3RequiredParameter(!!input.Delete, 'Delete');
46
+ url.pathname = '/';
47
+ url.search = new AmplifyUrlSearchParams({
48
+ delete: '',
49
+ }).toString();
50
+
51
+ const body = generateDeleteObjectsXml(
52
+ input.Delete!.Objects,
53
+ input.Delete!.Quiet ?? false,
54
+ );
55
+
56
+ const contentMd5 = input.ContentMD5 ?? (await calculateContentMd5(body));
57
+
58
+ const headers = assignStringVariables({
59
+ 'x-amz-expected-bucket-owner': input.ExpectedBucketOwner,
60
+ 'content-type': 'application/xml',
61
+ 'content-md5': contentMd5,
62
+ });
63
+
64
+ const request = {
65
+ method: 'POST',
66
+ headers,
67
+ url,
68
+ body,
69
+ };
70
+
71
+ return request;
72
+ };
73
+
74
+ const deleteObjectsDeserializer = async (
75
+ response: HttpResponse,
76
+ ): Promise<DeleteObjectsOutput> => {
77
+ if (response.statusCode >= 300) {
78
+ const error = await parseXmlError(response);
79
+ throw buildStorageServiceError(error!);
80
+ }
81
+
82
+ const text = await response.body.text();
83
+
84
+ const deleted: { Key?: string }[] = [];
85
+ const errors: { Key?: string; Code?: string; Message?: string }[] = [];
86
+
87
+ const deletedMatches = text.matchAll(/<Deleted>[\s\S]*?<\/Deleted>/g);
88
+ for (const match of deletedMatches) {
89
+ const keyMatch = match[0].match(/<Key>(.*?)<\/Key>/);
90
+ if (keyMatch) {
91
+ deleted.push({ Key: keyMatch[1] });
92
+ }
93
+ }
94
+
95
+ const errorMatches = text.matchAll(/<Error>[\s\S]*?<\/Error>/g);
96
+ for (const match of errorMatches) {
97
+ const keyMatch = match[0].match(/<Key>(.*?)<\/Key>/);
98
+ const codeMatch = match[0].match(/<Code>(.*?)<\/Code>/);
99
+ const messageMatch = match[0].match(/<Message>(.*?)<\/Message>/);
100
+
101
+ errors.push({
102
+ Key: keyMatch?.[1],
103
+ Code: codeMatch?.[1],
104
+ Message: messageMatch?.[1],
105
+ });
106
+ }
107
+
108
+ const result = {
109
+ Deleted: deleted,
110
+ Errors: errors,
111
+ $metadata: parseMetadata(response),
112
+ };
113
+
114
+ return result;
115
+ };
116
+
117
+ export const deleteObjects = composeServiceApi(
118
+ s3TransferHandler,
119
+ deleteObjectsSerializer,
120
+ deleteObjectsDeserializer,
121
+ { ...defaultConfig, responseType: 'text' },
122
+ );
@@ -38,4 +38,9 @@ export {
38
38
  DeleteObjectInput,
39
39
  DeleteObjectOutput,
40
40
  } from './deleteObject';
41
+ export {
42
+ deleteObjects,
43
+ DeleteObjectsInput,
44
+ DeleteObjectsOutput,
45
+ } from './deleteObjects';
41
46
  export { CompletedPart, Part, _Object } from './types';
@@ -5452,4 +5452,24 @@ export type StorageClass = (typeof StorageClass)[keyof typeof StorageClass];
5452
5452
  export type TaggingDirective =
5453
5453
  (typeof TaggingDirective)[keyof typeof TaggingDirective];
5454
5454
 
5455
+ /**
5456
+ * @public
5457
+ */
5458
+ export interface DeleteObjectsCommandInput {
5459
+ Bucket: string;
5460
+ Delete: {
5461
+ Objects: Array<{ Key: string }>;
5462
+ Quiet?: boolean;
5463
+ };
5464
+ ExpectedBucketOwner?: string;
5465
+ }
5466
+
5467
+ /**
5468
+ * @public
5469
+ */
5470
+ export interface DeleteObjectsCommandOutput extends __MetadataBearer {
5471
+ Deleted?: Array<{ Key?: string }>;
5472
+ Errors?: Array<{ Key?: string; Code?: string; Message?: string }>;
5473
+ }
5474
+
5455
5475
  export {};
@@ -0,0 +1,45 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { NonPausableTransferTask } from '../../../types/common';
5
+
6
+ export function createAbortableTask<T>(
7
+ executor: (abortController: AbortController) => Promise<T>,
8
+ ): NonPausableTransferTask<T> & {
9
+ then: Promise<T>['then'];
10
+ catch: Promise<T>['catch'];
11
+ finally: Promise<T>['finally'];
12
+ } {
13
+ const abortController = new AbortController();
14
+ let state: NonPausableTransferTask<T>['state'] = 'IN_PROGRESS';
15
+
16
+ const resultPromise = executor(abortController);
17
+
18
+ const wrappedPromise = resultPromise
19
+ .then(result => {
20
+ state = 'SUCCESS';
21
+
22
+ return result;
23
+ })
24
+ .catch(error => {
25
+ state = abortController.signal.aborted ? 'CANCELED' : 'ERROR';
26
+
27
+ throw error;
28
+ });
29
+
30
+ const operation = {
31
+ result: wrappedPromise,
32
+ cancel: () => {
33
+ abortController.abort();
34
+ state = 'CANCELED';
35
+ },
36
+ get state() {
37
+ return state;
38
+ },
39
+ then: wrappedPromise.then.bind(wrappedPromise),
40
+ catch: wrappedPromise.catch.bind(wrappedPromise),
41
+ finally: wrappedPromise.finally.bind(wrappedPromise),
42
+ };
43
+
44
+ return operation;
45
+ }