@scality/data-browser-library 1.1.9 → 1.1.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 (41) hide show
  1. package/dist/components/__tests__/BucketCorsPage.test.js +14 -6
  2. package/dist/components/__tests__/BucketLifecycleFormPage.test.js +131 -0
  3. package/dist/components/__tests__/BucketNotificationFormPage.test.js +15 -3
  4. package/dist/components/buckets/BucketCorsPage.js +5 -7
  5. package/dist/components/buckets/BucketLifecycleFormPage.js +32 -44
  6. package/dist/components/buckets/BucketLifecycleList.js +8 -4
  7. package/dist/components/buckets/BucketOverview.js +1 -1
  8. package/dist/components/buckets/BucketPolicyPage.js +4 -7
  9. package/dist/components/buckets/BucketReplicationFormPage.js +12 -6
  10. package/dist/components/buckets/BucketReplicationList.js +12 -9
  11. package/dist/components/buckets/BucketVersioning.js +1 -1
  12. package/dist/components/buckets/notifications/BucketNotificationFormPage.js +2 -2
  13. package/dist/components/buckets/notifications/BucketNotificationList.js +1 -1
  14. package/dist/components/objects/DeleteObjectButton.js +1 -1
  15. package/dist/components/objects/GetPresignedUrlButton.js +1 -1
  16. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +1 -1
  17. package/dist/components/objects/ObjectDetails/ObjectSummary.js +2 -2
  18. package/dist/components/objects/ObjectDetails/ObjectTags.js +1 -1
  19. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.js +37 -1
  20. package/dist/components/objects/ObjectLock/ObjectLockSettings.js +1 -1
  21. package/dist/components/objects/__tests__/GetPresignedUrlButton.test.js +30 -1
  22. package/dist/components/providers/QueryProvider.js +2 -1
  23. package/dist/hooks/bucketConfiguration.js +15 -15
  24. package/dist/hooks/bucketOperations.js +1 -1
  25. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +7 -35
  26. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +1 -1
  27. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +1 -1
  28. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +1 -1
  29. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +1 -1
  30. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +2 -2
  31. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +3 -3
  32. package/dist/hooks/factories/useCreateS3MutationHook.js +20 -8
  33. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +1 -1
  34. package/dist/hooks/factories/useCreateS3QueryHook.js +2 -2
  35. package/dist/hooks/objectOperations.js +6 -6
  36. package/dist/hooks/presignedOperations.js +1 -1
  37. package/dist/hooks/useDeleteFolder.js +1 -1
  38. package/dist/test/utils/errorHandling.test.js +45 -33
  39. package/dist/utils/errorHandling.d.ts +2 -1
  40. package/dist/utils/errorHandling.js +8 -7
  41. package/package.json +2 -2
@@ -62,7 +62,7 @@ const GetPresignedUrlButton = ({ bucketName, objectKey, versionId })=>{
62
62
  } catch (error) {
63
63
  showToast({
64
64
  open: true,
65
- message: error instanceof Error ? error.message : 'Failed to generate presigned URL',
65
+ message: error instanceof Error ? error.message : 'Unknown error',
66
66
  status: 'error'
67
67
  });
68
68
  }
@@ -160,7 +160,7 @@ const ObjectMetadata = ({ bucketName, objectKey, versionId })=>{
160
160
  status: 'success'
161
161
  });
