@scality/data-browser-library 1.0.0-preview.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Editor.d.ts +12 -0
- package/dist/components/Editor.js +28 -0
- package/dist/components/__tests__/BucketList.test.d.ts +1 -0
- package/dist/components/__tests__/BucketList.test.js +225 -0
- package/dist/components/__tests__/BucketOverview.test.d.ts +1 -0
- package/dist/components/__tests__/BucketOverview.test.js +479 -0
- package/dist/components/__tests__/BucketPolicyPage.test.d.ts +1 -0
- package/dist/components/__tests__/BucketPolicyPage.test.js +213 -0
- package/dist/components/__tests__/CreateFolderButton.test.d.ts +1 -0
- package/dist/components/__tests__/CreateFolderButton.test.js +147 -0
- package/dist/components/__tests__/DeleteBucketButton.test.d.ts +1 -0
- package/dist/components/__tests__/DeleteBucketButton.test.js +272 -0
- package/dist/components/__tests__/DeleteObjectButton.test.d.ts +1 -0
- package/dist/components/__tests__/DeleteObjectButton.test.js +302 -0
- package/dist/components/__tests__/MetadataSearch.test.d.ts +1 -0
- package/dist/components/__tests__/MetadataSearch.test.js +201 -0
- package/dist/components/__tests__/ObjectList.test.d.ts +1 -0
- package/dist/components/__tests__/ObjectList.test.js +283 -0
- package/dist/components/__tests__/UploadButton.test.d.ts +1 -0
- package/dist/components/__tests__/UploadButton.test.js +144 -0
- package/dist/components/buckets/BucketDetails.d.ts +1 -0
- package/dist/components/buckets/BucketDetails.js +51 -0
- package/dist/components/buckets/BucketList.d.ts +12 -0
- package/dist/components/buckets/BucketList.js +136 -0
- package/dist/components/buckets/BucketLocation.d.ts +3 -0
- package/dist/components/buckets/BucketLocation.js +16 -0
- package/dist/components/buckets/BucketOverview.d.ts +14 -0
- package/dist/components/buckets/BucketOverview.js +209 -0
- package/dist/components/buckets/BucketPage.d.ts +2 -0
- package/dist/components/buckets/BucketPage.js +47 -0
- package/dist/components/buckets/BucketPolicyButton.d.ts +7 -0
- package/dist/components/buckets/BucketPolicyButton.js +18 -0
- package/dist/components/buckets/BucketPolicyPage.d.ts +1 -0
- package/dist/components/buckets/BucketPolicyPage.js +205 -0
- package/dist/components/buckets/DeleteBucketButton.d.ts +8 -0
- package/dist/components/buckets/DeleteBucketButton.js +78 -0
- package/dist/components/index.d.ts +12 -0
- package/dist/components/index.js +13 -0
- package/dist/components/layouts/BrowserPageLayout.d.ts +9 -0
- package/dist/components/layouts/BrowserPageLayout.js +46 -0
- package/dist/components/objects/CreateFolderButton.d.ts +29 -0
- package/dist/components/objects/CreateFolderButton.js +118 -0
- package/dist/components/objects/DeleteObjectButton.d.ts +8 -0
- package/dist/components/objects/DeleteObjectButton.js +191 -0
- package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +2 -0
- package/dist/components/objects/ObjectDetails/ObjectMetadata.js +323 -0
- package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +3 -0
- package/dist/components/objects/ObjectDetails/ObjectSummary.js +193 -0
- package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +3 -0
- package/dist/components/objects/ObjectDetails/ObjectTags.js +300 -0
- package/dist/components/objects/ObjectDetails/index.d.ts +9 -0
- package/dist/components/objects/ObjectDetails/index.js +49 -0
- package/dist/components/objects/ObjectList.d.ts +40 -0
- package/dist/components/objects/ObjectList.js +407 -0
- package/dist/components/objects/ObjectPage.d.ts +1 -0
- package/dist/components/objects/ObjectPage.js +43 -0
- package/dist/components/objects/UploadButton.d.ts +34 -0
- package/dist/components/objects/UploadButton.js +229 -0
- package/dist/components/providers/DataBrowserProvider.d.ts +20 -0
- package/dist/components/providers/DataBrowserProvider.js +42 -0
- package/dist/components/search/MetadataSearch.d.ts +5 -0
- package/dist/components/search/MetadataSearch.js +162 -0
- package/dist/components/search/SearchHints.d.ts +8 -0
- package/dist/components/search/SearchHints.js +21 -0
- package/dist/components/ui/DeleteObjectModalContent.d.ts +5 -0
- package/dist/components/ui/DeleteObjectModalContent.js +71 -0
- package/dist/components/ui/Search.elements.d.ts +17 -0
- package/dist/components/ui/Search.elements.js +59 -0
- package/dist/components/ui/Table.elements.d.ts +36 -0
- package/dist/components/ui/Table.elements.js +87 -0
- package/dist/config/factory.d.ts +52 -0
- package/dist/config/factory.js +70 -0
- package/dist/config/types.d.ts +46 -0
- package/dist/config/types.js +0 -0
- package/dist/hooks/__tests__/useIsBucketEmpty.test.d.ts +1 -0
- package/dist/hooks/__tests__/useIsBucketEmpty.test.js +122 -0
- package/dist/hooks/bucketConfiguration.d.ts +147 -0
- package/dist/hooks/bucketConfiguration.js +59 -0
- package/dist/hooks/bucketOperations.d.ts +36 -0
- package/dist/hooks/bucketOperations.js +12 -0
- package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.d.ts +1 -0
- package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +276 -0
- package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.d.ts +1 -0
- package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +259 -0
- package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.d.ts +1 -0
- package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +166 -0
- package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.d.ts +1 -0
- package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +200 -0
- package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.d.ts +1 -0
- package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +136 -0
- package/dist/hooks/factories/index.d.ts +18 -0
- package/dist/hooks/factories/index.js +5 -0
- package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +13 -0
- package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +76 -0
- package/dist/hooks/factories/useCreateS3LoginHook.d.ts +8 -0
- package/dist/hooks/factories/useCreateS3LoginHook.js +22 -0
- package/dist/hooks/factories/useCreateS3MutationHook.d.ts +5 -0
- package/dist/hooks/factories/useCreateS3MutationHook.js +50 -0
- package/dist/hooks/factories/useCreateS3QueryHook.d.ts +3 -0
- package/dist/hooks/factories/useCreateS3QueryHook.js +30 -0
- package/dist/hooks/index.d.ts +8 -0
- package/dist/hooks/index.js +8 -0
- package/dist/hooks/loginOperations.d.ts +21 -0
- package/dist/hooks/loginOperations.js +9 -0
- package/dist/hooks/objectOperations.d.ts +190 -0
- package/dist/hooks/objectOperations.js +66 -0
- package/dist/hooks/presignedOperations.d.ts +73 -0
- package/dist/hooks/presignedOperations.js +72 -0
- package/dist/hooks/useIsBucketEmpty.d.ts +7 -0
- package/dist/hooks/useIsBucketEmpty.js +36 -0
- package/dist/hooks/useLoginMutation.d.ts +21 -0
- package/dist/hooks/useLoginMutation.js +9 -0
- package/dist/hooks/useS3Client.d.ts +1 -0
- package/dist/hooks/useS3Client.js +13 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/schemas/bucketPolicySchema.json +321 -0
- package/dist/test/msw/handlers/deleteBucket.d.ts +1 -0
- package/dist/test/msw/handlers/deleteBucket.js +14 -0
- package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -0
- package/dist/test/msw/handlers/getBucketAcl.js +96 -0
- package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -0
- package/dist/test/msw/handlers/getBucketLocation.js +23 -0
- package/dist/test/msw/handlers/getBucketPolicy.d.ts +11 -0
- package/dist/test/msw/handlers/getBucketPolicy.js +72 -0
- package/dist/test/msw/handlers/headObject.d.ts +1 -0
- package/dist/test/msw/handlers/headObject.js +17 -0
- package/dist/test/msw/handlers/listBuckets.d.ts +1 -0
- package/dist/test/msw/handlers/listBuckets.js +24 -0
- package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -0
- package/dist/test/msw/handlers/listObjectVersions.js +83 -0
- package/dist/test/msw/handlers/listObjects.d.ts +1 -0
- package/dist/test/msw/handlers/listObjects.js +66 -0
- package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -0
- package/dist/test/msw/handlers/objectLegalHold.js +24 -0
- package/dist/test/msw/handlers/objectRetention.d.ts +1 -0
- package/dist/test/msw/handlers/objectRetention.js +27 -0
- package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -0
- package/dist/test/msw/handlers/putBucketAcl.js +18 -0
- package/dist/test/msw/handlers/putObject.d.ts +1 -0
- package/dist/test/msw/handlers/putObject.js +16 -0
- package/dist/test/msw/handlers.d.ts +4 -0
- package/dist/test/msw/handlers.js +109 -0
- package/dist/test/msw/index.d.ts +2 -0
- package/dist/test/msw/index.js +3 -0
- package/dist/test/msw/server.d.ts +4 -0
- package/dist/test/msw/server.js +20 -0
- package/dist/test/msw/utils.d.ts +2 -0
- package/dist/test/msw/utils.js +13 -0
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.js +82 -0
- package/dist/test/testUtils.d.ts +82 -0
- package/dist/test/testUtils.js +236 -0
- package/dist/test/utils/errorHandling.test.d.ts +1 -0
- package/dist/test/utils/errorHandling.test.js +385 -0
- package/dist/types/index.d.ts +48 -0
- package/dist/types/index.js +0 -0
- package/dist/utils/deletion/index.d.ts +2 -0
- package/dist/utils/deletion/index.js +2 -0
- package/dist/utils/deletion/messages.d.ts +5 -0
- package/dist/utils/deletion/messages.js +29 -0
- package/dist/utils/deletion/types.d.ts +11 -0
- package/dist/utils/deletion/types.js +0 -0
- package/dist/utils/errorHandling.d.ts +54 -0
- package/dist/utils/errorHandling.js +79 -0
- package/dist/utils/hooks.d.ts +2 -0
- package/dist/utils/hooks.js +26 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/proxyMiddleware.d.ts +18 -0
- package/dist/utils/proxyMiddleware.js +56 -0
- package/dist/utils/s3Client.d.ts +5 -0
- package/dist/utils/s3Client.js +35 -0
- package/dist/utils/useFeatures.d.ts +1 -0
- package/dist/utils/useFeatures.js +7 -0
- package/package.json +79 -0
|
@@ -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,54 @@
|
|
|
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;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { InvalidObjectState, InvalidRequest, InvalidWriteOffset, NoSuchBucket, NoSuchKey, NoSuchUpload, ObjectAlreadyInActiveTierError, ObjectNotInActiveTierError } from "@aws-sdk/client-s3";
|
|
2
|
+
var errorHandling_ErrorCategory = /*#__PURE__*/ function(ErrorCategory) {
|
|
3
|
+
ErrorCategory["CLIENT_ERROR"] = "CLIENT_ERROR";
|
|
4
|
+
ErrorCategory["SERVER_ERROR"] = "SERVER_ERROR";
|
|
5
|
+
ErrorCategory["NETWORK_ERROR"] = "NETWORK_ERROR";
|
|
6
|
+
ErrorCategory["CANCELLATION"] = "CANCELLATION";
|
|
7
|
+
ErrorCategory["AUTHORIZATION"] = "AUTHORIZATION";
|
|
8
|
+
ErrorCategory["NOT_FOUND"] = "NOT_FOUND";
|
|
9
|
+
ErrorCategory["UNKNOWN"] = "UNKNOWN";
|
|
10
|
+
return ErrorCategory;
|
|
11
|
+
}({});
|
|
12
|
+
class EnhancedS3Error extends Error {
|
|
13
|
+
category;
|
|
14
|
+
statusCode;
|
|
15
|
+
metadata;
|
|
16
|
+
originalError;
|
|
17
|
+
context;
|
|
18
|
+
constructor(message, name, category, originalError, statusCode, metadata, context){
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = name;
|
|
21
|
+
this.category = category;
|
|
22
|
+
this.statusCode = statusCode;
|
|
23
|
+
this.metadata = metadata;
|
|
24
|
+
this.originalError = originalError;
|
|
25
|
+
this.context = context;
|
|
26
|
+
Object.setPrototypeOf(this, EnhancedS3Error.prototype);
|
|
27
|
+
}
|
|
28
|
+
shouldRetry() {
|
|
29
|
+
return "SERVER_ERROR" === this.category || "NETWORK_ERROR" === this.category;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function classifyByStatusCode(statusCode) {
|
|
33
|
+
if (statusCode >= 400 && statusCode < 500) {
|
|
34
|
+
if (401 === statusCode || 403 === statusCode) return "AUTHORIZATION";
|
|
35
|
+
if (404 === statusCode) return "NOT_FOUND";
|
|
36
|
+
return "CLIENT_ERROR";
|
|
37
|
+
}
|
|
38
|
+
return statusCode >= 500 ? "SERVER_ERROR" : "UNKNOWN";
|
|
39
|
+
}
|
|
40
|
+
function isS3ServiceException(error) {
|
|
41
|
+
return error instanceof Error && "$metadata" in error;
|
|
42
|
+
}
|
|
43
|
+
function isEnhancedS3Error(error) {
|
|
44
|
+
return error instanceof EnhancedS3Error;
|
|
45
|
+
}
|
|
46
|
+
function createS3Error(error, context) {
|
|
47
|
+
if (error instanceof Error && "AbortError" === error.name) return new EnhancedS3Error("Operation was cancelled", "AbortError", "CANCELLATION", error, void 0, void 0, context);
|
|
48
|
+
if (error instanceof NoSuchBucket || error instanceof NoSuchKey || error instanceof NoSuchUpload) return new EnhancedS3Error(error.message, error.name, "NOT_FOUND", error, error.$metadata?.httpStatusCode, error.$metadata, context);
|
|
49
|
+
if (error instanceof InvalidRequest || error instanceof InvalidObjectState || error instanceof InvalidWriteOffset || error instanceof ObjectAlreadyInActiveTierError || error instanceof ObjectNotInActiveTierError) return new EnhancedS3Error(error.message, error.name, "CLIENT_ERROR", error, error.$metadata?.httpStatusCode, error.$metadata, context);
|
|
50
|
+
if (isS3ServiceException(error)) {
|
|
51
|
+
const category = error.$metadata?.httpStatusCode ? classifyByStatusCode(error.$metadata.httpStatusCode) : "UNKNOWN";
|
|
52
|
+
return new EnhancedS3Error(error.message, error.name, category, error, error.$metadata?.httpStatusCode, error.$metadata, context);
|
|
53
|
+
}
|
|
54
|
+
if (error instanceof Error) {
|
|
55
|
+
const isNetwork = /network|connection|timeout|dns/i.test(error.message) || error.name.includes("Network") || error.name.includes("Timeout");
|
|
56
|
+
return new EnhancedS3Error(error.message, error.name, isNetwork ? "NETWORK_ERROR" : "UNKNOWN", error, void 0, void 0, context);
|
|
57
|
+
}
|
|
58
|
+
const message = "string" == typeof error ? error : "Unknown error occurred";
|
|
59
|
+
return new EnhancedS3Error(message, "UnknownError", "UNKNOWN", new Error(message), void 0, void 0, context);
|
|
60
|
+
}
|
|
61
|
+
function createS3OperationError(error, operation, bucketName, objectKey) {
|
|
62
|
+
const context = {
|
|
63
|
+
operation,
|
|
64
|
+
bucketName,
|
|
65
|
+
objectKey,
|
|
66
|
+
timestamp: new Date().toISOString()
|
|
67
|
+
};
|
|
68
|
+
const enhancedError = createS3Error(error, context);
|
|
69
|
+
if (!enhancedError.message.includes(operation)) {
|
|
70
|
+
const prefix = bucketName ? `${operation} failed for bucket '${bucketName}'${objectKey ? `, key '${objectKey}'` : ""}` : `${operation} failed`;
|
|
71
|
+
return new EnhancedS3Error(`${prefix}: ${enhancedError.message}`, enhancedError.name, enhancedError.category, enhancedError.originalError, enhancedError.statusCode, enhancedError.metadata, context);
|
|
72
|
+
}
|
|
73
|
+
return enhancedError;
|
|
74
|
+
}
|
|
75
|
+
function shouldRetryError(error, failureCount, maxRetries = 3) {
|
|
76
|
+
if (failureCount >= maxRetries) return false;
|
|
77
|
+
return isEnhancedS3Error(error) ? error.shouldRetry() : createS3Error(error).shouldRetry();
|
|
78
|
+
}
|
|
79
|
+
export { EnhancedS3Error, errorHandling_ErrorCategory as ErrorCategory, createS3Error, createS3OperationError, isEnhancedS3Error, isS3ServiceException, shouldRetryError };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useLocation } from "react-router-dom";
|
|
3
|
+
const useQueryParams = ()=>{
|
|
4
|
+
const location = useLocation();
|
|
5
|
+
return useMemo(()=>new URLSearchParams(location.search), [
|
|
6
|
+
location.search
|
|
7
|
+
]);
|
|
8
|
+
};
|
|
9
|
+
const usePrefixWithSlash = ()=>{
|
|
10
|
+
const query = useQueryParams();
|
|
11
|
+
return useMemo(()=>{
|
|
12
|
+
const prefix = query.get("prefix");
|
|
13
|
+
if (!prefix) return "";
|
|
14
|
+
if (!prefix || "/" === prefix.slice(-1)) return prefix;
|
|
15
|
+
{
|
|
16
|
+
const prefixArr = prefix.split("/");
|
|
17
|
+
prefixArr.pop();
|
|
18
|
+
if (!prefixArr.length) return "";
|
|
19
|
+
const joinedPrefix = prefixArr.join("/");
|
|
20
|
+
return joinedPrefix ? "/" !== joinedPrefix.slice(-1) ? `${joinedPrefix}/` : joinedPrefix : "";
|
|
21
|
+
}
|
|
22
|
+
}, [
|
|
23
|
+
query
|
|
24
|
+
]);
|
|
25
|
+
};
|
|
26
|
+
export { usePrefixWithSlash, useQueryParams };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Pluggable } from "@aws-sdk/types";
|
|
2
|
+
interface ProxyConfig {
|
|
3
|
+
realS3Host: string;
|
|
4
|
+
proxyBasePath: string;
|
|
5
|
+
proxyHost: string;
|
|
6
|
+
proxyPort: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a two-stage proxy middleware for AWS SDK v3
|
|
10
|
+
*
|
|
11
|
+
* This middleware enables proper S3 request signing through a development proxy:
|
|
12
|
+
* 1. Pre-signing: Modifies requests to use real S3 host for correct signature calculation
|
|
13
|
+
* 2. Post-signing: Routes signed requests through proxy to avoid CORS issues
|
|
14
|
+
*
|
|
15
|
+
* @param config Proxy configuration from build-time constants
|
|
16
|
+
*/
|
|
17
|
+
export declare const createProxyMiddleware: (config: ProxyConfig) => Pluggable<any, any>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { HttpRequest } from "@aws-sdk/protocol-http";
|
|
2
|
+
const createProxyMiddleware = (config)=>({
|
|
3
|
+
applyToStack: (clientStack)=>{
|
|
4
|
+
const preSigningMiddleware = (next)=>async (args)=>{
|
|
5
|
+
const { request } = args;
|
|
6
|
+
if (HttpRequest.isInstance(request) && request.hostname === config.proxyHost) {
|
|
7
|
+
const originalQuery = request.query || {};
|
|
8
|
+
if (request.path.startsWith(config.proxyBasePath)) {
|
|
9
|
+
request.path = request.path.replace(config.proxyBasePath, '');
|
|
10
|
+
if (!request.path.startsWith('/')) request.path = '/' + request.path;
|
|
11
|
+
}
|
|
12
|
+
request.hostname = config.realS3Host;
|
|
13
|
+
request.port = 443;
|
|
14
|
+
request.protocol = 'https:';
|
|
15
|
+
request.headers.host = config.realS3Host;
|
|
16
|
+
request.query = originalQuery;
|
|
17
|
+
console.log('Pre-signing: Modified for real S3 signing', {
|
|
18
|
+
path: request.path,
|
|
19
|
+
host: request.hostname,
|
|
20
|
+
query: request.query
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return next(args);
|
|
24
|
+
};
|
|
25
|
+
const postSigningMiddleware = (next)=>async (args)=>{
|
|
26
|
+
const { request } = args;
|
|
27
|
+
if (HttpRequest.isInstance(request) && request.hostname === config.realS3Host) {
|
|
28
|
+
const queryParams = request.query || {};
|
|
29
|
+
request.hostname = config.proxyHost;
|
|
30
|
+
request.port = config.proxyPort;
|
|
31
|
+
request.protocol = 'http:';
|
|
32
|
+
request.path = config.proxyBasePath + request.path;
|
|
33
|
+
request.headers.host = `${config.proxyHost}:${config.proxyPort}`;
|
|
34
|
+
request.query = queryParams;
|
|
35
|
+
console.log('Post-signing: Routed to proxy', {
|
|
36
|
+
host: request.hostname,
|
|
37
|
+
path: request.path,
|
|
38
|
+
query: request.query,
|
|
39
|
+
hasAuth: !!request.headers.authorization
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return next(args);
|
|
43
|
+
};
|
|
44
|
+
clientStack.add(preSigningMiddleware, {
|
|
45
|
+
step: "build",
|
|
46
|
+
name: "proxyPreSigningMiddleware",
|
|
47
|
+
priority: "high"
|
|
48
|
+
});
|
|
49
|
+
clientStack.add(postSigningMiddleware, {
|
|
50
|
+
step: "finalizeRequest",
|
|
51
|
+
name: "proxyPostSigningMiddleware",
|
|
52
|
+
priority: "high"
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
export { createProxyMiddleware };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { S3Client } from "@aws-sdk/client-s3";
|
|
2
|
+
import { createProxyMiddleware } from "./proxyMiddleware.js";
|
|
3
|
+
import { getBuildInfo, getProxyConfig, shouldUseProxy } from "../config/factory.js";
|
|
4
|
+
const createS3Client = (config)=>{
|
|
5
|
+
const client = new S3Client({
|
|
6
|
+
...config,
|
|
7
|
+
credentials: config.credentials,
|
|
8
|
+
forcePathStyle: true,
|
|
9
|
+
region: config.region
|
|
10
|
+
});
|
|
11
|
+
if (shouldUseProxy()) {
|
|
12
|
+
const proxyConfig = getProxyConfig();
|
|
13
|
+
if (proxyConfig.proxyConfig) {
|
|
14
|
+
client.middlewareStack.use(createProxyMiddleware({
|
|
15
|
+
realS3Host: proxyConfig.proxyConfig.realHost,
|
|
16
|
+
proxyBasePath: proxyConfig.proxyConfig.proxyBasePath,
|
|
17
|
+
proxyHost: proxyConfig.proxyConfig.proxyHost,
|
|
18
|
+
proxyPort: proxyConfig.proxyConfig.proxyPort
|
|
19
|
+
}));
|
|
20
|
+
const buildInfo = getBuildInfo();
|
|
21
|
+
console.log("S3Client configured with proxy middleware", {
|
|
22
|
+
buildInfo,
|
|
23
|
+
proxyConfig: proxyConfig.proxyConfig
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
const buildInfo = getBuildInfo();
|
|
28
|
+
console.log("S3Client configured for direct connection", {
|
|
29
|
+
buildInfo,
|
|
30
|
+
endpoint: config.endpoint
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return client;
|
|
34
|
+
};
|
|
35
|
+
export { createS3Client };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useFeatures(feature: string): boolean | undefined;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { useDataBrowserContext } from "../components/index.js";
|
|
2
|
+
function useFeatures(feature) {
|
|
3
|
+
const { getS3Config } = useDataBrowserContext();
|
|
4
|
+
const config = getS3Config();
|
|
5
|
+
return config?.credentials?.features?.includes(feature);
|
|
6
|
+
}
|
|
7
|
+
export { useFeatures };
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@scality/data-browser-library",
|
|
3
|
+
"version": "1.0.0-preview.2",
|
|
4
|
+
"description": "A modular React component library for browsing S3 buckets and objects",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "rslib build",
|
|
19
|
+
"dev": "rslib build --watch",
|
|
20
|
+
"type-check": "tsc --noEmit",
|
|
21
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
22
|
+
"test": "jest",
|
|
23
|
+
"clean": "rm -rf dist"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@aws-sdk/client-s3": "^3.478.0",
|
|
27
|
+
"@aws-sdk/protocol-http": "^3.370.0",
|
|
28
|
+
"@aws-sdk/s3-presigned-post": "^3.888.0",
|
|
29
|
+
"@aws-sdk/s3-request-presigner": "^3.478.0",
|
|
30
|
+
"@monaco-editor/react": "^4.7.0",
|
|
31
|
+
"@tanstack/react-query": "^5.8.0",
|
|
32
|
+
"@tanstack/react-query-devtools": "^5.8.0",
|
|
33
|
+
"@testing-library/user-event": "^14.6.1",
|
|
34
|
+
"react-dropzone": "^14.2.0",
|
|
35
|
+
"react-hook-form": "^7.48.0"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@scality/core-ui": "0.174.0",
|
|
39
|
+
"react": ">=18.0.0",
|
|
40
|
+
"react-dom": ">=18.0.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@rslib/core": "^0.14.0",
|
|
44
|
+
"@rsbuild/plugin-react": "^1.4.1",
|
|
45
|
+
"@testing-library/jest-dom": "^6.8.0",
|
|
46
|
+
"@testing-library/react": "^15.0.6",
|
|
47
|
+
"@testing-library/user-event": "^14.6.1",
|
|
48
|
+
"@types/jest": "^30.0.0",
|
|
49
|
+
"@types/react": "^18.2.0",
|
|
50
|
+
"@types/react-dom": "^18.2.0",
|
|
51
|
+
"@types/styled-components": "^5.1.34",
|
|
52
|
+
"identity-obj-proxy": "^3.0.0",
|
|
53
|
+
"jest": "^30.0.5",
|
|
54
|
+
"jest-environment-jsdom": "^30.0.5",
|
|
55
|
+
"msw": "^0.28.2",
|
|
56
|
+
"ts-jest": "^29.4.1"
|
|
57
|
+
},
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "https://github.com/scality/data-browser.git",
|
|
61
|
+
"directory": "packages/data-browser-library"
|
|
62
|
+
},
|
|
63
|
+
"keywords": [
|
|
64
|
+
"s3",
|
|
65
|
+
"aws",
|
|
66
|
+
"react",
|
|
67
|
+
"browser",
|
|
68
|
+
"data",
|
|
69
|
+
"scality",
|
|
70
|
+
"tanstack",
|
|
71
|
+
"react-query",
|
|
72
|
+
"component-library"
|
|
73
|
+
],
|
|
74
|
+
"author": "Scality",
|
|
75
|
+
"license": "Apache-2.0",
|
|
76
|
+
"publishConfig": {
|
|
77
|
+
"access": "public"
|
|
78
|
+
}
|
|
79
|
+
}
|