@scality/data-browser-library 1.0.0-preview.11

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 (256) hide show
  1. package/dist/components/Editor.d.ts +12 -0
  2. package/dist/components/Editor.js +28 -0
  3. package/dist/components/__tests__/BucketCreate.test.d.ts +1 -0
  4. package/dist/components/__tests__/BucketCreate.test.js +408 -0
  5. package/dist/components/__tests__/BucketLifecycleFormPage.test.d.ts +1 -0
  6. package/dist/components/__tests__/BucketLifecycleFormPage.test.js +618 -0
  7. package/dist/components/__tests__/BucketLifecycleList.test.d.ts +1 -0
  8. package/dist/components/__tests__/BucketLifecycleList.test.js +325 -0
  9. package/dist/components/__tests__/BucketList.test.d.ts +1 -0
  10. package/dist/components/__tests__/BucketList.test.js +415 -0
  11. package/dist/components/__tests__/BucketNotificationCreatePage.test.d.ts +1 -0
  12. package/dist/components/__tests__/BucketNotificationCreatePage.test.js +316 -0
  13. package/dist/components/__tests__/BucketOverview.test.d.ts +1 -0
  14. package/dist/components/__tests__/BucketOverview.test.js +769 -0
  15. package/dist/components/__tests__/BucketPolicyPage.test.d.ts +1 -0
  16. package/dist/components/__tests__/BucketPolicyPage.test.js +268 -0
  17. package/dist/components/__tests__/BucketReplicationFormPage.test.d.ts +1 -0
  18. package/dist/components/__tests__/BucketReplicationFormPage.test.js +1757 -0
  19. package/dist/components/__tests__/BucketReplicationList.test.d.ts +1 -0
  20. package/dist/components/__tests__/BucketReplicationList.test.js +344 -0
  21. package/dist/components/__tests__/CreateFolderButton.test.d.ts +1 -0
  22. package/dist/components/__tests__/CreateFolderButton.test.js +147 -0
  23. package/dist/components/__tests__/DeleteBucketButton.test.d.ts +1 -0
  24. package/dist/components/__tests__/DeleteBucketButton.test.js +272 -0
  25. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.d.ts +1 -0
  26. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.js +196 -0
  27. package/dist/components/__tests__/DeleteObjectButton.test.d.ts +1 -0
  28. package/dist/components/__tests__/DeleteObjectButton.test.js +302 -0
  29. package/dist/components/__tests__/EmptyBucketButton.test.d.ts +1 -0
  30. package/dist/components/__tests__/EmptyBucketButton.test.js +302 -0
  31. package/dist/components/__tests__/MetadataSearch.test.d.ts +1 -0
  32. package/dist/components/__tests__/MetadataSearch.test.js +201 -0
  33. package/dist/components/__tests__/ObjectList.test.d.ts +1 -0
  34. package/dist/components/__tests__/ObjectList.test.js +283 -0
  35. package/dist/components/__tests__/UploadButton.test.d.ts +1 -0
  36. package/dist/components/__tests__/UploadButton.test.js +144 -0
  37. package/dist/components/buckets/BucketCreate.d.ts +49 -0
  38. package/dist/components/buckets/BucketCreate.js +237 -0
  39. package/dist/components/buckets/BucketDetails.d.ts +1 -0
  40. package/dist/components/buckets/BucketDetails.js +106 -0
  41. package/dist/components/buckets/BucketLifecycleFormPage.d.ts +15 -0
  42. package/dist/components/buckets/BucketLifecycleFormPage.js +1085 -0
  43. package/dist/components/buckets/BucketLifecycleList.d.ts +10 -0
  44. package/dist/components/buckets/BucketLifecycleList.js +270 -0
  45. package/dist/components/buckets/BucketList.d.ts +15 -0
  46. package/dist/components/buckets/BucketList.js +146 -0
  47. package/dist/components/buckets/BucketLocation.d.ts +3 -0
  48. package/dist/components/buckets/BucketLocation.js +16 -0
  49. package/dist/components/buckets/BucketOverview.d.ts +88 -0
  50. package/dist/components/buckets/BucketOverview.js +291 -0
  51. package/dist/components/buckets/BucketPage.d.ts +2 -0
  52. package/dist/components/buckets/BucketPage.js +47 -0
  53. package/dist/components/buckets/BucketPolicyButton.d.ts +7 -0
  54. package/dist/components/buckets/BucketPolicyButton.js +18 -0
  55. package/dist/components/buckets/BucketPolicyPage.d.ts +1 -0
  56. package/dist/components/buckets/BucketPolicyPage.js +236 -0
  57. package/dist/components/buckets/BucketReplicationFormPage.d.ts +1 -0
  58. package/dist/components/buckets/BucketReplicationFormPage.js +834 -0
  59. package/dist/components/buckets/BucketReplicationList.d.ts +11 -0
  60. package/dist/components/buckets/BucketReplicationList.js +189 -0
  61. package/dist/components/buckets/BucketVersioning.d.ts +4 -0
  62. package/dist/components/buckets/BucketVersioning.js +73 -0
  63. package/dist/components/buckets/DeleteBucketButton.d.ts +8 -0
  64. package/dist/components/buckets/DeleteBucketButton.js +78 -0
  65. package/dist/components/buckets/DeleteBucketConfigRuleButton.d.ts +18 -0
  66. package/dist/components/buckets/DeleteBucketConfigRuleButton.js +53 -0
  67. package/dist/components/buckets/EmptyBucketButton.d.ts +5 -0
  68. package/dist/components/buckets/EmptyBucketButton.js +232 -0
  69. package/dist/components/buckets/EmptyBucketSummary.d.ts +9 -0
  70. package/dist/components/buckets/EmptyBucketSummary.js +60 -0
  71. package/dist/components/buckets/EmptyBucketSummaryList.d.ts +13 -0
  72. package/dist/components/buckets/EmptyBucketSummaryList.js +140 -0
  73. package/dist/components/buckets/__tests__/BucketVersioning.test.d.ts +1 -0
  74. package/dist/components/buckets/__tests__/BucketVersioning.test.js +163 -0
  75. package/dist/components/buckets/notifications/BucketNotificationCreatePage.d.ts +1 -0
  76. package/dist/components/buckets/notifications/BucketNotificationCreatePage.js +234 -0
  77. package/dist/components/buckets/notifications/EventsSection.d.ts +1 -0
  78. package/dist/components/buckets/notifications/EventsSection.js +123 -0
  79. package/dist/components/buckets/notifications/events.d.ts +12 -0
  80. package/dist/components/buckets/notifications/events.js +27 -0
  81. package/dist/components/index.d.ts +21 -0
  82. package/dist/components/index.js +22 -0
  83. package/dist/components/layouts/ArrowNavigation.d.ts +4 -0
  84. package/dist/components/layouts/ArrowNavigation.js +16 -0
  85. package/dist/components/layouts/BrowserPageLayout.d.ts +12 -0
  86. package/dist/components/layouts/BrowserPageLayout.js +51 -0
  87. package/dist/components/objects/CreateFolderButton.d.ts +29 -0
  88. package/dist/components/objects/CreateFolderButton.js +118 -0
  89. package/dist/components/objects/DeleteObjectButton.d.ts +8 -0
  90. package/dist/components/objects/DeleteObjectButton.js +191 -0
  91. package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +2 -0
  92. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +356 -0
  93. package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +3 -0
  94. package/dist/components/objects/ObjectDetails/ObjectSummary.js +241 -0
  95. package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +3 -0
  96. package/dist/components/objects/ObjectDetails/ObjectTags.js +272 -0
  97. package/dist/components/objects/ObjectDetails/index.d.ts +9 -0
  98. package/dist/components/objects/ObjectDetails/index.js +75 -0
  99. package/dist/components/objects/ObjectList.d.ts +40 -0
  100. package/dist/components/objects/ObjectList.js +453 -0
  101. package/dist/components/objects/ObjectLock/EditRetentionButton.d.ts +4 -0
  102. package/dist/components/objects/ObjectLock/EditRetentionButton.js +32 -0
  103. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.d.ts +3 -0
  104. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.js +211 -0
  105. package/dist/components/objects/ObjectLock/ObjectLockSettings.d.ts +9 -0
  106. package/dist/components/objects/ObjectLock/ObjectLockSettings.js +158 -0
  107. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.d.ts +8 -0
  108. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.js +39 -0
  109. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.d.ts +1 -0
  110. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.js +204 -0
  111. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.d.ts +1 -0
  112. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.js +374 -0
  113. package/dist/components/objects/ObjectPage.d.ts +1 -0
  114. package/dist/components/objects/ObjectPage.js +45 -0
  115. package/dist/components/objects/UploadButton.d.ts +34 -0
  116. package/dist/components/objects/UploadButton.js +229 -0
  117. package/dist/components/providers/DataBrowserProvider.d.ts +20 -0
  118. package/dist/components/providers/DataBrowserProvider.js +42 -0
  119. package/dist/components/search/MetadataSearch.d.ts +5 -0
  120. package/dist/components/search/MetadataSearch.js +162 -0
  121. package/dist/components/search/SearchHints.d.ts +8 -0
  122. package/dist/components/search/SearchHints.js +21 -0
  123. package/dist/components/ui/ArrayFieldActions.d.ts +36 -0
  124. package/dist/components/ui/ArrayFieldActions.js +43 -0
  125. package/dist/components/ui/ConfirmDeleteRuleModal.d.ts +16 -0
  126. package/dist/components/ui/ConfirmDeleteRuleModal.js +43 -0
  127. package/dist/components/ui/DeleteObjectModalContent.d.ts +5 -0
  128. package/dist/components/ui/DeleteObjectModalContent.js +71 -0
  129. package/dist/components/ui/FilterFormSection.d.ts +44 -0
  130. package/dist/components/ui/FilterFormSection.js +159 -0
  131. package/dist/components/ui/Search.elements.d.ts +17 -0
  132. package/dist/components/ui/Search.elements.js +59 -0
  133. package/dist/components/ui/Table.elements.d.ts +36 -0
  134. package/dist/components/ui/Table.elements.js +87 -0
  135. package/dist/config/factory.d.ts +63 -0
  136. package/dist/config/factory.js +74 -0
  137. package/dist/config/types.d.ts +46 -0
  138. package/dist/config/types.js +0 -0
  139. package/dist/hooks/__tests__/useISVBucketDetection.test.d.ts +1 -0
  140. package/dist/hooks/__tests__/useISVBucketDetection.test.js +188 -0
  141. package/dist/hooks/__tests__/useIsBucketEmpty.test.d.ts +1 -0
  142. package/dist/hooks/__tests__/useIsBucketEmpty.test.js +122 -0
  143. package/dist/hooks/bucketConfiguration.d.ts +168 -0
  144. package/dist/hooks/bucketConfiguration.js +67 -0
  145. package/dist/hooks/bucketOperations.d.ts +36 -0
  146. package/dist/hooks/bucketOperations.js +12 -0
  147. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.d.ts +1 -0
  148. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +276 -0
  149. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.d.ts +1 -0
  150. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +259 -0
  151. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.d.ts +1 -0
  152. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +166 -0
  153. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.d.ts +1 -0
  154. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +200 -0
  155. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.d.ts +1 -0
  156. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +179 -0
  157. package/dist/hooks/factories/index.d.ts +18 -0
  158. package/dist/hooks/factories/index.js +5 -0
  159. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +13 -0
  160. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +76 -0
  161. package/dist/hooks/factories/useCreateS3LoginHook.d.ts +8 -0
  162. package/dist/hooks/factories/useCreateS3LoginHook.js +22 -0
  163. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +5 -0
  164. package/dist/hooks/factories/useCreateS3MutationHook.js +50 -0
  165. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +3 -0
  166. package/dist/hooks/factories/useCreateS3QueryHook.js +51 -0
  167. package/dist/hooks/index.d.ts +13 -0
  168. package/dist/hooks/index.js +13 -0
  169. package/dist/hooks/loginOperations.d.ts +21 -0
  170. package/dist/hooks/loginOperations.js +9 -0
  171. package/dist/hooks/objectOperations.d.ts +190 -0
  172. package/dist/hooks/objectOperations.js +67 -0
  173. package/dist/hooks/presignedOperations.d.ts +73 -0
  174. package/dist/hooks/presignedOperations.js +72 -0
  175. package/dist/hooks/useBatchObjectLegalHold.d.ts +11 -0
  176. package/dist/hooks/useBatchObjectLegalHold.js +45 -0
  177. package/dist/hooks/useDeleteBucketConfigRule.d.ts +26 -0
  178. package/dist/hooks/useDeleteBucketConfigRule.js +46 -0
  179. package/dist/hooks/useEmptyBucket.d.ts +27 -0
  180. package/dist/hooks/useEmptyBucket.js +116 -0
  181. package/dist/hooks/useISVBucketDetection.d.ts +15 -0
  182. package/dist/hooks/useISVBucketDetection.js +27 -0
  183. package/dist/hooks/useIsBucketEmpty.d.ts +7 -0
  184. package/dist/hooks/useIsBucketEmpty.js +36 -0
  185. package/dist/hooks/useLoginMutation.d.ts +21 -0
  186. package/dist/hooks/useLoginMutation.js +9 -0
  187. package/dist/hooks/useS3Client.d.ts +1 -0
  188. package/dist/hooks/useS3Client.js +13 -0
  189. package/dist/hooks/useTableRowSelection.d.ts +9 -0
  190. package/dist/hooks/useTableRowSelection.js +45 -0
  191. package/dist/index.d.ts +6 -0
  192. package/dist/index.js +6 -0
  193. package/dist/schemas/bucketPolicySchema.json +321 -0
  194. package/dist/test/msw/handlers/deleteBucket.d.ts +1 -0
  195. package/dist/test/msw/handlers/deleteBucket.js +14 -0
  196. package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -0
  197. package/dist/test/msw/handlers/getBucketAcl.js +96 -0
  198. package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -0
  199. package/dist/test/msw/handlers/getBucketLocation.js +23 -0
  200. package/dist/test/msw/handlers/getBucketPolicy.d.ts +11 -0
  201. package/dist/test/msw/handlers/getBucketPolicy.js +72 -0
  202. package/dist/test/msw/handlers/headObject.d.ts +1 -0
  203. package/dist/test/msw/handlers/headObject.js +17 -0
  204. package/dist/test/msw/handlers/listBuckets.d.ts +1 -0
  205. package/dist/test/msw/handlers/listBuckets.js +24 -0
  206. package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -0
  207. package/dist/test/msw/handlers/listObjectVersions.js +83 -0
  208. package/dist/test/msw/handlers/listObjects.d.ts +1 -0
  209. package/dist/test/msw/handlers/listObjects.js +66 -0
  210. package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -0
  211. package/dist/test/msw/handlers/objectLegalHold.js +24 -0
  212. package/dist/test/msw/handlers/objectRetention.d.ts +1 -0
  213. package/dist/test/msw/handlers/objectRetention.js +27 -0
  214. package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -0
  215. package/dist/test/msw/handlers/putBucketAcl.js +18 -0
  216. package/dist/test/msw/handlers/putObject.d.ts +1 -0
  217. package/dist/test/msw/handlers/putObject.js +16 -0
  218. package/dist/test/msw/handlers.d.ts +4 -0
  219. package/dist/test/msw/handlers.js +109 -0
  220. package/dist/test/msw/index.d.ts +2 -0
  221. package/dist/test/msw/index.js +3 -0
  222. package/dist/test/msw/server.d.ts +4 -0
  223. package/dist/test/msw/server.js +20 -0
  224. package/dist/test/msw/utils.d.ts +2 -0
  225. package/dist/test/msw/utils.js +13 -0
  226. package/dist/test/setup.d.ts +1 -0
  227. package/dist/test/setup.js +90 -0
  228. package/dist/test/testUtils.d.ts +181 -0
  229. package/dist/test/testUtils.js +310 -0
  230. package/dist/test/utils/errorHandling.test.d.ts +1 -0
  231. package/dist/test/utils/errorHandling.test.js +423 -0
  232. package/dist/types/index.d.ts +51 -0
  233. package/dist/types/index.js +0 -0
  234. package/dist/utils/constants.d.ts +12 -0
  235. package/dist/utils/constants.js +9 -0
  236. package/dist/utils/deletion/index.d.ts +2 -0
  237. package/dist/utils/deletion/index.js +2 -0
  238. package/dist/utils/deletion/messages.d.ts +5 -0
  239. package/dist/utils/deletion/messages.js +29 -0
  240. package/dist/utils/deletion/types.d.ts +11 -0
  241. package/dist/utils/deletion/types.js +0 -0
  242. package/dist/utils/errorHandling.d.ts +63 -0
  243. package/dist/utils/errorHandling.js +84 -0
  244. package/dist/utils/hooks.d.ts +2 -0
  245. package/dist/utils/hooks.js +26 -0
  246. package/dist/utils/index.d.ts +4 -0
  247. package/dist/utils/index.js +4 -0
  248. package/dist/utils/proxyMiddleware.d.ts +18 -0
  249. package/dist/utils/proxyMiddleware.js +56 -0
  250. package/dist/utils/s3Client.d.ts +5 -0
  251. package/dist/utils/s3Client.js +36 -0
  252. package/dist/utils/s3RuleUtils.d.ts +53 -0
  253. package/dist/utils/s3RuleUtils.js +101 -0
  254. package/dist/utils/useFeatures.d.ts +1 -0
  255. package/dist/utils/useFeatures.js +7 -0
  256. package/package.json +84 -0