162
162
  } catch (error) {
163
- const errorMessage = error instanceof Error ? error.message : 'Failed to save metadata';
163
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
164
164
  showToast({
165
165
  open: true,
166
166
  message: errorMessage,
@@ -106,7 +106,7 @@ const ObjectSummary = ({ bucketName, objectKey, versionId })=>{
106
106
  onError: (error)=>{
107
107
  showToast({
108
108
  open: true,
109
- message: error instanceof Error ? error.message : 'Failed to update legal hold',
109
+ message: error.message,
110
110
  status: 'error'
111
111
  });
112
112
  }
@@ -138,7 +138,7 @@ const ObjectSummary = ({ bucketName, objectKey, versionId })=>{
138
138
  onError: (error)=>{
139
139
  showToast({
140
140
  open: true,
141
- message: error instanceof Error ? error.message : 'Failed to update object visibility',
141
+ message: error.message,
142
142
  status: 'error'
143
143
  });
144
144
  }
@@ -108,7 +108,7 @@ const ObjectTags = ({ bucketName, objectKey, versionId })=>{
108
108
  status: 'success'
109
109
  });
110
110
  } catch (error) {
111
- const errorMessage = error instanceof Error ? error.message : 'Failed to save tags';
111
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
112
112
  showToast({
113
113
  open: true,
114
114
  message: errorMessage,
@@ -6,6 +6,7 @@ import user_event from "@testing-library/user-event";
6
6
  import { DataBrowserUICustomizationProvider } from "../../../../contexts/DataBrowserUICustomizationContext.js";
7
7
  import { useGetPresignedDownload, useGetPublicAccessBlock, useObjectAcl, useObjectLegalHold, useObjectMetadata, useObjectRetention, useSetObjectAcl, useSetObjectLegalHold } from "../../../../hooks/index.js";
8
8
  import { findToggleByLabel } from "../../../../test/testUtils.js";
9
+ import { EnhancedS3Error, ErrorCategory } from "../../../../utils/errorHandling.js";
9
10
  import { ObjectSummary } from "../ObjectSummary.js";
10
11
  jest.mock('../../../../hooks');
11
12
  jest.mock('@scality/core-ui', ()=>{
@@ -663,6 +664,41 @@ describe('ObjectSummary', ()=>{
663
664
  });
664
665
  });
665
666
  });
667
+ it('should show permission message when mutation fails with 403 error', async ()=>{
668
+ const user = user_event.setup();
669
+ const mockShowToast = jest.fn();
670
+ const authError = new EnhancedS3Error("You don't have permission to update legal hold. Contact your administrator.", 'AccessDenied', ErrorCategory.AUTHORIZATION, new Error('Access Denied'), 403);
671
+ const mockMutate = jest.fn((_params, callbacks)=>{
672
+ callbacks.onError(authError);
673
+ });
674
+ mockUseToast.mockReturnValue({
675
+ showToast: mockShowToast
676
+ });
677
+ mockUseObjectRetention.mockReturnValueOnce({
678
+ data: mockRetentionData,
679
+ status: 'success'
680
+ });
681
+ mockUseObjectLegalHold.mockReturnValueOnce({
682
+ data: mockLegalHoldData,
683
+ status: 'success'
684
+ });
685
+ mockUseSetObjectLegalHold.mockReturnValueOnce({
686
+ mutate: mockMutate,
687
+ isPending: false
688
+ });
689
+ renderWithProviders(/*#__PURE__*/ jsx(ObjectSummary, {
690
+ ...defaultProps
691
+ }));
692
+ const toggle = getLegalHoldToggle();
693
+ await user.click(toggle);
694
+ await waitFor(()=>{
695
+ expect(mockShowToast).toHaveBeenCalledWith({
696
+ open: true,
697
+ message: "You don't have permission to update legal hold. Contact your administrator.",
698
+ status: 'error'
699
+ });
700
+ });
701
+ });
666
702
  it('should show generic error message when mutation fails with non-Error object', async ()=>{
667
703
  const user = user_event.setup();
668
704
  const mockShowToast = jest.fn();
@@ -694,7 +730,7 @@ describe('ObjectSummary', ()=>{
694
730
  await waitFor(()=>{
695
731
  expect(mockShowToast).toHaveBeenCalledWith({
696
732
  open: true,
697
- message: 'Failed to update legal hold',
733
+ message: 'Custom error',
698
734
  status: 'error'
699
735
  });
700
736
  });
@@ -102,7 +102,7 @@ function ObjectLockSettings() {
102
102
  navigate(`/buckets/${bucketName}`);
103
103
  },
104
104
  onError: (error)=>{
105
- const errorMessage = error instanceof Error ? error.message : 'Failed to save Object Lock settings';
105
+ const errorMessage = error.message;
106
106
  showToast({
107
107
  open: true,
108
108
  message: errorMessage,
@@ -4,6 +4,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
4
4
  import { cleanup, render, screen, waitFor } from "@testing-library/react";
5
5
  import user_event from "@testing-library/user-event";
6
6
  import { useGetPresignedDownload } from "../../../hooks/index.js";
7
+ import { EnhancedS3Error, ErrorCategory } from "../../../utils/errorHandling.js";
7
8
  import { GetPresignedUrlButton } from "../GetPresignedUrlButton.js";
8
9
  jest.mock('../../../hooks');
9
10
  jest.mock('@scality/core-ui', ()=>{
@@ -462,6 +463,34 @@ describe('GetPresignedUrlButton', ()=>{
462
463
  });
463
464
  });
464
465
  });
466
+ it('should show permission message for 403 errors', async ()=>{
467
+ const mockShowToast = jest.fn();
468
+ mockUseToast.mockReturnValue({
469
+ showToast: mockShowToast
470
+ });
471
+ const authError = new EnhancedS3Error("You don't have permission to generate the presigned URL. Contact your administrator.", 'AccessDenied', ErrorCategory.AUTHORIZATION, new Error('Access Denied'), 403);
472
+ mockUseGetPresignedDownload.mockReturnValue({
473
+ mutateAsync: jest.fn().mockRejectedValue(authError),
474
+ isPending: false
475
+ });
476
+ const user = user_event.setup();
477
+ renderWithProviders(/*#__PURE__*/ jsx(GetPresignedUrlButton, {
478
+ ...defaultProps
479
+ }));
480
+ await user.click(screen.getByRole('button', {
481
+ name: /get pre-signed url/i
482
+ }));
483
+ await user.click(screen.getByRole('button', {
484
+ name: /generate a pre-signed url/i
485
+ }));
486
+ await waitFor(()=>{
487
+ expect(mockShowToast).toHaveBeenCalledWith({
488
+ open: true,
489
+ message: "You don't have permission to generate the presigned URL. Contact your administrator.",
490
+ status: 'error'
491
+ });
492
+ });
493
+ });
465
494
  it('should show generic toast for non-Error failures', async ()=>{
466
495
  const mockShowToast = jest.fn();
467
496
  mockUseToast.mockReturnValue({
@@ -484,7 +513,7 @@ describe('GetPresignedUrlButton', ()=>{
484
513
  await waitFor(()=>{
485
514
  expect(mockShowToast).toHaveBeenCalledWith({
486
515
  open: true,
487
- message: 'Failed to generate presigned URL',
516
+ message: 'Unknown error',
488
517
  status: 'error'
489
518
  });
490
519
  });
@@ -1,11 +1,12 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
3
3
  import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
4
+ import { shouldRetryError } from "../../utils/errorHandling.js";
4
5
  const defaultQueryClient = new QueryClient({
5
6
  defaultOptions: {
6
7
  queries: {
7
8
  staleTime: 300000,
8
- retry: 2
9
+ retry: (failureCount, error)=>shouldRetryError(error, failureCount, 2)
9
10
  }
10
11
  }
11
12
  });
@@ -5,40 +5,40 @@ const useGetBucketAcl = useCreateS3QueryHook(GetBucketAclCommand, 'GetBucketAcl'
5
5
  const useSetBucketAcl = useCreateS3MutationHook(PutBucketAclCommand, 'PutBucketAcl', [
6
6
  'GetBucketAcl',
7
7
  'ListBuckets'
8
- ]);
9
- const useGetBucketPolicy = useCreateS3QueryHook(GetBucketPolicyCommand, 'GetBucketPolicy');
8
+ ], 'update bucket visibility');
9
+ const useGetBucketPolicy = useCreateS3QueryHook(GetBucketPolicyCommand, 'GetBucketPolicy', 'load the bucket policy');
10
10
  const useSetBucketPolicy = useCreateS3MutationHook(PutBucketPolicyCommand, 'PutBucketPolicy', [
11
11
  'GetBucketPolicy',
12
12
  'ListBuckets'
13
- ]);
13
+ ], 'save the bucket policy');
14
14
  const useDeleteBucketPolicy = useCreateS3MutationHook(DeleteBucketPolicyCommand, 'DeleteBucketPolicy', [
15
15
  'GetBucketPolicy'
16
- ]);
16
+ ], 'delete the bucket policy');
17
17
  const useGetBucketVersioning = useCreateS3QueryHook(GetBucketVersioningCommand, 'GetBucketVersioning');
18
18
  const useSetBucketVersioning = useCreateS3MutationHook(PutBucketVersioningCommand, 'PutBucketVersioning', [
19
19
  'GetBucketVersioning'
20
- ]);
21
- const useGetBucketCors = useCreateS3QueryHook(GetBucketCorsCommand, 'GetBucketCors');
20
+ ], 'update bucket versioning');
21
+ const useGetBucketCors = useCreateS3QueryHook(GetBucketCorsCommand, 'GetBucketCors', 'load CORS configuration');
22
22
  const useSetBucketCors = useCreateS3MutationHook(PutBucketCorsCommand, 'PutBucketCors', [
23
23
  'GetBucketCors',
24
24
  'ListBuckets'
25
- ]);
25
+ ], 'save the CORS configuration');
26
26
  const useDeleteBucketCors = useCreateS3MutationHook(DeleteBucketCorsCommand, 'DeleteBucketCors', [
27
27
  'GetBucketCors'
28
- ]);
28
+ ], 'delete the CORS rule');
29
29
  const useGetBucketLifecycle = useCreateS3QueryHook(GetBucketLifecycleConfigurationCommand, 'GetBucketLifecycleConfiguration');
30
30
  const useSetBucketLifecycle = useCreateS3MutationHook(PutBucketLifecycleConfigurationCommand, 'PutBucketLifecycleConfiguration', [
31
31
  'GetBucketLifecycleConfiguration',
32
32
  'ListBuckets'
33
- ]);
33
+ ], 'save the lifecycle rule');
34
34
  const useDeleteBucketLifecycle = useCreateS3MutationHook(DeleteBucketLifecycleCommand, 'DeleteBucketLifecycle', [
35
35
  'GetBucketLifecycleConfiguration'
36
- ]);
37
- const useGetBucketNotification = useCreateS3QueryHook(GetBucketNotificationConfigurationCommand, 'GetBucketNotificationConfiguration');
36
+ ], 'delete the lifecycle rule');
37
+ const useGetBucketNotification = useCreateS3QueryHook(GetBucketNotificationConfigurationCommand, 'GetBucketNotificationConfiguration', 'load the notification configuration');
38
38
  const useSetBucketNotification = useCreateS3MutationHook(PutBucketNotificationConfigurationCommand, 'PutBucketNotificationConfiguration', [
39
39
  'GetBucketNotificationConfiguration',
40
40
  'ListBuckets'
41
- ]);
41
+ ], 'save the notification configuration');
42
42
  const useGetBucketEncryption = useCreateS3QueryHook(GetBucketEncryptionCommand, 'GetBucketEncryption');
