@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.
Files changed (176) hide show
  1. package/dist/components/Editor.d.ts +12 -0
  2. package/dist/components/Editor.js +28 -0
  3. package/dist/components/__tests__/BucketList.test.d.ts +1 -0
  4. package/dist/components/__tests__/BucketList.test.js +225 -0
  5. package/dist/components/__tests__/BucketOverview.test.d.ts +1 -0
  6. package/dist/components/__tests__/BucketOverview.test.js +479 -0
  7. package/dist/components/__tests__/BucketPolicyPage.test.d.ts +1 -0
  8. package/dist/components/__tests__/BucketPolicyPage.test.js +213 -0
  9. package/dist/components/__tests__/CreateFolderButton.test.d.ts +1 -0
  10. package/dist/components/__tests__/CreateFolderButton.test.js +147 -0
  11. package/dist/components/__tests__/DeleteBucketButton.test.d.ts +1 -0
  12. package/dist/components/__tests__/DeleteBucketButton.test.js +272 -0
  13. package/dist/components/__tests__/DeleteObjectButton.test.d.ts +1 -0
  14. package/dist/components/__tests__/DeleteObjectButton.test.js +302 -0
  15. package/dist/components/__tests__/MetadataSearch.test.d.ts +1 -0
  16. package/dist/components/__tests__/MetadataSearch.test.js +201 -0
  17. package/dist/components/__tests__/ObjectList.test.d.ts +1 -0
  18. package/dist/components/__tests__/ObjectList.test.js +283 -0
  19. package/dist/components/__tests__/UploadButton.test.d.ts +1 -0
  20. package/dist/components/__tests__/UploadButton.test.js +144 -0
  21. package/dist/components/buckets/BucketDetails.d.ts +1 -0
  22. package/dist/components/buckets/BucketDetails.js +51 -0
  23. package/dist/components/buckets/BucketList.d.ts +12 -0
  24. package/dist/components/buckets/BucketList.js +136 -0
  25. package/dist/components/buckets/BucketLocation.d.ts +3 -0
  26. package/dist/components/buckets/BucketLocation.js +16 -0
  27. package/dist/components/buckets/BucketOverview.d.ts +14 -0
  28. package/dist/components/buckets/BucketOverview.js +209 -0
  29. package/dist/components/buckets/BucketPage.d.ts +2 -0
  30. package/dist/components/buckets/BucketPage.js +47 -0
  31. package/dist/components/buckets/BucketPolicyButton.d.ts +7 -0
  32. package/dist/components/buckets/BucketPolicyButton.js +18 -0
  33. package/dist/components/buckets/BucketPolicyPage.d.ts +1 -0
  34. package/dist/components/buckets/BucketPolicyPage.js +205 -0
  35. package/dist/components/buckets/DeleteBucketButton.d.ts +8 -0
  36. package/dist/components/buckets/DeleteBucketButton.js +78 -0
  37. package/dist/components/index.d.ts +12 -0
  38. package/dist/components/index.js +13 -0
  39. package/dist/components/layouts/BrowserPageLayout.d.ts +9 -0
  40. package/dist/components/layouts/BrowserPageLayout.js +46 -0
  41. package/dist/components/objects/CreateFolderButton.d.ts +29 -0
  42. package/dist/components/objects/CreateFolderButton.js +118 -0
  43. package/dist/components/objects/DeleteObjectButton.d.ts +8 -0
  44. package/dist/components/objects/DeleteObjectButton.js +191 -0
  45. package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +2 -0
  46. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +323 -0
  47. package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +3 -0
  48. package/dist/components/objects/ObjectDetails/ObjectSummary.js +193 -0
  49. package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +3 -0
  50. package/dist/components/objects/ObjectDetails/ObjectTags.js +300 -0
  51. package/dist/components/objects/ObjectDetails/index.d.ts +9 -0
  52. package/dist/components/objects/ObjectDetails/index.js +49 -0
  53. package/dist/components/objects/ObjectList.d.ts +40 -0
  54. package/dist/components/objects/ObjectList.js +407 -0
  55. package/dist/components/objects/ObjectPage.d.ts +1 -0
  56. package/dist/components/objects/ObjectPage.js +43 -0
  57. package/dist/components/objects/UploadButton.d.ts +34 -0
  58. package/dist/components/objects/UploadButton.js +229 -0
  59. package/dist/components/providers/DataBrowserProvider.d.ts +20 -0
  60. package/dist/components/providers/DataBrowserProvider.js +42 -0
  61. package/dist/components/search/MetadataSearch.d.ts +5 -0
  62. package/dist/components/search/MetadataSearch.js +162 -0
  63. package/dist/components/search/SearchHints.d.ts +8 -0
  64. package/dist/components/search/SearchHints.js +21 -0
  65. package/dist/components/ui/DeleteObjectModalContent.d.ts +5 -0
  66. package/dist/components/ui/DeleteObjectModalContent.js +71 -0
  67. package/dist/components/ui/Search.elements.d.ts +17 -0
  68. package/dist/components/ui/Search.elements.js +59 -0
  69. package/dist/components/ui/Table.elements.d.ts +36 -0
  70. package/dist/components/ui/Table.elements.js +87 -0
  71. package/dist/config/factory.d.ts +52 -0
  72. package/dist/config/factory.js +70 -0
  73. package/dist/config/types.d.ts +46 -0
  74. package/dist/config/types.js +0 -0
  75. package/dist/hooks/__tests__/useIsBucketEmpty.test.d.ts +1 -0
  76. package/dist/hooks/__tests__/useIsBucketEmpty.test.js +122 -0
  77. package/dist/hooks/bucketConfiguration.d.ts +147 -0
  78. package/dist/hooks/bucketConfiguration.js +59 -0
  79. package/dist/hooks/bucketOperations.d.ts +36 -0
  80. package/dist/hooks/bucketOperations.js +12 -0
  81. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.d.ts +1 -0
  82. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +276 -0
  83. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.d.ts +1 -0
  84. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +259 -0
  85. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.d.ts +1 -0
  86. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +166 -0
  87. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.d.ts +1 -0
  88. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +200 -0
  89. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.d.ts +1 -0
  90. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +136 -0
  91. package/dist/hooks/factories/index.d.ts +18 -0
  92. package/dist/hooks/factories/index.js +5 -0
  93. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +13 -0
  94. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +76 -0
  95. package/dist/hooks/factories/useCreateS3LoginHook.d.ts +8 -0
  96. package/dist/hooks/factories/useCreateS3LoginHook.js +22 -0
  97. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +5 -0
  98. package/dist/hooks/factories/useCreateS3MutationHook.js +50 -0
  99. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +3 -0
  100. package/dist/hooks/factories/useCreateS3QueryHook.js +30 -0
  101. package/dist/hooks/index.d.ts +8 -0
  102. package/dist/hooks/index.js +8 -0
  103. package/dist/hooks/loginOperations.d.ts +21 -0
  104. package/dist/hooks/loginOperations.js +9 -0
  105. package/dist/hooks/objectOperations.d.ts +190 -0
  106. package/dist/hooks/objectOperations.js +66 -0
  107. package/dist/hooks/presignedOperations.d.ts +73 -0
  108. package/dist/hooks/presignedOperations.js +72 -0
  109. package/dist/hooks/useIsBucketEmpty.d.ts +7 -0
  110. package/dist/hooks/useIsBucketEmpty.js +36 -0
  111. package/dist/hooks/useLoginMutation.d.ts +21 -0
  112. package/dist/hooks/useLoginMutation.js +9 -0
  113. package/dist/hooks/useS3Client.d.ts +1 -0
  114. package/dist/hooks/useS3Client.js +13 -0
  115. package/dist/index.d.ts +6 -0
  116. package/dist/index.js +6 -0
  117. package/dist/schemas/bucketPolicySchema.json +321 -0
  118. package/dist/test/msw/handlers/deleteBucket.d.ts +1 -0
  119. package/dist/test/msw/handlers/deleteBucket.js +14 -0
  120. package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -0
  121. package/dist/test/msw/handlers/getBucketAcl.js +96 -0
  122. package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -0
  123. package/dist/test/msw/handlers/getBucketLocation.js +23 -0
  124. package/dist/test/msw/handlers/getBucketPolicy.d.ts +11 -0
  125. package/dist/test/msw/handlers/getBucketPolicy.js +72 -0
  126. package/dist/test/msw/handlers/headObject.d.ts +1 -0
  127. package/dist/test/msw/handlers/headObject.js +17 -0
  128. package/dist/test/msw/handlers/listBuckets.d.ts +1 -0
  129. package/dist/test/msw/handlers/listBuckets.js +24 -0
  130. package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -0
  131. package/dist/test/msw/handlers/listObjectVersions.js +83 -0
  132. package/dist/test/msw/handlers/listObjects.d.ts +1 -0
  133. package/dist/test/msw/handlers/listObjects.js +66 -0
  134. package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -0
  135. package/dist/test/msw/handlers/objectLegalHold.js +24 -0
  136. package/dist/test/msw/handlers/objectRetention.d.ts +1 -0
  137. package/dist/test/msw/handlers/objectRetention.js +27 -0
  138. package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -0
  139. package/dist/test/msw/handlers/putBucketAcl.js +18 -0
  140. package/dist/test/msw/handlers/putObject.d.ts +1 -0
  141. package/dist/test/msw/handlers/putObject.js +16 -0
  142. package/dist/test/msw/handlers.d.ts +4 -0
  143. package/dist/test/msw/handlers.js +109 -0
  144. package/dist/test/msw/index.d.ts +2 -0
  145. package/dist/test/msw/index.js +3 -0
  146. package/dist/test/msw/server.d.ts +4 -0
  147. package/dist/test/msw/server.js +20 -0
  148. package/dist/test/msw/utils.d.ts +2 -0
  149. package/dist/test/msw/utils.js +13 -0
  150. package/dist/test/setup.d.ts +1 -0
  151. package/dist/test/setup.js +82 -0
  152. package/dist/test/testUtils.d.ts +82 -0
  153. package/dist/test/testUtils.js +236 -0
  154. package/dist/test/utils/errorHandling.test.d.ts +1 -0
  155. package/dist/test/utils/errorHandling.test.js +385 -0
  156. package/dist/types/index.d.ts +48 -0
  157. package/dist/types/index.js +0 -0
  158. package/dist/utils/deletion/index.d.ts +2 -0
  159. package/dist/utils/deletion/index.js +2 -0
  160. package/dist/utils/deletion/messages.d.ts +5 -0
  161. package/dist/utils/deletion/messages.js +29 -0
  162. package/dist/utils/deletion/types.d.ts +11 -0
  163. package/dist/utils/deletion/types.js +0 -0
  164. package/dist/utils/errorHandling.d.ts +54 -0
  165. package/dist/utils/errorHandling.js +79 -0
  166. package/dist/utils/hooks.d.ts +2 -0
  167. package/dist/utils/hooks.js +26 -0
  168. package/dist/utils/index.d.ts +2 -0
  169. package/dist/utils/index.js +2 -0
  170. package/dist/utils/proxyMiddleware.d.ts +18 -0
  171. package/dist/utils/proxyMiddleware.js +56 -0
  172. package/dist/utils/s3Client.d.ts +5 -0
  173. package/dist/utils/s3Client.js +35 -0
  174. package/dist/utils/useFeatures.d.ts +1 -0
  175. package/dist/utils/useFeatures.js +7 -0
  176. 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,2 @@
1
+ export declare const useQueryParams: () => URLSearchParams;
2
+ export declare const usePrefixWithSlash: () => string;
@@ -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,2 @@
1
+ export * from "./s3Client";
2
+ export * from "./errorHandling";
@@ -0,0 +1,2 @@
1
+ export * from "./s3Client.js";
2
+ export * from "./errorHandling.js";
@@ -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,5 @@
1
+ import { S3Client } from "@aws-sdk/client-s3";
2
+ import { S3BrowserConfig, S3Credentials } from "../types";
3
+ export declare const createS3Client: (config: S3BrowserConfig & {
4
+ credentials: S3Credentials;
5
+ }) => S3Client;
@@ -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
+ }