@@ -0,0 +1,423 @@
1
+ import { EnhancedS3Error, ErrorCategory, createS3Error, createS3OperationError, isEnhancedS3Error, isNotFoundError, isS3ServiceException, shouldRetryError } from "../../utils/errorHandling.js";
2
+ const TEST_CONSTANTS = {
3
+ REQUEST_ID: "test-request-id",
4
+ ATTEMPTS: 1,
5
+ RETRY_DELAY: 0,
6
+ BUCKET: "test-bucket",
7
+ KEY: "test-key",
8
+ MESSAGES: {
9
+ NO_SUCH_BUCKET: "The specified bucket does not exist",
10
+ NO_SUCH_KEY: "The specified key does not exist",
11
+ INVALID_REQUEST: "Invalid request",
12
+ ACCESS_DENIED: "Access denied",
13
+ INTERNAL_ERROR: "Internal error",
14
+ NETWORK_FAILED: "Network connection failed",
15
+ SERVICE_UNAVAILABLE: "Service temporarily unavailable"
16
+ }
17
+ };
18
+ const createMockAWSError = (errorType, message, statusCode = 500)=>{
19
+ const error = new Error(message);
20
+ Object.defineProperty(error, "name", {
21
+ value: errorType,
22
+ writable: true
23
+ });
24
+ error.$metadata = {
25
+ httpStatusCode: statusCode,
26
+ requestId: TEST_CONSTANTS.REQUEST_ID,
27
+ attempts: TEST_CONSTANTS.ATTEMPTS,
28
+ totalRetryDelay: TEST_CONSTANTS.RETRY_DELAY
29
+ };
30
+ return error;
31
+ };
32
+ const TestErrors = {
33
+ noSuchBucket: ()=>createMockAWSError("NoSuchBucket", TEST_CONSTANTS.MESSAGES.NO_SUCH_BUCKET, 404),
34
+ noSuchKey: ()=>createMockAWSError("NoSuchKey", TEST_CONSTANTS.MESSAGES.NO_SUCH_KEY, 404),
35
+ invalidRequest: ()=>createMockAWSError("InvalidRequest", TEST_CONSTANTS.MESSAGES.INVALID_REQUEST, 400),
36
+ accessDenied: ()=>createMockAWSError("AccessDenied", TEST_CONSTANTS.MESSAGES.ACCESS_DENIED, 403),
37
+ internalError: ()=>createMockAWSError("InternalError", TEST_CONSTANTS.MESSAGES.INTERNAL_ERROR, 500),
38
+ serviceUnavailable: ()=>createMockAWSError("ServiceUnavailable", TEST_CONSTANTS.MESSAGES.SERVICE_UNAVAILABLE, 503),
39
+ abortError: ()=>{
40
+ const error = new Error("Operation aborted");
41
+ Object.defineProperty(error, "name", {
42
+ value: "AbortError",
43
+ writable: true
44
+ });
45
+ return error;
46
+ },
47
+ networkError: ()=>new Error(TEST_CONSTANTS.MESSAGES.NETWORK_FAILED),
48
+ timeoutError: ()=>{
49
+ const error = new Error("Request timeout");
50
+ Object.defineProperty(error, "name", {
51
+ value: "TimeoutError",
52
+ writable: true
53
+ });
54
+ return error;
55
+ }
56
+ };
57
+ const TestEnhancedErrors = {
58
+ server: ()=>new EnhancedS3Error("Server error", "ServerError", ErrorCategory.SERVER_ERROR, new Error()),
59
+ network: ()=>new EnhancedS3Error("Network error", "NetworkError", ErrorCategory.NETWORK_ERROR, new Error()),
60
+ client: ()=>new EnhancedS3Error("Client error", "ClientError", ErrorCategory.CLIENT_ERROR, new Error()),
61
+ auth: ()=>new EnhancedS3Error("Auth error", "AuthError", ErrorCategory.AUTHORIZATION, new Error()),
62
+ notFound: ()=>new EnhancedS3Error("Not found", "NotFoundError", ErrorCategory.NOT_FOUND, new Error()),
63
+ cancelled: ()=>new EnhancedS3Error("Cancelled", "CancelError", ErrorCategory.CANCELLATION, new Error()),
64
+ unknown: ()=>new EnhancedS3Error("Unknown", "UnknownError", ErrorCategory.UNKNOWN, new Error())
65
+ };
66
+ describe("ErrorCategory", ()=>{
67
+ test("contains all expected categories", ()=>{
68
+ expect(ErrorCategory.CLIENT_ERROR).toBe("CLIENT_ERROR");
69
+ expect(ErrorCategory.SERVER_ERROR).toBe("SERVER_ERROR");
70
+ expect(ErrorCategory.NETWORK_ERROR).toBe("NETWORK_ERROR");
71
+ expect(ErrorCategory.CANCELLATION).toBe("CANCELLATION");
72
+ expect(ErrorCategory.AUTHORIZATION).toBe("AUTHORIZATION");
73
+ expect(ErrorCategory.NOT_FOUND).toBe("NOT_FOUND");
74
+ expect(ErrorCategory.UNKNOWN).toBe("UNKNOWN");
75
+ });
76
+ });
77
+ describe("EnhancedS3Error", ()=>{
78
+ test("creates error with all properties", ()=>{
79
+ const originalError = new Error("Original error");
80
+ const metadata = {
81
+ httpStatusCode: 400,
82
+ requestId: TEST_CONSTANTS.REQUEST_ID,
83
+ attempts: TEST_CONSTANTS.ATTEMPTS,
84
+ totalRetryDelay: TEST_CONSTANTS.RETRY_DELAY
85
+ };
86
+ const context = {
87
+ operation: "test",
88
+ bucket: TEST_CONSTANTS.BUCKET
89
+ };
90
+ const error = new EnhancedS3Error("Test error", "TestError", ErrorCategory.CLIENT_ERROR, originalError, 400, metadata, context);
91
+ expect(error.message).toBe("Test error");
92
+ expect(error.name).toBe("TestError");
93
+ expect(error.category).toBe(ErrorCategory.CLIENT_ERROR);
94
+ expect(error.statusCode).toBe(400);
95
+ expect(error.metadata).toBe(metadata);
96
+ expect(error.originalError).toBe(originalError);
97
+ expect(error.context).toBe(context);
98
+ expect(error instanceof Error).toBe(true);
99
+ expect(error instanceof EnhancedS3Error).toBe(true);
100
+ });
101
+ describe("shouldRetry", ()=>{
102
+ test("returns true for retryable categories", ()=>{
103
+ expect(TestEnhancedErrors.server().shouldRetry()).toBe(true);
104
+ expect(TestEnhancedErrors.network().shouldRetry()).toBe(true);
105
+ });
106
+ test("returns false for non-retryable categories", ()=>{
107
+ expect(TestEnhancedErrors.client().shouldRetry()).toBe(false);
108
+ expect(TestEnhancedErrors.auth().shouldRetry()).toBe(false);
109
+ expect(TestEnhancedErrors.notFound().shouldRetry()).toBe(false);
110
+ expect(TestEnhancedErrors.cancelled().shouldRetry()).toBe(false);
111
+ expect(TestEnhancedErrors.unknown().shouldRetry()).toBe(false);
112
+ });
113
+ });
114
+ });
115
+ describe("Type Guards", ()=>{
116
+ describe("isS3ServiceException", ()=>{
117
+ test("returns true for S3ServiceException", ()=>{
118
+ expect(isS3ServiceException(TestErrors.invalidRequest())).toBe(true);
119
+ });
120
+ test("returns false for regular Error", ()=>{
121
+ expect(isS3ServiceException(new Error("Regular error"))).toBe(false);
122
+ });
123
+ test("returns false for non-Error objects", ()=>{
124
+ expect(isS3ServiceException("string")).toBe(false);
125
+ expect(isS3ServiceException(null)).toBe(false);
126
+ expect(isS3ServiceException(void 0)).toBe(false);
127
+ expect(isS3ServiceException({})).toBe(false);
128
+ });
129
+ });
130
+ describe("isEnhancedS3Error", ()=>{
131
+ test("returns true for EnhancedS3Error", ()=>{
132
+ expect(isEnhancedS3Error(TestEnhancedErrors.unknown())).toBe(true);
133
+ });
134
+ test("returns false for other error types", ()=>{
135
+ expect(isEnhancedS3Error(new Error("Regular error"))).toBe(false);
136
+ expect(isEnhancedS3Error(TestErrors.invalidRequest())).toBe(false);
137
+ expect(isEnhancedS3Error("string")).toBe(false);
138
+ });
139
+ });
140
+ });
141
+ describe("createS3Error", ()=>{
142
+ test("handles AbortError", ()=>{
143
+ const abortError = TestErrors.abortError();
144
+ const result = createS3Error(abortError);
145
+ expect(result.message).toBe("Operation was cancelled");
146
+ expect(result.name).toBe("AbortError");
147
+ expect(result.category).toBe(ErrorCategory.CANCELLATION);
148
+ expect(result.originalError).toBe(abortError);
149
+ });
150
+ test("handles specific AWS errors", ()=>{
151
+ const testCases = [
152
+ {
153
+ error: TestErrors.noSuchBucket(),
154
+ expectedCategory: ErrorCategory.NOT_FOUND,
155
+ expectedName: "NoSuchBucket",
156
+ expectedStatus: 404
157
+ },
158
+ {
159
+ error: TestErrors.noSuchKey(),
160
+ expectedCategory: ErrorCategory.NOT_FOUND,
161
+ expectedName: "NoSuchKey",
162
+ expectedStatus: 404
163
+ },
164
+ {
165
+ error: TestErrors.invalidRequest(),
166
+ expectedCategory: ErrorCategory.CLIENT_ERROR,
167
+ expectedName: "InvalidRequest",
168
+ expectedStatus: 400
169
+ }
170
+ ];
171
+ testCases.forEach(({ error, expectedCategory, expectedName, expectedStatus })=>{
172
+ const result = createS3Error(error);
173
+ expect(result.category).toBe(expectedCategory);
174
+ expect(result.name).toBe(expectedName);
175
+ expect(result.statusCode).toBe(expectedStatus);
176
+ expect(result.metadata).toBe(error.$metadata);
177
+ });
178
+ });
179
+ test("handles status code classification", ()=>{
180
+ const testCases = [
181
+ {
182
+ error: TestErrors.accessDenied(),
183
+ expectedCategory: ErrorCategory.AUTHORIZATION
184
+ },
185
+ {
186
+ error: TestErrors.internalError(),
187
+ expectedCategory: ErrorCategory.SERVER_ERROR
188
+ }
189
+ ];
190
+ testCases.forEach(({ error, expectedCategory })=>{
191
+ const result = createS3Error(error);
192
+ expect(result.category).toBe(expectedCategory);
193
+ });
194
+ });
195
+ test("handles network errors", ()=>{
196
+ const testCases = [
197
+ TestErrors.networkError(),
198
+ TestErrors.timeoutError()
199
+ ];
200
+ testCases.forEach((error)=>{
201
+ const result = createS3Error(error);
202
+ expect(result.category).toBe(ErrorCategory.NETWORK_ERROR);
203
+ });
204
+ });
205
+ test("handles edge cases", ()=>{
206
+ const testCases = [
207
+ {
208
+ input: new Error("Some error"),
209
+ expectedCategory: ErrorCategory.UNKNOWN,
210
+ expectedMessage: "Some error"
211
+ },
212
+ {
213
+ input: "String error",
214
+ expectedCategory: ErrorCategory.UNKNOWN,
215
+ expectedMessage: "String error",
216
+ expectedName: "UnknownError"
217
+ },
218
+ {
219
+ input: null,
220
+ expectedCategory: ErrorCategory.UNKNOWN,
221
+ expectedMessage: "Unknown error occurred"
222
+ },
223
+ {
224
+ input: void 0,
225
+ expectedCategory: ErrorCategory.UNKNOWN,
226
+ expectedMessage: "Unknown error occurred"
227
+ }
228
+ ];
229
+ testCases.forEach(({ input, expectedCategory, expectedMessage, expectedName })=>{
230
+ const result = createS3Error(input);
231
+ expect(result.category).toBe(expectedCategory);
232
+ expect(result.message).toBe(expectedMessage);
233
+ if (expectedName) expect(result.name).toBe(expectedName);
234
+ });
235
+ });
236
+ test("preserves context", ()=>{
237
+ const context = {
238
+ operation: "test",
239
+ bucket: TEST_CONSTANTS.BUCKET
240
+ };
241
+ const result = createS3Error(new Error("Test error"), context);
242
+ expect(result.context).toBe(context);
243
+ });
244
+ });
245
+ describe("createS3OperationError", ()=>{
246
+ test("message modification scenarios", ()=>{
247
+ const testCases = [
248
+ {
249
+ name: "preserves existing operation in message",
250
+ error: new Error("ListObjectsV2 failed: Access denied"),
251
+ operation: "ListObjectsV2",
252
+ bucket: TEST_CONSTANTS.BUCKET,
253
+ expectedMessage: "ListObjectsV2 failed: Access denied"
254
+ },
255
+ {
256
+ name: "enhances message with operation context",
257
+ error: new Error(TEST_CONSTANTS.MESSAGES.ACCESS_DENIED),
258
+ operation: "GetObject",
259
+ bucket: TEST_CONSTANTS.BUCKET,
260
+ key: TEST_CONSTANTS.KEY,
261
+ expectedMessage: `GetObject failed for bucket '${TEST_CONSTANTS.BUCKET}', key '${TEST_CONSTANTS.KEY}': ${TEST_CONSTANTS.MESSAGES.ACCESS_DENIED}`
262
+ },
263
+ {
264
+ name: "handles operation without bucket",
265
+ error: new Error(TEST_CONSTANTS.MESSAGES.SERVICE_UNAVAILABLE),
266
+ operation: "ListBuckets",
267
+ expectedMessage: `ListBuckets failed: ${TEST_CONSTANTS.MESSAGES.SERVICE_UNAVAILABLE}`
268
+ }
269
+ ];
270
+ testCases.forEach(({ error, operation, bucket, key, expectedMessage })=>{
271
+ const result = createS3OperationError(error, operation, bucket, key);
272
+ expect(result.message).toBe(expectedMessage);
273
+ expect(result.context).toEqual({
274
+ operation,
275
+ bucketName: bucket || void 0,
276
+ objectKey: key || void 0,
277
+ timestamp: expect.any(String)
278
+ });
279
+ });
280
+ });
281
+ test("preserves all error properties", ()=>{
282
+ const originalError = TestErrors.noSuchBucket();
283
+ const result = createS3OperationError(originalError, "HeadObject", TEST_CONSTANTS.BUCKET, TEST_CONSTANTS.KEY);
284
+ expect(result.category).toBe(ErrorCategory.NOT_FOUND);
285
+ expect(result.statusCode).toBe(404);
286
+ expect(result.metadata).toBe(originalError.$metadata);
287
+ expect(result.originalError).toBe(originalError);
288
+ });
289
+ });
290
+ describe("shouldRetryError", ()=>{
291
+ test("respects maxRetries limit", ()=>{
292
+ const retryableError = TestEnhancedErrors.server();
293
+ const maxRetries = 3;
294
+ expect(shouldRetryError(retryableError, 0, maxRetries)).toBe(true);
295
+ expect(shouldRetryError(retryableError, 2, maxRetries)).toBe(true);
296
+ expect(shouldRetryError(retryableError, 3, maxRetries)).toBe(false);
297
+ expect(shouldRetryError(retryableError, 5, maxRetries)).toBe(false);
298
+ });
299
+ test("uses error category for retry decision", ()=>{
300
+ const testCases = [
301
+ {
302
+ error: TestEnhancedErrors.server(),
303
+ shouldRetry: true
304
+ },
305
+ {
306
+ error: TestEnhancedErrors.network(),
307
+ shouldRetry: true
308
+ },
309
+ {
310
+ error: TestEnhancedErrors.client(),
311
+ shouldRetry: false
312
+ },
313
+ {
314
+ error: TestEnhancedErrors.auth(),
315
+ shouldRetry: false
316
+ }
317
+ ];
318
+ testCases.forEach(({ error, shouldRetry })=>{
319
+ expect(shouldRetryError(error, 0)).toBe(shouldRetry);
320
+ });
321
+ });
322
+ test("converts and retries AWS errors", ()=>{
323
+ const testCases = [
324
+ {
325
+ error: TestErrors.internalError(),
326
+ shouldRetry: true
327
+ },
328
+ {
329
+ error: TestErrors.invalidRequest(),
330
+ shouldRetry: false
331
+ }
332
+ ];
333
+ testCases.forEach(({ error, shouldRetry })=>{
334
+ expect(shouldRetryError(error, 0)).toBe(shouldRetry);
335
+ });
336
+ });
337
+ test("uses default maxRetries of 3", ()=>{
338
+ const retryableError = TestEnhancedErrors.server();
339
+ expect(shouldRetryError(retryableError, 0)).toBe(true);
340
+ expect(shouldRetryError(retryableError, 3)).toBe(false);
341
+ });
342
+ });
343
+ describe("isNotFoundError", ()=>{
344
+ test("returns true for NOT_FOUND category errors", ()=>{
345
+ expect(isNotFoundError(TestEnhancedErrors.notFound())).toBe(true);
346
+ });
347
+ test("returns true for AWS NOT_FOUND errors", ()=>{
348
+ expect(isNotFoundError(TestErrors.noSuchBucket())).toBe(true);
349
+ expect(isNotFoundError(TestErrors.noSuchKey())).toBe(true);
350
+ });
351
+ test("returns true for 404 status code errors", ()=>{
352
+ const error404 = createMockAWSError("NoSuchLifecycleConfiguration", "The lifecycle configuration does not exist", 404);
353
+ expect(isNotFoundError(error404)).toBe(true);
354
+ });
355
+ test("returns false for other error categories", ()=>{
356
+ expect(isNotFoundError(TestEnhancedErrors.server())).toBe(false);
357
+ expect(isNotFoundError(TestEnhancedErrors.network())).toBe(false);
358
+ expect(isNotFoundError(TestEnhancedErrors.client())).toBe(false);
359
+ expect(isNotFoundError(TestEnhancedErrors.auth())).toBe(false);
360
+ expect(isNotFoundError(TestEnhancedErrors.cancelled())).toBe(false);
361
+ expect(isNotFoundError(TestEnhancedErrors.unknown())).toBe(false);
362
+ });
363
+ test("returns false for non-404 AWS errors", ()=>{
364
+ expect(isNotFoundError(TestErrors.invalidRequest())).toBe(false);
365
+ expect(isNotFoundError(TestErrors.accessDenied())).toBe(false);
366
+ expect(isNotFoundError(TestErrors.internalError())).toBe(false);
367
+ });
368
+ test("handles edge cases", ()=>{
369
+ expect(isNotFoundError(null)).toBe(false);
370
+ expect(isNotFoundError(void 0)).toBe(false);
371
+ expect(isNotFoundError("string")).toBe(false);
372
+ expect(isNotFoundError({})).toBe(false);
373
+ expect(isNotFoundError(new Error("Regular error"))).toBe(false);
374
+ });
375
+ test("works with any error type by converting to EnhancedS3Error", ()=>{
376
+ const regularError = new Error("Some error");
377
+ const result = isNotFoundError(regularError);
378
+ expect(result).toBe(false);
379
+ });
380
+ });
381
+ describe("Integration Tests", ()=>{
382
+ test("complete error processing workflow", ()=>{
383
+ const testCases = [
384
+ {
385
+ name: "NoSuchBucket - non-retryable",
386
+ originalError: TestErrors.noSuchBucket(),
387
+ operation: "ListObjectsV2",
388
+ bucket: TEST_CONSTANTS.BUCKET,
389
+ expectedCategory: ErrorCategory.NOT_FOUND,
390
+ shouldRetry: false
391
+ },
392
+ {
393
+ name: "Server error - retryable",
394
+ originalError: TestErrors.serviceUnavailable(),
395
+ operation: "PutObject",
396
+ bucket: TEST_CONSTANTS.BUCKET,
397
+ key: TEST_CONSTANTS.KEY,
398
+ expectedCategory: ErrorCategory.SERVER_ERROR,
399
+ shouldRetry: true
400
+ }
401
+ ];
402
+ testCases.forEach(({ originalError, operation, bucket, key, expectedCategory, shouldRetry })=>{
403
+ const operationError = createS3OperationError(originalError, operation, bucket, key);
404
+ expect(operationError.category).toBe(expectedCategory);
405
+ expect(operationError.shouldRetry()).toBe(shouldRetry);
406
+ expect(isEnhancedS3Error(operationError)).toBe(true);
407
+ expect(shouldRetryError(operationError, 0)).toBe(shouldRetry);
408
+ expect(shouldRetryError(operationError, 3)).toBe(false);
409
+ });
410
+ });
411
+ test("retry attempt progression", ()=>{
412
+ const serverError = TestErrors.serviceUnavailable();
413
+ const operationError = createS3OperationError(serverError, "PutObject", TEST_CONSTANTS.BUCKET, TEST_CONSTANTS.KEY);
414
+ [
415
+ 0,
416
+ 1,
417
+ 2
418
+ ].forEach((attempt)=>{
419
+ expect(shouldRetryError(operationError, attempt)).toBe(true);
420
+ });
421
+ expect(shouldRetryError(operationError, 3)).toBe(false);
422
+ });
423
+ });
@@ -0,0 +1,51 @@
1
+ import { S3ClientConfig } from "@aws-sdk/client-s3";
2
+ import type { AwsCredentialIdentity } from "@aws-sdk/types";
3
+ export type { CreateBucketCommandInput, CreateBucketCommandOutput, DeleteBucketCommandInput, DeleteBucketCommandOutput, ListBucketsCommandOutput, GetBucketLocationCommandInput, GetBucketLocationCommandOutput, PutBucketTaggingCommandInput, PutBucketTaggingCommandOutput, GetBucketTaggingCommandOutput, DeleteBucketTaggingCommandOutput, PutBucketPolicyCommandInput, GetBucketPolicyCommandOutput, DeleteBucketPolicyCommandOutput, PutBucketVersioningCommandInput, GetBucketVersioningCommandOutput, PutBucketCorsCommandInput, GetBucketCorsCommandOutput, DeleteBucketCorsCommandOutput, PutBucketLifecycleConfigurationCommandInput, GetBucketLifecycleConfigurationCommandOutput, DeleteBucketLifecycleCommandOutput, PutBucketEncryptionCommandInput, GetBucketEncryptionCommandOutput, PutBucketAclCommandInput, GetBucketAclCommandOutput, PutBucketNotificationConfigurationCommandInput, GetBucketNotificationConfigurationCommandOutput, PutObjectLockConfigurationCommandInput, GetObjectLockConfigurationCommandOutput, PutBucketReplicationCommandInput, GetBucketReplicationCommandOutput, DeleteBucketReplicationCommandOutput, PutObjectCommandInput, PutObjectCommandOutput, GetObjectCommandInput, GetObjectCommandOutput, HeadObjectCommandInput, HeadObjectCommandOutput, DeleteObjectCommandInput, DeleteObjectCommandOutput, DeleteObjectsCommandInput, DeleteObjectsCommandOutput, CopyObjectCommandInput, CopyObjectCommandOutput, ListObjectsV2CommandInput, ListObjectsV2CommandOutput, ListObjectVersionsCommandInput, ListObjectVersionsCommandOutput, PutObjectRetentionCommandInput, GetObjectRetentionCommandOutput, PutObjectLegalHoldCommandInput, GetObjectLegalHoldCommandOutput, PutObjectTaggingCommandInput, GetObjectTaggingCommandOutput, DeleteObjectTaggingCommandOutput, PutObjectAclCommandInput, GetObjectAclCommandOutput, GetObjectAttributesCommandInput, GetObjectAttributesCommandOutput, GetObjectTorrentCommandOutput, RestoreObjectCommandInput, RestoreObjectCommandOutput, SelectObjectContentCommandInput, SelectObjectContentCommandOutput, ListMultipartUploadsCommandInput, ListMultipartUploadsCommandOutput, BucketLocationConstraint, ObjectCannedACL, BucketCannedACL, } from "@aws-sdk/client-s3";
4
+ export interface S3BrowserConfig extends Omit<S3ClientConfig, "credentials"> {
5
+ endpoint?: string;
6
+ region: string;
7
+ forcePathStyle?: boolean;
8
+ useDevProxy?: boolean;
9
+ realS3Host?: string;
10
+ proxyPath?: string;
11
+ proxyHost?: string;
12
+ proxyPort?: number;
13
+ publicAclIndicator?: string;
14
+ }
15
+ export interface S3Credentials extends AwsCredentialIdentity {
16
+ roleArn?: string;
17
+ features?: string[];
18
+ }
19
+ export type GetConfigFunction = () => S3BrowserConfig & {
20
+ credentials: S3Credentials;
21
+ };
22
+ export interface ObjectInfo {
23
+ key: string;
24
+ size?: number;
25
+ lastModified?: Date;
26
+ etag?: string;
27
+ storageClass?: string;
28
+ owner?: {
29
+ displayName?: string;
30
+ id?: string;
31
+ };
32
+ }
33
+ export interface ObjectVersion extends ObjectInfo {
34
+ versionId: string;
35
+ isLatest: boolean;
36
+ isDeleteMarker?: boolean;
37
+ }
38
+ export interface CommonPrefix {
39
+ prefix: string;
40
+ }
41
+ export interface ListObjectsResult {
42
+ objects: ObjectInfo[];
43
+ commonPrefixes: CommonPrefix[];
44
+ nextContinuationToken?: string;
45
+ isTruncated: boolean;
46
+ }
47
+ export type S3ErrorCode = "AccessDenied" | "NoSuchBucket" | "NoSuchKey" | "InvalidBucketName" | "BucketNotFound" | "NetworkError" | "UnknownError";
48
+ export interface S3Error extends Error {
49
+ code?: S3ErrorCode;
50
+ statusCode?: number;
51
+ }
File without changes
@@ -0,0 +1,12 @@
1
+ export declare const BUCKET_TAG_VEEAM_APPLICATION = "X-Scality-Veeam-Application";
2
+ export declare const BUCKET_TAG_APPLICATION = "X-Scality-Application";
3
+ export declare const VEEAM_BACKUP_REPLICATION = "Veeam Backup & Replication";
4
+ export declare const VEEAM_IMMUTABLE_POLICY_NAME = "Scality-Veeam-Immutable-Policy";
5
+ /** Generic identifier for Veeam Backup for Microsoft 365 (VBO) */
6
+ export declare const VEEAM_VBO_APPLICATION = "Veeam Backup for Microsoft 365";
7
+ /** Generic identifier for Veeam Backup for Microsoft 365 (v6, v7) */
8
+ export declare const VEEAM_OFFICE_365 = "Veeam Backup for Microsoft 365 (v6, v7)";
9
+ /** Generic identifier for Veeam Backup for Microsoft 365 (v8+) */
10
+ export declare const VEEAM_OFFICE_365_V8 = "Veeam Backup for Microsoft 365 (v8+)";
11
+ /** Generic identifier for Commvault */
12
+ export declare const COMMVAULT_APPLICATION = "Commvault";
@@ -0,0 +1,9 @@
1
+ const BUCKET_TAG_VEEAM_APPLICATION = "X-Scality-Veeam-Application";
2
+ const BUCKET_TAG_APPLICATION = "X-Scality-Application";
3
+ const VEEAM_BACKUP_REPLICATION = "Veeam Backup & Replication";
4
+ const VEEAM_IMMUTABLE_POLICY_NAME = "Scality-Veeam-Immutable-Policy";
5
+ const VEEAM_VBO_APPLICATION = "Veeam Backup for Microsoft 365";
6
+ const VEEAM_OFFICE_365 = "Veeam Backup for Microsoft 365 (v6, v7)";
7
+ const VEEAM_OFFICE_365_V8 = "Veeam Backup for Microsoft 365 (v8+)";
8
+ const COMMVAULT_APPLICATION = "Commvault";
9
+ export { BUCKET_TAG_APPLICATION, BUCKET_TAG_VEEAM_APPLICATION, COMMVAULT_APPLICATION, VEEAM_BACKUP_REPLICATION, VEEAM_IMMUTABLE_POLICY_NAME, VEEAM_OFFICE_365, VEEAM_OFFICE_365_V8, VEEAM_VBO_APPLICATION };
@@ -0,0 +1,2 @@
1
+ export * from "./types";
2
+ export * from "./messages";
@@ -0,0 +1,2 @@
1
+ export * from "./types.js";
2
+ export * from "./messages.js";
@@ -0,0 +1,5 @@
1
+ import { DeletionContext, DeletionResult } from "./types";
2
+ /**
3
+ * Determines deletion behavior based on bucket versioning
4
+ */
5
+ export declare const getDeletionMessages: (context: DeletionContext) => DeletionResult;
@@ -0,0 +1,29 @@
1
+ const maybePluralize = (count, word, suffix = "s", includeCount = true)=>{
2
+ const pluralWord = 1 === count ? word : `${word}${suffix}`;
3
+ return includeCount ? `${count} ${pluralWord}` : pluralWord;
4
+ };
5
+ const getDeletionMessages = (context)=>{
6
+ const { numberOfObjects, selectedObjectsAreSpecificVersions, isBucketVersioned } = context;
7
+ if (!isBucketVersioned) return createNonVersionedDeletionResult(numberOfObjects);
8
+ if (!selectedObjectsAreSpecificVersions) return createDefaultVersionDeletionResult(numberOfObjects);
9
+ return createSpecificVersionDeletionResult(numberOfObjects);
10
+ };
11
+ const createNonVersionedDeletionResult = (numberOfObjects)=>({
12
+ info: `The selected ${maybePluralize(numberOfObjects, "object", "s", false)} will be permanently deleted.`,
13
+ checkboxRequired: true,
14
+ confirmationRequired: false,
15
+ isDeletionPossible: true
16
+ });
17
+ const createDefaultVersionDeletionResult = (numberOfObjects)=>({
18
+ info: `${1 === numberOfObjects ? "A delete marker" : "Delete markers"} will be added to the ${maybePluralize(numberOfObjects, "object", "s", false)}.`,
19
+ checkboxRequired: false,
20
+ confirmationRequired: false,
21
+ isDeletionPossible: true
22
+ });
23
+ const createSpecificVersionDeletionResult = (numberOfObjects)=>({
24
+ info: `The selected ${maybePluralize(numberOfObjects, "version", "s", false)} will be permanently deleted.`,
25
+ checkboxRequired: true,
26
+ confirmationRequired: false,
27
+ isDeletionPossible: true
28
+ });
29
+ export { getDeletionMessages };
@@ -0,0 +1,11 @@
1
+ export interface DeletionContext {
2
+ numberOfObjects: number;
3
+ selectedObjectsAreSpecificVersions: boolean;
4
+ isBucketVersioned: boolean;
5
+ }
6
+ export interface DeletionResult {
7
+ info: string;
8
+ checkboxRequired: boolean;
9
+ confirmationRequired: boolean;
10
+ isDeletionPossible: boolean;
11
+ }
File without changes
@@ -0,0 +1,63 @@
1
+ import { S3ServiceException } from "@aws-sdk/client-s3";
2
+ /**
3
+ * Business-level error categories for S3 operations.
4
+ * Used to determine retry strategy and user messaging.
5
+ */
6
+ export declare enum ErrorCategory {
7
+ CLIENT_ERROR = "CLIENT_ERROR",// 4xx errors - don't retry
8
+ SERVER_ERROR = "SERVER_ERROR",// 5xx errors - can retry
9
+ NETWORK_ERROR = "NETWORK_ERROR",// Network issues - can retry
10
+ CANCELLATION = "CANCELLATION",// User cancelled - don't retry
11
+ AUTHORIZATION = "AUTHORIZATION",// Permission issues - don't retry
12
+ NOT_FOUND = "NOT_FOUND",// Resource doesn't exist - don't retry
13
+ UNKNOWN = "UNKNOWN"
14
+ }
15
+ /**
16
+ * Enhanced S3 error with business categorization and AWS metadata preservation.
17
+ * Extends standard Error with retry logic and operation context.
18
+ */
19
+ export declare class EnhancedS3Error extends Error {
20
+ readonly category: ErrorCategory;
21
+ readonly statusCode?: number;
22
+ readonly metadata?: S3ServiceException["$metadata"];
23
+ readonly originalError: Error;
24
+ readonly context?: Record<string, unknown>;
25
+ constructor(message: string, name: string, category: ErrorCategory, originalError: Error, statusCode?: number, metadata?: S3ServiceException["$metadata"], context?: Record<string, unknown>);
26
+ /**
27
+ * Determines if this error should be retried based on its category.
28
+ * Only server errors and network issues are retryable.
29
+ */
30
+ shouldRetry(): boolean;
31
+ }
32
+ /**
33
+ * Type guard to check if an error is an AWS S3 service exception.
34
+ */
35
+ export declare function isS3ServiceException(error: unknown): error is S3ServiceException;
36
+ /**
37
+ * Type guard to check if an error is our enhanced S3 error.
38
+ */
39
+ export declare function isEnhancedS3Error(error: unknown): error is EnhancedS3Error;
40
+ /**
41
+ * Converts any error into an EnhancedS3Error with proper categorization.
42
+ * Uses official AWS SDK error types for type-safe error classification.
43
+ */
44
+ export declare function createS3Error(error: unknown, context?: Record<string, unknown>): EnhancedS3Error;
45
+ /**
46
+ * Creates an enhanced S3 error with operation context and enriched error messages.
47
+ * Automatically adds operation details to error messages for better debugging.
48
+ */
49
+ export declare function createS3OperationError(error: unknown, operation: string, bucketName?: string, objectKey?: string): EnhancedS3Error;
50
+ /**
51
+ * Determines whether an error should be retried based on its classification.
52
+ * Implements unified retry policy for all S3 operations.
53
+ */
54
+ export declare function shouldRetryError(error: unknown, failureCount: number, maxRetries?: number): boolean;
55
+ /**
56
+ * Checks if an error indicates that a resource was not found (404).
57
+ * This is useful for distinguishing between "resource doesn't exist" (normal state)
58
+ * and actual errors (permissions, network issues, etc.).
59
+ *
60
+ * @param error - The error to check
61
+ * @returns true if the error category is NOT_FOUND
62
+ */
63
+ export declare function isNotFoundError(error: unknown): boolean;