43
43
  const useSetBucketEncryption = useCreateS3MutationHook(PutBucketEncryptionCommand, 'PutBucketEncryption', [
44
44
  'GetBucketEncryption',
@@ -55,15 +55,15 @@ const useDeleteBucketTagging = useCreateS3MutationHook(DeleteBucketTaggingComman
55
55
  const useGetBucketObjectLockConfiguration = useCreateS3QueryHook(GetObjectLockConfigurationCommand, 'GetObjectLockConfiguration');
56
56
  const useSetBucketObjectLockConfiguration = useCreateS3MutationHook(PutObjectLockConfigurationCommand, 'PutObjectLockConfiguration', [
57
57
  'GetObjectLockConfiguration'
58
- ]);
58
+ ], 'save Object Lock settings');
59
59
  const useGetBucketReplication = useCreateS3QueryHook(GetBucketReplicationCommand, 'GetBucketReplication');
60
60
  const useSetBucketReplication = useCreateS3MutationHook(PutBucketReplicationCommand, 'PutBucketReplication', [
61
61
  'GetBucketReplication',
62
62
  'ListBuckets'
63
- ]);
63
+ ], 'save the replication rule');
64
64
  const useDeleteBucketReplication = useCreateS3MutationHook(DeleteBucketReplicationCommand, 'DeleteBucketReplication', [
65
65
  'GetBucketReplication'
66
- ]);
66
+ ], 'delete the replication rule');
67
67
  const useGetPublicAccessBlock = useCreateS3QueryHook(GetPublicAccessBlockCommand, 'GetPublicAccessBlock');
68
68
  const usePutPublicAccessBlock = useCreateS3MutationHook(PutPublicAccessBlockCommand, 'PutPublicAccessBlock', [
69
69
  'GetPublicAccessBlock',
@@ -5,7 +5,7 @@ const useBuckets = useCreateS3QueryHook(ListBucketsCommand, 'ListBuckets');
5
5
  const useGetBucketLocation = useCreateS3QueryHook(GetBucketLocationCommand, 'GetBucketLocation');
6
6
  const useCreateBucket = useCreateS3MutationHook(CreateBucketCommand, 'CreateBucket', [
7
7
  'ListBuckets'
8
- ]);
8
+ ], 'create the bucket');
9
9
  const useDeleteBucket = useCreateS3MutationHook(DeleteBucketCommand, 'DeleteBucket', [
10
10
  'ListBuckets'
11
11
  ]);
@@ -61,9 +61,13 @@ describe('useCreateS3FunctionMutationHook - Factory Specific', ()=>{
61
61
  expect(mockOperation).toHaveBeenCalledWith(mockS3Client, inputParams);
62
62
  expect(mockOperation).toHaveBeenCalledTimes(1);
63
63
  });
64
- it('should handle function operation errors', async ()=>{
64
+ it('should handle function operation errors by wrapping with createS3OperationError', async ()=>{
65
65
  const mockError = new Error('Presigned URL generation failed');
66
+ const enhancedError = {
67
+ message: 'Enhanced error'
68
+ };
66
69
  mockOperation.mockRejectedValue(mockError);
70
+ mockCreateS3OperationError.mockReturnValue(enhancedError);
67
71
  const useMutation = useCreateS3FunctionMutationHook(mockOperation);
68
72
  const { result } = renderHook(()=>useMutation(), {
69
73
  wrapper: createTestWrapper()
@@ -75,40 +79,8 @@ describe('useCreateS3FunctionMutationHook - Factory Specific', ()=>{
75
79
  await waitFor(()=>{
76
80
  expect(result.current.isError).toBe(true);
77
81
  });
78
- expect(result.current.error).toBe(mockError);
79
- expect(mockOperation).toHaveBeenCalledWith(mockS3Client, {
80
- Bucket: 'test-bucket',
81
- Key: 'test-key'
82
- });
83
- expect(mockCreateS3OperationError).not.toHaveBeenCalled();
84
- });
85
- it('should handle function operation with internal error wrapping', async ()=>{
86
- const mockInternalError = new Error('Internal operation error');
87
- const mockWrappedError = new Error('Wrapped operation error');
88
- const mockOperationWithErrorHandling = jest.fn().mockImplementation(async ()=>{
89
- try {
90
- throw mockInternalError;
91
- } catch (error) {
92
- const wrappedError = mockWrappedError;
93
- throw wrappedError;
94
- }
95
- });
96
- const useMutation = useCreateS3FunctionMutationHook(mockOperationWithErrorHandling);
97
- const { result } = renderHook(()=>useMutation(), {
98
- wrapper: createTestWrapper()
99
- });
100
- result.current.mutate({
101
- Bucket: 'test-bucket',
102
- Key: 'test-key'
103
- });
104
- await waitFor(()=>{
105
- expect(result.current.isError).toBe(true);
106
- });
107
- expect(result.current.error).toBe(mockWrappedError);
108
- expect(mockOperationWithErrorHandling).toHaveBeenCalledWith(mockS3Client, {
109
- Bucket: 'test-bucket',
110
- Key: 'test-key'
111
- });
82
+ expect(result.current.error).toBe(enhancedError);
83
+ expect(mockCreateS3OperationError).toHaveBeenCalledWith(mockError, 'FunctionMutation', void 0, void 0, void 0);
112
84
  });
113
85
  it('should handle mutation callbacks correctly', async ()=>{
114
86
  const mockResponse = {
@@ -173,7 +173,7 @@ describe('useCreateS3InfiniteQueryHook - Pagination Logic', ()=>{
173
173
  expect(result.current.isError).toBe(true);
174
174
  });
175
175
  expect(result.current.error).toBe(enhancedError);
176
- expect(mockCreateS3OperationError).toHaveBeenCalledWith(mockError, 'ListObjects', 'test-bucket');
176
+ expect(mockCreateS3OperationError).toHaveBeenCalledWith(mockError, 'ListObjects', 'test-bucket', void 0, void 0);
177
177
  });
178
178
  it('should handle fetchNextPage correctly', async ()=>{
179
179
  const mockFirstPage = {
@@ -84,7 +84,7 @@ describe('useCreateS3MutationHook - Factory Specific', ()=>{
84
84
  expect(result.current.isError).toBe(true);
85
85
  });
86
86
  expect(result.current.error).toBe(enhancedError);
87
- expect(mockCreateS3OperationError).toHaveBeenCalledWith(mockError, 'PutObject', 'test-bucket');
87
+ expect(mockCreateS3OperationError).toHaveBeenCalledWith(mockError, 'PutObject', 'test-bucket', void 0, void 0);
88
88
  });
89
89
  it('should handle mutation callbacks correctly', async ()=>{
90
90
  const mockResponse = {
@@ -84,7 +84,7 @@ describe('useCreateS3QueryHook - Factory Specific', ()=>{
84
84
  expect(result.current.isError).toBe(true);
85
85
  });
86
86
  expect(result.current.error).toBe(enhancedError);
87
- expect(mockCreateS3OperationError).toHaveBeenCalledWith(mockError, 'testOperation', 'test-bucket');
87
+ expect(mockCreateS3OperationError).toHaveBeenCalledWith(mockError, 'testOperation', 'test-bucket', void 0, void 0);
88
88
  });
89
89
  it('should handle parameter validation correctly', ()=>{
90
90
  const useTestQuery = useCreateS3QueryHook(MockCommand, 'testOperation');
@@ -10,4 +10,4 @@ import { type EnhancedS3Error } from '../../utils/errorHandling';
10
10
  * - AbortSignal support for cancellation
11
11
  * - Pagination parameters and logic
12
12
  */
13
- export declare function useCreateS3InfiniteQueryHook<TInput extends object, TOutput>(Command: new (input: TInput) => any, operationName: string): (params: TInput, options?: Partial<UseInfiniteQueryOptions<TOutput, EnhancedS3Error, TOutput, (string | TInput)[], string | undefined>>) => UseInfiniteQueryResult<TOutput, EnhancedS3Error>;
13
+ export declare function useCreateS3InfiniteQueryHook<TInput extends object, TOutput>(Command: new (input: TInput) => any, operationName: string, operationLabel?: string): (params: TInput, options?: Partial<UseInfiniteQueryOptions<TOutput, EnhancedS3Error, TOutput, (string | TInput)[], string | undefined>>) => UseInfiniteQueryResult<TOutput, EnhancedS3Error>;
@@ -2,7 +2,7 @@ import { useInfiniteQuery } from "@tanstack/react-query";
2
2
  import { useDataBrowserContext } from "../../components/providers/DataBrowserProvider.js";
3
3
  import { createS3OperationError, shouldRetryError } from "../../utils/errorHandling.js";
4
4
  import { useS3Client } from "../useS3Client.js";
5
- function useCreateS3InfiniteQueryHook(Command, operationName) {
5
+ function useCreateS3InfiniteQueryHook(Command, operationName, operationLabel) {
6
6
  return (params, options)=>{
7
7
  const { s3ConfigIdentifier } = useDataBrowserContext();
8
8
  const s3Client = useS3Client();
@@ -24,7 +24,7 @@ function useCreateS3InfiniteQueryHook(Command, operationName) {
24
24
  return response;
25
25
  } catch (error) {
26
26
  const bucketName = 'Bucket' in params ? params.Bucket : void 0;
27
- throw createS3OperationError(error, operationName, bucketName);
27
+ throw createS3OperationError(error, operationName, bucketName, void 0, operationLabel);
28
28
  }
29
29
  },
30
30
  retry: options?.retry ?? ((failureCount, error)=>shouldRetryError(error, failureCount)),
@@ -1,7 +1,7 @@
1
1
  import type { S3Client } from '@aws-sdk/client-s3';
2
2
  import { type UseMutationOptions, type UseMutationResult } from '@tanstack/react-query';
3
3
  import { type EnhancedS3Error } from '../../utils/errorHandling';
4
- export declare function useCreateS3MutationHook<TInput extends object, TOutput>(Command: new (input: TInput) => any, operationName: string, invalidationKeys?: string[]): (options?: Omit<UseMutationOptions<TOutput, EnhancedS3Error, TInput>, "mutationFn">) => UseMutationResult<TOutput, EnhancedS3Error, TInput>;
5
- export declare function useCreateS3FunctionMutationHook<TInput, TOutput>(operation: (s3Client: S3Client, input: TInput) => Promise<TOutput>, invalidationKeys?: string[]): (options?: Omit<UseMutationOptions<TOutput, EnhancedS3Error, TInput, unknown>, "mutationFn"> | undefined) => UseMutationResult<TOutput, EnhancedS3Error, TInput>;
4
+ export declare function useCreateS3MutationHook<TInput extends object, TOutput>(Command: new (input: TInput) => any, operationName: string, invalidationKeys?: string[], operationLabel?: string): (options?: Omit<UseMutationOptions<TOutput, EnhancedS3Error, TInput>, "mutationFn">) => UseMutationResult<TOutput, EnhancedS3Error, TInput>;
5
+ export declare function useCreateS3FunctionMutationHook<TInput, TOutput>(operation: (s3Client: S3Client, input: TInput) => Promise<TOutput>, invalidationKeys?: string[], operationLabel?: string): (options?: Omit<UseMutationOptions<TOutput, EnhancedS3Error, TInput, unknown>, "mutationFn"> | undefined) => UseMutationResult<TOutput, EnhancedS3Error, TInput>;
6
6
  export type UrlRewriter = (url: string) => string;
7
- export declare function useCreatePresigningMutationHook<TInput, TOutput>(operation: (s3Client: S3Client, input: TInput, rewriteUrl: UrlRewriter) => Promise<TOutput>, invalidationKeys?: string[]): (options?: Omit<UseMutationOptions<TOutput, EnhancedS3Error, TInput>, "mutationFn">) => UseMutationResult<TOutput, EnhancedS3Error, TInput>;
7
+ export declare function useCreatePresigningMutationHook<TInput, TOutput>(operation: (s3Client: S3Client, input: TInput, rewriteUrl: UrlRewriter) => Promise<TOutput>, invalidationKeys?: string[], operationLabel?: string): (options?: Omit<UseMutationOptions<TOutput, EnhancedS3Error, TInput>, "mutationFn">) => UseMutationResult<TOutput, EnhancedS3Error, TInput>;
@@ -3,7 +3,7 @@ import { useDataBrowserContext } from "../../components/providers/DataBrowserPro
3
3
  import { createS3OperationError } from "../../utils/errorHandling.js";
4
4
  import { usePresigningS3Client } from "../usePresigningS3Client.js";
5
5
  import { useS3Client } from "../useS3Client.js";
6
- function useCreateS3MutationHook(Command, operationName, invalidationKeys) {
6
+ function useCreateS3MutationHook(Command, operationName, invalidationKeys, operationLabel) {
7
7
  return (options)=>{
8
8
  const { s3ConfigIdentifier } = useDataBrowserContext();
9
9
  const s3Client = useS3Client();
@@ -15,7 +15,7 @@ function useCreateS3MutationHook(Command, operationName, invalidationKeys) {
15
15
  return await s3Client.send(command);
16
16
  } catch (error) {
17
17
  const bucketName = 'Bucket' in params ? params.Bucket : void 0;
18
- throw createS3OperationError(error, operationName, bucketName);
18
+ throw createS3OperationError(error, operationName, bucketName, void 0, operationLabel);
19
19
  }
20
20
  },
21
21
  onSuccess: (_data, _variables)=>{
@@ -32,13 +32,19 @@ function useCreateS3MutationHook(Command, operationName, invalidationKeys) {
32
32
  });
33
33
  };
34
34
  }
35
- function createFunctionMutationHook(operation, useClient, invalidationKeys) {
35
+ function createFunctionMutationHook(operation, useClient, invalidationKeys, operationLabel) {
36
36
  return (options)=>{
37
37
  const { s3ConfigIdentifier } = useDataBrowserContext();
38
38
  const s3Client = useClient();
39
39
  const queryClient = useQueryClient();
40
40
  return useMutation({
41
- mutationFn: async (params)=>operation(s3Client, params),
41
+ mutationFn: async (params)=>{
42
+ try {
43
+ return await operation(s3Client, params);
44
+ } catch (error) {
45
+ throw createS3OperationError(error, 'FunctionMutation', void 0, void 0, operationLabel);
46
+ }
47
+ },
42
48
  onSuccess: (_data, _variables)=>{
43
49
  if (invalidationKeys) invalidationKeys.forEach((key)=>{
44
50
  queryClient.invalidateQueries({
@@ -53,16 +59,22 @@ function createFunctionMutationHook(operation, useClient, invalidationKeys) {
53
59
  });
54
60
  };
55
61
  }
56
- function useCreateS3FunctionMutationHook(operation, invalidationKeys) {
57
- return createFunctionMutationHook(operation, useS3Client, invalidationKeys);
62
+ function useCreateS3FunctionMutationHook(operation, invalidationKeys, operationLabel) {
63
+ return createFunctionMutationHook(operation, useS3Client, invalidationKeys, operationLabel);
58
64
  }
59
- function useCreatePresigningMutationHook(operation, invalidationKeys) {
65
+ function useCreatePresigningMutationHook(operation, invalidationKeys, operationLabel) {
60
66
  return (options)=>{
61
67
  const { s3ConfigIdentifier } = useDataBrowserContext();
62
68
  const { client, rewriteUrl } = usePresigningS3Client();
63
69
  const queryClient = useQueryClient();
64
70
  return useMutation({
65
- mutationFn: async (params)=>operation(client, params, rewriteUrl),
71
+ mutationFn: async (params)=>{
72
+ try {
73
+ return await operation(client, params, rewriteUrl);
74
+ } catch (error) {
75
+ throw createS3OperationError(error, 'PresigningMutation', void 0, void 0, operationLabel);
76
+ }
77
+ },
66
78
  onSuccess: (_data, _variables)=>{
67
79
  if (invalidationKeys) invalidationKeys.forEach((key)=>{
68
80
  queryClient.invalidateQueries({
@@ -1,4 +1,4 @@
1
1
  import { type QueryKey, type UseQueryOptions, type UseQueryResult } from '@tanstack/react-query';
2
2
  import { type EnhancedS3Error } from '../../utils/errorHandling';
3
3
  export declare function createS3QueryKey(s3ConfigIdentifier: string, operationName: string, params?: object): QueryKey;
4
- export declare function useCreateS3QueryHook<TInput extends object, TOutput>(Command: new (input: TInput) => any, operationName: string): (params?: TInput, options?: Omit<UseQueryOptions<TOutput, EnhancedS3Error, TOutput, QueryKey>, "queryKey" | "queryFn">) => UseQueryResult<TOutput, EnhancedS3Error>;
4
+ export declare function useCreateS3QueryHook<TInput extends object, TOutput>(Command: new (input: TInput) => any, operationName: string, operationLabel?: string): (params?: TInput, options?: Omit<UseQueryOptions<TOutput, EnhancedS3Error, TOutput, QueryKey>, "queryKey" | "queryFn">) => UseQueryResult<TOutput, EnhancedS3Error>;
@@ -28,7 +28,7 @@ function createS3QueryKey(s3ConfigIdentifier, operationName, params) {
28
28
  params
29
29
  ];
30
30
  }
31
- function useCreateS3QueryHook(Command, operationName) {
31
+ function useCreateS3QueryHook(Command, operationName, operationLabel) {
32
32
  return (params, options)=>{
33
33
  const { s3ConfigIdentifier } = useDataBrowserContext();
34
34
  const s3Client = useS3Client();
@@ -47,7 +47,7 @@ function useCreateS3QueryHook(Command, operationName) {
47
47
  const emptyConfig = getEmptyConfigForOperation(operationName);
48
48
  if (null !== emptyConfig) return emptyConfig;
49
49
  }
50
- throw createS3OperationError(error, operationName, bucketName);
50
+ throw createS3OperationError(error, operationName, bucketName, void 0, operationLabel);
51
51
  }
52
52
  },
53
53
  retry: options?.retry ?? ((failureCount, error)=>shouldRetryError(error, failureCount)),
@@ -30,12 +30,12 @@ const useDeleteObjects = useCreateS3MutationHook(DeleteObjectsCommand, 'DeleteOb
30
30
  'ListObjectVersions',
31
31
  'SearchObjects',
32
32
  'SearchObjectsVersions'
33
- ]);
33
+ ], 'delete objects');
34
34
  const useCopyObject = useCreateS3MutationHook(CopyObjectCommand, 'CopyObject', [
35
35
  'ListObjects',
36
36
  'SearchObjects',
37
37
  'HeadObject'
38
- ]);
38
+ ], 'save metadata');
39
39
  const useObjectRetention = useCreateS3QueryHook(GetObjectRetentionCommand, 'GetObjectRetention');
40
40
  const useSetObjectRetention = useCreateS3MutationHook(PutObjectRetentionCommand, 'PutObjectRetention', [
41
41
  'GetObjectRetention'
@@ -44,18 +44,18 @@ const useObjectLegalHold = useCreateS3QueryHook(GetObjectLegalHoldCommand, 'GetO
44
44
  const useSetObjectLegalHold = useCreateS3MutationHook(PutObjectLegalHoldCommand, 'PutObjectLegalHold', [
45
45
  'GetObjectLegalHold',
46
46
  'BatchObjectLegalHold'
47
- ]);
47
+ ], 'update legal hold');
48
48
  const useObjectTagging = useCreateS3QueryHook(GetObjectTaggingCommand, 'GetObjectTagging');
49
49
  const useSetObjectTagging = useCreateS3MutationHook(PutObjectTaggingCommand, 'PutObjectTagging', [
50
50
  'GetObjectTagging'
51
- ]);
51
+ ], 'save tags');
52
52
  const useDeleteObjectTagging = useCreateS3MutationHook(DeleteObjectTaggingCommand, 'DeleteObjectTagging', [
53
53
  'GetObjectTagging'
54
- ]);
54
+ ], 'save tags');
55
55
  const useObjectAcl = useCreateS3QueryHook(GetObjectAclCommand, 'GetObjectAcl');
56
56
  const useSetObjectAcl = useCreateS3MutationHook(PutObjectAclCommand, 'PutObjectAcl', [
57
57
  'GetObjectAcl'
58
- ]);
58
+ ], 'update object visibility');
59
59
  const useGetObjectAttributes = useCreateS3QueryHook(GetObjectAttributesCommand, 'GetObjectAttributes');
60
60
  const useGetObjectTorrent = useCreateS3QueryHook(GetObjectTorrentCommand, 'GetObjectTorrent');
61
61
  const useRestoreObject = useCreateS3MutationHook(RestoreObjectCommand, 'RestoreObject', [
@@ -67,7 +67,7 @@ const generatePresignedPost = async (client, config, rewriteUrl)=>{
67
67
  throw createS3OperationError(error, 'GeneratePresignedPost', config.Bucket, config.Key);
68
68
  }
69
69
  };
70
- const useGetPresignedDownload = useCreatePresigningMutationHook(generatePresignedDownloadUrl);
70
+ const useGetPresignedDownload = useCreatePresigningMutationHook(generatePresignedDownloadUrl, void 0, 'generate the presigned URL');
71
71
  const useGetPresignedUpload = useCreatePresigningMutationHook(generatePresignedUploadUrl);
72
72
  const useGetPresignedPost = useCreatePresigningMutationHook(generatePresignedPost);
73
73
  export { useGetPresignedDownload, useGetPresignedPost, useGetPresignedUpload };
@@ -36,5 +36,5 @@ async function deleteFolder(s3Client, input) {
36
36
  }
37
37
  }
38
38
  }
39
- const useDeleteFolder = useCreateS3FunctionMutationHook(deleteFolder);
39
+ const useDeleteFolder = useCreateS3FunctionMutationHook(deleteFolder, void 0, 'delete the folder');
40
40
  export { useDeleteFolder };