@scality/data-browser-library 1.0.0-preview.9 → 1.0.3

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 (287) hide show
  1. package/dist/components/DataBrowserUI.d.ts +12 -0
  2. package/dist/components/DataBrowserUI.js +99 -0
  3. package/dist/components/Editor.d.ts +1 -1
  4. package/dist/components/Editor.js +3 -3
  5. package/dist/components/__tests__/BucketAccessor.test.js +214 -0
  6. package/dist/components/__tests__/BucketCorsPage.test.d.ts +1 -0
  7. package/dist/components/__tests__/BucketCorsPage.test.js +263 -0
  8. package/dist/components/__tests__/BucketCreate.test.js +271 -105
  9. package/dist/components/__tests__/BucketDetails.test.d.ts +1 -0
  10. package/dist/components/__tests__/BucketDetails.test.js +421 -0
  11. package/dist/components/__tests__/BucketLifecycleFormPage.test.d.ts +13 -0
  12. package/dist/components/__tests__/BucketLifecycleFormPage.test.js +178 -178
  13. package/dist/components/__tests__/BucketLifecycleList.test.js +85 -85
  14. package/dist/components/__tests__/BucketList.test.js +463 -239
  15. package/dist/components/__tests__/BucketNotificationFormPage.test.d.ts +1 -0
  16. package/dist/components/__tests__/BucketNotificationFormPage.test.js +348 -0
  17. package/dist/components/__tests__/BucketNotificationList.test.d.ts +1 -0
  18. package/dist/components/__tests__/BucketNotificationList.test.js +379 -0
  19. package/dist/components/__tests__/BucketOverview.test.js +281 -266
  20. package/dist/components/__tests__/BucketPolicyPage.test.js +151 -99
  21. package/dist/components/__tests__/BucketReplicationFormPage.test.d.ts +15 -0
  22. package/dist/components/__tests__/BucketReplicationFormPage.test.js +544 -544
  23. package/dist/components/__tests__/BucketReplicationList.test.js +106 -106
  24. package/dist/components/__tests__/CreateFolderButton.test.js +56 -56
  25. package/dist/components/__tests__/DeleteBucketButton.test.js +64 -64
  26. package/dist/components/__tests__/DeleteBucketConfigRuleButton.test.js +47 -47
  27. package/dist/components/__tests__/DeleteObjectButton.test.js +64 -64
  28. package/dist/components/__tests__/EmptyBucketButton.test.js +59 -59
  29. package/dist/components/__tests__/MetadataSearch.test.js +65 -65
  30. package/dist/components/__tests__/ObjectList.test.js +741 -240
  31. package/dist/components/__tests__/UploadButton.test.js +45 -45
  32. package/dist/components/breadcrumb/Breadcrumb.d.ts +6 -0
  33. package/dist/components/breadcrumb/Breadcrumb.js +37 -0
  34. package/dist/components/breadcrumb/DataBrowserBreadcrumb.d.ts +1 -0
  35. package/dist/components/breadcrumb/DataBrowserBreadcrumb.js +10 -0
  36. package/dist/components/breadcrumb/__tests__/Breadcrumb.test.d.ts +1 -0
  37. package/dist/components/breadcrumb/__tests__/Breadcrumb.test.js +196 -0
  38. package/dist/components/breadcrumb/__tests__/DataBrowserBreadcrumb.test.d.ts +1 -0
  39. package/dist/components/breadcrumb/__tests__/DataBrowserBreadcrumb.test.js +153 -0
  40. package/dist/components/breadcrumb/__tests__/useBreadcrumbPaths.test.d.ts +1 -0
  41. package/dist/components/breadcrumb/__tests__/useBreadcrumbPaths.test.js +134 -0
  42. package/dist/components/breadcrumb/index.d.ts +8 -0
  43. package/dist/components/breadcrumb/index.js +4 -0
  44. package/dist/components/breadcrumb/useBreadcrumbPaths.d.ts +2 -0
  45. package/dist/components/breadcrumb/useBreadcrumbPaths.js +82 -0
  46. package/dist/components/buckets/BucketAccessor.d.ts +2 -0
  47. package/dist/components/buckets/BucketAccessor.js +125 -0
  48. package/dist/components/buckets/BucketConfigEditButton.d.ts +8 -0
  49. package/dist/components/buckets/{BucketPolicyButton.js → BucketConfigEditButton.js} +9 -5
  50. package/dist/components/buckets/BucketCorsPage.d.ts +1 -0
  51. package/dist/components/buckets/BucketCorsPage.js +234 -0
  52. package/dist/components/buckets/BucketCreate.d.ts +3 -2
  53. package/dist/components/buckets/BucketCreate.js +93 -47
  54. package/dist/components/buckets/BucketDetails.d.ts +42 -0
  55. package/dist/components/buckets/BucketDetails.js +249 -85
  56. package/dist/components/buckets/BucketLifecycleFormPage.js +225 -191
  57. package/dist/components/buckets/BucketLifecycleList.d.ts +2 -2
  58. package/dist/components/buckets/BucketLifecycleList.js +59 -61
  59. package/dist/components/buckets/BucketList.d.ts +7 -8
  60. package/dist/components/buckets/BucketList.js +158 -101
  61. package/dist/components/buckets/BucketLocation.js +4 -4
  62. package/dist/components/buckets/BucketOverview.d.ts +22 -2
  63. package/dist/components/buckets/BucketOverview.js +394 -187
  64. package/dist/components/buckets/BucketPage.js +43 -21
  65. package/dist/components/buckets/BucketPolicyPage.js +155 -127
  66. package/dist/components/buckets/BucketReplicationFormPage.js +134 -133
  67. package/dist/components/buckets/BucketReplicationList.d.ts +2 -2
  68. package/dist/components/buckets/BucketReplicationList.js +48 -45
  69. package/dist/components/buckets/BucketVersioning.d.ts +4 -0
  70. package/dist/components/buckets/BucketVersioning.js +76 -0
  71. package/dist/components/buckets/DeleteBucketButton.js +8 -8
  72. package/dist/components/buckets/DeleteBucketConfigRuleButton.d.ts +2 -2
  73. package/dist/components/buckets/DeleteBucketConfigRuleButton.js +2 -2
  74. package/dist/components/buckets/EmptyBucketButton.js +24 -24
  75. package/dist/components/buckets/EmptyBucketSummary.d.ts +2 -2
  76. package/dist/components/buckets/EmptyBucketSummary.js +1 -1
  77. package/dist/components/buckets/EmptyBucketSummaryList.d.ts +1 -1
  78. package/dist/components/buckets/EmptyBucketSummaryList.js +22 -22
  79. package/dist/components/buckets/__tests__/BucketVersioning.test.d.ts +1 -0
  80. package/dist/components/buckets/__tests__/BucketVersioning.test.js +163 -0
  81. package/dist/components/buckets/notifications/BucketNotificationFormPage.d.ts +1 -0
  82. package/dist/components/buckets/notifications/BucketNotificationFormPage.js +316 -0
  83. package/dist/components/buckets/notifications/BucketNotificationList.d.ts +10 -0
  84. package/dist/components/buckets/notifications/BucketNotificationList.js +267 -0
  85. package/dist/components/buckets/notifications/EventsSection.js +145 -29
  86. package/dist/components/buckets/notifications/__tests__/events.test.d.ts +1 -0
  87. package/dist/components/buckets/notifications/__tests__/events.test.js +56 -0
  88. package/dist/components/buckets/notifications/events.d.ts +71 -7
  89. package/dist/components/buckets/notifications/events.js +98 -16
  90. package/dist/components/index.d.ts +27 -20
  91. package/dist/components/index.js +17 -10
  92. package/dist/components/layouts/ArrowNavigation.d.ts +3 -0
  93. package/dist/components/layouts/ArrowNavigation.js +28 -0
  94. package/dist/components/layouts/BrowserPageLayout.d.ts +5 -1
  95. package/dist/components/layouts/BrowserPageLayout.js +10 -5
  96. package/dist/components/objects/CreateFolderButton.d.ts +2 -2
  97. package/dist/components/objects/CreateFolderButton.js +12 -12
  98. package/dist/components/objects/DeleteObjectButton.d.ts +1 -1
  99. package/dist/components/objects/DeleteObjectButton.js +19 -21
  100. package/dist/components/objects/GetPresignedUrlButton.d.ts +7 -0
  101. package/dist/components/objects/GetPresignedUrlButton.js +255 -0
  102. package/dist/components/objects/ObjectDetails/ObjectMetadata.d.ts +2 -2
  103. package/dist/components/objects/ObjectDetails/ObjectMetadata.js +289 -230
  104. package/dist/components/objects/ObjectDetails/ObjectSummary.d.ts +2 -2
  105. package/dist/components/objects/ObjectDetails/ObjectSummary.js +540 -138
  106. package/dist/components/objects/ObjectDetails/ObjectTags.d.ts +2 -2
  107. package/dist/components/objects/ObjectDetails/ObjectTags.js +103 -123
  108. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.d.ts +1 -0
  109. package/dist/components/objects/ObjectDetails/__tests__/ObjectDetails.test.js +516 -0
  110. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.d.ts +1 -0
  111. package/dist/components/objects/ObjectDetails/__tests__/ObjectSummary.test.js +1064 -0
  112. package/dist/components/objects/ObjectDetails/formUtils.d.ts +15 -0
  113. package/dist/components/objects/ObjectDetails/formUtils.js +7 -0
  114. package/dist/components/objects/ObjectDetails/index.d.ts +18 -2
  115. package/dist/components/objects/ObjectDetails/index.js +152 -40
  116. package/dist/components/objects/ObjectList.d.ts +12 -10
  117. package/dist/components/objects/ObjectList.js +590 -263
  118. package/dist/components/objects/ObjectLock/EditRetentionButton.js +4 -4
  119. package/dist/components/objects/ObjectLock/ObjectLockRetentionSettings.js +15 -15
  120. package/dist/components/objects/ObjectLock/ObjectLockSettings.d.ts +1 -1
  121. package/dist/components/objects/ObjectLock/ObjectLockSettings.js +32 -31
  122. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.d.ts +1 -1
  123. package/dist/components/objects/ObjectLock/ObjectLockSettingsUtils.js +6 -6
  124. package/dist/components/objects/ObjectLock/__tests__/EditRetentionButton.test.js +51 -51
  125. package/dist/components/objects/ObjectLock/__tests__/ObjectLockSettings.test.js +78 -78
  126. package/dist/components/objects/ObjectPage.js +12 -8
  127. package/dist/components/objects/UploadButton.d.ts +3 -3
  128. package/dist/components/objects/UploadButton.js +10 -10
  129. package/dist/components/objects/__tests__/GetPresignedUrlButton.test.d.ts +1 -0
  130. package/dist/components/objects/__tests__/GetPresignedUrlButton.test.js +531 -0
  131. package/dist/components/providers/DataBrowserProvider.d.ts +23 -12
  132. package/dist/components/providers/DataBrowserProvider.js +60 -38
  133. package/dist/components/providers/QueryProvider.d.ts +9 -0
  134. package/dist/components/providers/QueryProvider.js +21 -0
  135. package/dist/components/search/MetadataSearch.js +29 -28
  136. package/dist/components/search/SearchHints.js +1 -1
  137. package/dist/components/ui/ArrayFieldActions.js +12 -7
  138. package/dist/components/ui/ConfirmDeleteRuleModal.d.ts +2 -2
  139. package/dist/components/ui/ConfirmDeleteRuleModal.js +6 -1
  140. package/dist/components/ui/DeleteObjectModalContent.d.ts +1 -1
  141. package/dist/components/ui/DeleteObjectModalContent.js +12 -12
  142. package/dist/components/ui/FilterFormSection.d.ts +2 -2
  143. package/dist/components/ui/FilterFormSection.js +29 -29
  144. package/dist/components/ui/Search.elements.d.ts +2 -2
  145. package/dist/components/ui/Search.elements.js +7 -7
  146. package/dist/components/ui/Table.elements.d.ts +2 -1
  147. package/dist/components/ui/Table.elements.js +18 -12
  148. package/dist/config/__tests__/factory.test.d.ts +1 -0
  149. package/dist/config/__tests__/factory.test.js +311 -0
  150. package/dist/config/factory.d.ts +10 -56
  151. package/dist/config/factory.js +23 -71
  152. package/dist/config/types.d.ts +212 -34
  153. package/dist/contexts/DataBrowserUICustomizationContext.d.ts +27 -0
  154. package/dist/contexts/DataBrowserUICustomizationContext.js +13 -0
  155. package/dist/hooks/__tests__/useAccessibleBuckets.test.d.ts +1 -0
  156. package/dist/hooks/__tests__/useAccessibleBuckets.test.js +145 -0
  157. package/dist/hooks/__tests__/useISVBucketDetection.test.js +45 -45
  158. package/dist/hooks/__tests__/useIsBucketEmpty.test.js +27 -27
  159. package/dist/hooks/__tests__/useLoginMutation.test.d.ts +1 -0
  160. package/dist/hooks/__tests__/useLoginMutation.test.js +194 -0
  161. package/dist/hooks/bucketConfiguration.d.ts +8 -1
  162. package/dist/hooks/bucketConfiguration.js +52 -51
  163. package/dist/hooks/bucketOperations.d.ts +10 -1
  164. package/dist/hooks/bucketOperations.js +10 -9
  165. package/dist/hooks/factories/__tests__/useCreateS3FunctionMutationHook.test.js +80 -80
  166. package/dist/hooks/factories/__tests__/useCreateS3InfiniteQueryHook.test.js +80 -80
  167. package/dist/hooks/factories/__tests__/useCreateS3LoginHook.test.js +44 -44
  168. package/dist/hooks/factories/__tests__/useCreateS3MutationHook.test.js +63 -63
  169. package/dist/hooks/factories/__tests__/useCreateS3QueryHook.test.js +65 -65
  170. package/dist/hooks/factories/index.d.ts +4 -4
  171. package/dist/hooks/factories/index.js +2 -2
  172. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.d.ts +2 -2
  173. package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +16 -13
  174. package/dist/hooks/factories/useCreateS3LoginHook.d.ts +2 -2
  175. package/dist/hooks/factories/useCreateS3LoginHook.js +1 -1
  176. package/dist/hooks/factories/useCreateS3MutationHook.d.ts +3 -3
  177. package/dist/hooks/factories/useCreateS3MutationHook.js +7 -2
  178. package/dist/hooks/factories/useCreateS3QueryHook.d.ts +2 -2
  179. package/dist/hooks/factories/useCreateS3QueryHook.js +11 -6
  180. package/dist/hooks/index.d.ts +19 -12
  181. package/dist/hooks/index.js +16 -9
  182. package/dist/hooks/loginOperations.d.ts +1 -1
  183. package/dist/hooks/loginOperations.js +1 -1
  184. package/dist/hooks/objectOperations.d.ts +2 -2
  185. package/dist/hooks/objectOperations.js +50 -49
  186. package/dist/hooks/presignedOperations.d.ts +4 -4
  187. package/dist/hooks/presignedOperations.js +5 -5
  188. package/dist/hooks/useAccessibleBuckets.d.ts +11 -0
  189. package/dist/hooks/useAccessibleBuckets.js +115 -0
  190. package/dist/hooks/useBatchObjectLegalHold.d.ts +11 -0
  191. package/dist/hooks/useBatchObjectLegalHold.js +48 -0
  192. package/dist/hooks/useBucketConfigEditor.d.ts +31 -0
  193. package/dist/hooks/useBucketConfigEditor.js +82 -0
  194. package/dist/hooks/useDataBrowserNavigate.d.ts +28 -0
  195. package/dist/hooks/useDataBrowserNavigate.js +24 -0
  196. package/dist/hooks/useDeleteBucketConfigRule.d.ts +2 -2
  197. package/dist/hooks/useDeleteBucketConfigRule.js +4 -4
  198. package/dist/hooks/useEmptyBucket.js +11 -11
  199. package/dist/hooks/useFeatures.d.ts +7 -0
  200. package/dist/hooks/useFeatures.js +8 -0
  201. package/dist/hooks/useISVBucketDetection.js +6 -6
  202. package/dist/hooks/useIsBucketEmpty.js +4 -4
  203. package/dist/hooks/useLimitedAccessFlow.d.ts +48 -0
  204. package/dist/hooks/useLimitedAccessFlow.js +23 -0
  205. package/dist/hooks/useS3Client.d.ts +6 -0
  206. package/dist/hooks/useS3Client.js +3 -2
  207. package/dist/hooks/useS3ConfigSwitch.d.ts +11 -0
  208. package/dist/hooks/useS3ConfigSwitch.js +37 -0
  209. package/dist/hooks/useSupportedNotificationEvents.d.ts +6 -0
  210. package/dist/hooks/useSupportedNotificationEvents.js +8 -0
  211. package/dist/index.d.ts +6 -6
  212. package/dist/index.js +2 -2
  213. package/dist/schemas/bucketPolicySchema.json +3 -13
  214. package/dist/test/msw/handlers/deleteBucket.d.ts +1 -1
  215. package/dist/test/msw/handlers/deleteBucket.js +20 -10
  216. package/dist/test/msw/handlers/getBucketAcl.d.ts +1 -1
  217. package/dist/test/msw/handlers/getBucketAcl.js +29 -17
  218. package/dist/test/msw/handlers/getBucketLocation.d.ts +1 -1
  219. package/dist/test/msw/handlers/getBucketLocation.js +29 -15
  220. package/dist/test/msw/handlers/getBucketPolicy.d.ts +1 -1
  221. package/dist/test/msw/handlers/getBucketPolicy.js +52 -32
  222. package/dist/test/msw/handlers/headObject.d.ts +1 -1
  223. package/dist/test/msw/handlers/headObject.js +31 -13
  224. package/dist/test/msw/handlers/listBuckets.d.ts +1 -1
  225. package/dist/test/msw/handlers/listBuckets.js +5 -3
  226. package/dist/test/msw/handlers/listObjectVersions.d.ts +1 -1
  227. package/dist/test/msw/handlers/listObjectVersions.js +38 -26
  228. package/dist/test/msw/handlers/listObjects.d.ts +1 -1
  229. package/dist/test/msw/handlers/listObjects.js +35 -23
  230. package/dist/test/msw/handlers/objectLegalHold.d.ts +1 -1
  231. package/dist/test/msw/handlers/objectLegalHold.js +32 -17
  232. package/dist/test/msw/handlers/objectRetention.d.ts +1 -1
  233. package/dist/test/msw/handlers/objectRetention.js +31 -17
  234. package/dist/test/msw/handlers/putBucketAcl.d.ts +1 -1
  235. package/dist/test/msw/handlers/putBucketAcl.js +29 -14
  236. package/dist/test/msw/handlers/putObject.d.ts +1 -1
  237. package/dist/test/msw/handlers/putObject.js +27 -12
  238. package/dist/test/msw/handlers.d.ts +3 -3
  239. package/dist/test/msw/handlers.js +77 -54
  240. package/dist/test/msw/index.d.ts +2 -2
  241. package/dist/test/msw/index.js +1 -1
  242. package/dist/test/msw/server.d.ts +1 -1
  243. package/dist/test/msw/server.js +1 -1
  244. package/dist/test/msw/utils.js +2 -2
  245. package/dist/test/setup.d.ts +1 -1
  246. package/dist/test/setup.js +13 -30
  247. package/dist/test/testUtils.d.ts +85 -33
  248. package/dist/test/testUtils.js +176 -111
  249. package/dist/test/utils/errorHandling.test.js +119 -119
  250. package/dist/types/index.d.ts +50 -37
  251. package/dist/types/monaco.d.ts +13 -0
  252. package/dist/types/monaco.js +0 -0
  253. package/dist/utils/__tests__/proxyMiddleware.test.d.ts +1 -0
  254. package/dist/utils/__tests__/proxyMiddleware.test.js +579 -0
  255. package/dist/utils/__tests__/s3Client.test.d.ts +1 -0
  256. package/dist/utils/__tests__/s3Client.test.js +340 -0
  257. package/dist/utils/__tests__/s3ConfigIdentifier.test.d.ts +1 -0
  258. package/dist/utils/__tests__/s3ConfigIdentifier.test.js +437 -0
  259. package/dist/utils/constants.d.ts +10 -0
  260. package/dist/utils/constants.js +19 -9
  261. package/dist/utils/deletion/index.d.ts +2 -2
  262. package/dist/utils/deletion/index.js +1 -1
  263. package/dist/utils/deletion/messages.d.ts +1 -1
  264. package/dist/utils/deletion/messages.js +4 -4
  265. package/dist/utils/errorHandling.d.ts +3 -3
  266. package/dist/utils/errorHandling.js +6 -6
  267. package/dist/utils/hooks.js +8 -8
  268. package/dist/utils/index.d.ts +5 -4
  269. package/dist/utils/index.js +4 -2
  270. package/dist/utils/proxyMiddleware.d.ts +32 -13
  271. package/dist/utils/proxyMiddleware.js +90 -36
  272. package/dist/utils/s3Client.d.ts +14 -4
  273. package/dist/utils/s3Client.js +5 -26
  274. package/dist/utils/s3ConfigIdentifier.d.ts +79 -0
  275. package/dist/utils/s3ConfigIdentifier.js +57 -0
  276. package/dist/utils/s3RuleUtils.d.ts +5 -5
  277. package/dist/utils/s3RuleUtils.js +17 -17
  278. package/package.json +10 -8
  279. package/dist/components/__tests__/BucketNotificationCreatePage.test.js +0 -316
  280. package/dist/components/buckets/BucketPolicyButton.d.ts +0 -7
  281. package/dist/components/buckets/notifications/BucketNotificationCreatePage.d.ts +0 -1
  282. package/dist/components/buckets/notifications/BucketNotificationCreatePage.js +0 -234
  283. package/dist/hooks/useLoginMutation.d.ts +0 -21
  284. package/dist/hooks/useLoginMutation.js +0 -9
  285. package/dist/utils/useFeatures.d.ts +0 -1
  286. package/dist/utils/useFeatures.js +0 -7
  287. /package/dist/components/__tests__/{BucketNotificationCreatePage.test.d.ts → BucketAccessor.test.d.ts} +0 -0
@@ -1,18 +1,37 @@
1
- import { Pluggable } from "@aws-sdk/types";
2
- interface ProxyConfig {
3
- realS3Host: string;
4
- proxyBasePath: string;
5
- proxyHost: string;
6
- proxyPort: number;
7
- }
1
+ import type { ServiceInputTypes, ServiceOutputTypes } from '@aws-sdk/client-s3';
2
+ import type { Pluggable } from '@aws-sdk/types';
3
+ import type { ProxyConfiguration } from '../config/types';
4
+ /**
5
+ * Resolves proxy endpoint to a full URL
6
+ *
7
+ * Supported formats:
8
+ * - "origin" → window.location.origin
9
+ * - "/path" → window.location.origin + "/path"
10
+ * - "http://..." → unchanged
11
+ *
12
+ * @param endpoint Proxy endpoint string
13
+ * @returns Resolved full URL
14
+ */
15
+ export declare function resolveProxyEndpoint(endpoint: string): string;
16
+ /**
17
+ * Parses endpoint URL and validates basic security requirements
18
+ *
19
+ * @param endpoint Endpoint URL string
20
+ * @returns Parsed endpoint components
21
+ */
22
+ export declare function parseEndpoint(endpoint: string): {
23
+ hostname: string;
24
+ port: number;
25
+ protocol: string;
26
+ pathname: string;
27
+ };
8
28
  /**
9
29
  * Creates a two-stage proxy middleware for AWS SDK v3
10
30
  *
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
31
+ * Stage 1: Pre-signing - Replace proxy host with target S3 for signature calculation
32
+ * Stage 2: Post-signing - Route signed request back through proxy
14
33
  *
15
- * @param config Proxy configuration from build-time constants
34
+ * @param config Proxy configuration with target S3 endpoint and proxy endpoint
35
+ * @returns AWS SDK v3 pluggable middleware
16
36
  */
17
- export declare const createProxyMiddleware: (config: ProxyConfig) => Pluggable<any, any>;
18
- export {};
37
+ export declare const createProxyMiddleware: (config: ProxyConfiguration) => Pluggable<ServiceInputTypes, ServiceOutputTypes>;
@@ -1,56 +1,110 @@
1
1
  import { HttpRequest } from "@aws-sdk/protocol-http";
2
- const createProxyMiddleware = (config)=>({
2
+ const ALLOWED_PROTOCOLS = [
3
+ 'http:',
4
+ 'https:'
5
+ ];
6
+ function resolveProxyEndpoint(endpoint) {
7
+ if (!endpoint || 'string' != typeof endpoint) throw new Error('Proxy endpoint must be a non-empty string');
8
+ const trimmed = endpoint.trim();
9
+ if (!trimmed) throw new Error('Proxy endpoint cannot be empty');
10
+ if ('origin' === trimmed) {
11
+ if ('undefined' == typeof window || !window?.location?.origin) throw new Error('Cannot use "origin" keyword outside browser environment');
12
+ const origin = window.location.origin;
13
+ if (!origin.startsWith('http://') && !origin.startsWith('https://')) throw new Error(`Invalid origin protocol: ${origin}`);
14
+ return origin;
15
+ }
16
+ if (trimmed.startsWith('/')) {
17
+ if ('undefined' == typeof window || !window?.location?.origin) throw new Error('Cannot resolve relative path outside browser environment');
18
+ const origin = window.location.origin;
19
+ if (!origin.startsWith('http://') && !origin.startsWith('https://')) throw new Error(`Invalid origin protocol: ${origin}`);
20
+ return origin + trimmed;
21
+ }
22
+ try {
23
+ new URL(trimmed);
24
+ } catch (e) {
25
+ throw new Error(`Invalid proxy endpoint URL: ${trimmed}`);
26
+ }
27
+ return trimmed;
28
+ }
29
+ function parseEndpoint(endpoint) {
30
+ let url;
31
+ let prepared = endpoint;
32
+ try {
33
+ if (!endpoint.includes('://')) prepared = `http://${endpoint}`;
34
+ url = new URL(prepared);
35
+ if (!ALLOWED_PROTOCOLS.includes(url.protocol)) throw new Error(`Protocol "${url.protocol}" not allowed. Use http: or https:`);
36
+ if (url.username || url.password) throw new Error('Embedded credentials in URLs are not allowed');
37
+ if (!url.hostname) throw new Error('Hostname cannot be empty');
38
+ } catch (error) {
39
+ if (error instanceof Error && error.message.includes('not allowed')) throw error;
40
+ if (error instanceof TypeError) throw new Error(`Invalid endpoint URL: ${endpoint}`);
41
+ throw error;
42
+ }
43
+ return {
44
+ hostname: url.hostname,
45
+ port: url.port ? parseInt(url.port, 10) : 'https:' === url.protocol ? 443 : 80,
46
+ protocol: url.protocol,
47
+ pathname: '/' === url.pathname ? '' : url.pathname
48
+ };
49
+ }
50
+ const createProxyMiddleware = (config)=>{
51
+ if (!config.target) throw new Error('ProxyConfiguration.target is required');
52
+ const resolvedProxyEndpoint = resolveProxyEndpoint(config.endpoint);
53
+ const target = parseEndpoint(config.target);
54
+ const proxy = parseEndpoint(resolvedProxyEndpoint);
55
+ return {
3
56
  applyToStack: (clientStack)=>{
4
57
  const preSigningMiddleware = (next)=>async (args)=>{
5
58
  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;
59
+ if (HttpRequest.isInstance(request) && request.hostname === proxy.hostname) {
60
+ const originalQuery = request.query ? {
61
+ ...request.query
62
+ } : {};
63
+ if (proxy.pathname && '/' !== proxy.pathname) {
64
+ const normalizedProxyPath = proxy.pathname.toLowerCase();
65
+ const normalizedRequestPath = request.path.toLowerCase();
66
+ if (normalizedRequestPath.startsWith(normalizedProxyPath)) {
67
+ const prefixLength = proxy.pathname.length;
68
+ request.path = request.path.substring(prefixLength);
69
+ if (request.path) {
70
+ if (!request.path.startsWith('/')) request.path = '/' + request.path;
71
+ } else request.path = '/';
72
+ }
11
73
  }
12
- request.hostname = config.realS3Host;
13
- request.port = 443;
14
- request.protocol = 'https:';
15
- request.headers.host = config.realS3Host;
74
+ request.hostname = target.hostname;
75
+ request.port = target.port;
76
+ request.protocol = target.protocol;
77
+ request.headers.host = target.port && 80 !== target.port && 443 !== target.port ? `${target.hostname}:${target.port}` : target.hostname;
16
78
  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
79
  }
23
80
  return next(args);
24
81
  };
25
82
  const postSigningMiddleware = (next)=>async (args)=>{
26
83
  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}`;
84
+ if (HttpRequest.isInstance(request) && request.hostname === target.hostname) {
85
+ const queryParams = request.query ? {
86
+ ...request.query
87
+ } : {};
88
+ request.hostname = proxy.hostname;
89
+ request.port = proxy.port;
90
+ request.protocol = proxy.protocol;
91
+ request.path = '' === proxy.pathname || '/' === proxy.pathname ? request.path : proxy.pathname + request.path;
92
+ request.headers.host = proxy.port && 80 !== proxy.port && 443 !== proxy.port ? `${proxy.hostname}:${proxy.port}` : proxy.hostname;
34
93
  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
94
  }
42
95
  return next(args);
43
96
  };
44
97
  clientStack.add(preSigningMiddleware, {
45
- step: "build",
46
- name: "proxyPreSigningMiddleware",
47
- priority: "high"
98
+ step: 'build',
99
+ name: 'proxyPreSigningMiddleware',
100
+ priority: 'high'
48
101
  });
49
102
  clientStack.add(postSigningMiddleware, {
50
- step: "finalizeRequest",
51
- name: "proxyPostSigningMiddleware",
52
- priority: "high"
103
+ step: 'finalizeRequest',
104
+ name: 'proxyPostSigningMiddleware',
105
+ priority: 'high'
53
106
  });
54
107
  }
55
- });
56
- export { createProxyMiddleware };
108
+ };
109
+ };
110
+ export { createProxyMiddleware, parseEndpoint, resolveProxyEndpoint };
@@ -1,5 +1,15 @@
1
- import { S3Client } from "@aws-sdk/client-s3";
2
- import { S3BrowserConfig, S3Credentials } from "../types";
3
- export declare const createS3Client: (config: S3BrowserConfig & {
1
+ import { S3Client } from '@aws-sdk/client-s3';
2
+ import type { S3BrowserConfig, S3Credentials } from '../types';
3
+ /**
4
+ * S3Client configuration with credentials
5
+ */
6
+ export interface S3ClientConfigWithProxy extends S3BrowserConfig {
4
7
  credentials: S3Credentials;
5
- }) => S3Client;
8
+ }
9
+ /**
10
+ * Create S3 client with optional proxy middleware
11
+ *
12
+ * @param config - S3 configuration with credentials and optional proxy config
13
+ * @returns Configured S3Client instance
14
+ */
15
+ export declare const createS3Client: (config: S3ClientConfigWithProxy) => S3Client;
@@ -1,36 +1,15 @@
1
1
  import { S3Client } from "@aws-sdk/client-s3";
2
- import { createProxyMiddleware } from "./proxyMiddleware.js";
3
- import { S3ConfigurationFactory } from "../config/factory.js";
4
- function extractProxyConfig(config) {
5
- if (config.useDevProxy && config.realS3Host && config.proxyPath) return {
6
- realS3Host: config.realS3Host,
7
- proxyBasePath: config.proxyPath,
8
- proxyHost: config.proxyHost || "localhost",
9
- proxyPort: config.proxyPort || 8084
10
- };
11
- const proxyConfig = S3ConfigurationFactory.createProxyConfiguration();
12
- if (proxyConfig.useProxy && proxyConfig.proxyConfig) return {
13
- realS3Host: proxyConfig.proxyConfig.realHost,
14
- proxyBasePath: proxyConfig.proxyConfig.proxyBasePath,
15
- proxyHost: proxyConfig.proxyConfig.proxyHost,
16
- proxyPort: proxyConfig.proxyConfig.proxyPort
17
- };
18
- return null;
19
- }
2
+ import { createProxyMiddleware, resolveProxyEndpoint } from "./proxyMiddleware.js";
20
3
  const createS3Client = (config)=>{
4
+ if (config.proxy?.enabled && !config.proxy.target) throw new Error('Proxy configuration error: "target" is required when proxy is enabled');
5
+ const clientEndpoint = config.proxy?.enabled ? resolveProxyEndpoint(config.proxy.endpoint) : config.endpoint;
21
6
  const client = new S3Client({
22
- ...config,
7
+ endpoint: clientEndpoint,
23
8
  credentials: config.credentials,
24
9
  forcePathStyle: config.forcePathStyle ?? true,
25
10
  region: config.region
26
11
  });
27
- const proxyConfig = extractProxyConfig(config);
28
- if (proxyConfig) client.middlewareStack.use(createProxyMiddleware({
29
- realS3Host: proxyConfig.realS3Host,
30
- proxyBasePath: proxyConfig.proxyBasePath,
31
- proxyHost: proxyConfig.proxyHost,
32
- proxyPort: proxyConfig.proxyPort
33
- }));
12
+ if (config.proxy?.enabled) client.middlewareStack.use(createProxyMiddleware(config.proxy));
34
13
  return client;
35
14
  };
36
15
  export { createS3Client };
@@ -0,0 +1,79 @@
1
+ import type { GetConfigFunction } from '../types';
2
+ export declare const ANONYMOUS_S3_CONFIG_IDENTIFIER = "anonymous-s3-config";
3
+ /**
4
+ * Hashes a session token using FNV-1a 64-bit algorithm for query cache isolation.
5
+ *
6
+ * Note: This is NOT a cryptographic hash - it's designed for collision resistance
7
+ * in the context of query key uniqueness, not security.
8
+ *
9
+ * The input is trimmed before hashing to ensure consistent results regardless of
10
+ * whitespace variations.
11
+ *
12
+ * @param sessionToken - AWS session token string to hash
13
+ * @returns A 16-character zero-padded hexadecimal string (64-bit hash)
14
+ */
15
+ export declare const hashSessionToken: (sessionToken: string) => string;
16
+ /**
17
+ * Normalizes a region string for consistent comparison.
18
+ *
19
+ * @param region - AWS region string
20
+ * @returns Normalized region (trimmed and lowercase)
21
+ */
22
+ export declare const normalizeRegion: (region: string) => string;
23
+ /**
24
+ * Normalizes an S3 endpoint URL for consistent comparison.
25
+ *
26
+ * Handles:
27
+ * - Protocol and hostname lowercasing
28
+ * - Default port removal (443 for HTTPS, 80 for HTTP)
29
+ * - Trailing slash removal from pathname
30
+ * - Query parameters and URL fragments are stripped
31
+ * - User credentials (username:password) are stripped
32
+ * - Invalid URL fallback to string normalization
33
+ *
34
+ * @param endpoint - S3 endpoint URL
35
+ * @returns Normalized endpoint string
36
+ */
37
+ export declare const normalizeEndpoint: (endpoint: string) => string;
38
+ /**
39
+ * Minimal configuration interface for computing S3 config identifiers.
40
+ *
41
+ * This interface describes which fields are used by `computeS3ConfigIdentifier`.
42
+ * The function accepts any object with these optional properties, including the
43
+ * full S3BrowserConfig type.
44
+ *
45
+ * ## Cache Key Resolution Priority
46
+ *
47
+ * 1. `cacheKey` (top-level) - Explicit cache identity, highest priority
48
+ * 2. `accessKeyId` + `sessionToken` - Fallback for direct credentials
49
+ *
50
+ * When `cacheKey` is provided, `accessKeyId` and `sessionToken` are ignored
51
+ * for cache key generation. This prevents unnecessary cache invalidation when
52
+ * credentials refresh but the logical identity remains the same.
53
+ */
54
+ export interface S3ConfigIdentifierConfig {
55
+ /**
56
+ * Explicit cache identity. When provided, takes priority over credentials.
57
+ * Use this when credentials change frequently (e.g., token refresh) but
58
+ * represent the same logical identity.
59
+ */
60
+ cacheKey?: string;
61
+ credentials?: {
62
+ accessKeyId?: string;
63
+ secretAccessKey?: string;
64
+ sessionToken?: string;
65
+ };
66
+ region?: string;
67
+ endpoint?: string;
68
+ }
69
+ /**
70
+ * Computes a unique identifier for the current S3 configuration to isolate
71
+ * query caches between different S3 configurations.
72
+ *
73
+ * All inputs are normalized to prevent cache misses due to formatting differences.
74
+ *
75
+ * @param config - S3 configuration object
76
+ * @param fallbackIdentifier - Identifier to use when no config parts are available (default: ANONYMOUS_S3_CONFIG_IDENTIFIER)
77
+ * @returns An opaque identifier string (|| separated internally), or fallbackIdentifier if all parts are empty/missing
78
+ */
79
+ export declare const computeS3ConfigIdentifier: (config: S3ConfigIdentifierConfig | ReturnType<GetConfigFunction>, fallbackIdentifier?: string) => string;
@@ -0,0 +1,57 @@
1
+ const ANONYMOUS_S3_CONFIG_IDENTIFIER = 'anonymous-s3-config';
2
+ const TEXT_ENCODER = new TextEncoder();
3
+ const DEFAULT_PORTS = {
4
+ 'https:': '443',
5
+ 'http:': '80'
6
+ };
7
+ const IDENTIFIER_SEPARATOR = '||';
8
+ const hashSessionToken = (sessionToken)=>{
9
+ const FNV_PRIME = 0x100000001b3n;
10
+ const FNV_OFFSET_BASIS = 0xcbf29ce484222325n;
11
+ const MASK_64 = 0xffffffffffffffffn;
12
+ let hash = FNV_OFFSET_BASIS;
13
+ const trimmed = sessionToken.trim();
14
+ const bytes = TEXT_ENCODER.encode(trimmed);
15
+ for (const byte of bytes){
16
+ hash ^= BigInt(byte);
17
+ hash = hash * FNV_PRIME & MASK_64;
18
+ }
19
+ return hash.toString(16).padStart(16, '0');
20
+ };
21
+ const normalizeRegion = (region)=>region.trim().toLowerCase();
22
+ const normalizeEndpoint = (endpoint)=>{
23
+ const trimmed = endpoint.trim();
24
+ try {
25
+ const url = new URL(trimmed);
26
+ const protocol = url.protocol.toLowerCase();
27
+ const hostname = url.hostname.toLowerCase();
28
+ const isDefaultPort = '' === url.port || url.port === DEFAULT_PORTS[protocol];
29
+ const port = isDefaultPort ? '' : `:${url.port}`;
30
+ const pathname = url.pathname.replace(/\/+$/, '') || '';
31
+ return `${protocol}//${hostname}${port}${pathname}`;
32
+ } catch (error) {
33
+ return trimmed.replace(/\/+$/, '');
34
+ }
35
+ };
36
+ const computeS3ConfigIdentifier = (config, fallbackIdentifier = ANONYMOUS_S3_CONFIG_IDENTIFIER)=>{
37
+ const parts = [];
38
+ const cacheKey = config?.cacheKey?.trim();
39
+ if (cacheKey) parts.push(cacheKey);
40
+ else {
41
+ const accessKeyId = config?.credentials?.accessKeyId?.trim();
42
+ if (accessKeyId) {
43
+ parts.push(accessKeyId);
44
+ const sessionToken = config?.credentials?.sessionToken?.trim();
45
+ if (sessionToken) {
46
+ const hash = hashSessionToken(sessionToken);
47
+ parts.push(`session:${hash}`);
48
+ }
49
+ }
50
+ }
51
+ const region = config?.region?.trim();
52
+ if (region) parts.push(`region:${normalizeRegion(region)}`);
53
+ const endpoint = config?.endpoint?.trim();
54
+ if (endpoint) parts.push(`endpoint:${normalizeEndpoint(endpoint)}`);
55
+ return parts.length > 0 ? parts.join(IDENTIFIER_SEPARATOR) : fallbackIdentifier;
56
+ };
57
+ export { ANONYMOUS_S3_CONFIG_IDENTIFIER, computeS3ConfigIdentifier, hashSessionToken, normalizeEndpoint, normalizeRegion };
@@ -10,7 +10,7 @@ export declare const STATUS_OPTIONS: readonly [{
10
10
  readonly value: "Disabled";
11
11
  readonly label: "Disabled";
12
12
  }];
13
- export type FilterType = "none" | "prefix" | "tags" | "and";
13
+ export type FilterType = 'none' | 'prefix' | 'tags' | 'and';
14
14
  /**
15
15
  * Filter data for S3 rules. All fields are present for form handling,
16
16
  * but only certain fields are used based on filterType.
@@ -28,18 +28,18 @@ export interface FilterData {
28
28
  * Each variant only includes the fields relevant to that filter type.
29
29
  */
30
30
  export type FilterSpec = {
31
- type: "none";
31
+ type: 'none';
32
32
  } | {
33
- type: "prefix";
33
+ type: 'prefix';
34
34
  prefix: string;
35
35
  } | {
36
- type: "tags";
36
+ type: 'tags';
37
37
  tags: Array<{
38
38
  key: string;
39
39
  value: string;
40
40
  }>;
41
41
  } | {
42
- type: "and";
42
+ type: 'and';
43
43
  prefix: string;
44
44
  tags: Array<{
45
45
  key: string;
@@ -5,33 +5,33 @@ const AWS_RULE_LIMITS = {
5
5
  };
6
6
  const STATUS_OPTIONS = [
7
7
  {
8
- value: "Enabled",
9
- label: "Enabled"
8
+ value: 'Enabled',
9
+ label: 'Enabled'
10
10
  },
11
11
  {
12
- value: "Disabled",
13
- label: "Disabled"
12
+ value: 'Disabled',
13
+ label: 'Disabled'
14
14
  }
15
15
  ];
16
16
  function toFilterSpec(data) {
17
17
  switch(data.filterType){
18
- case "none":
18
+ case 'none':
19
19
  return {
20
- type: "none"
20
+ type: 'none'
21
21
  };
22
- case "prefix":
22
+ case 'prefix':
23
23
  return {
24
- type: "prefix",
24
+ type: 'prefix',
25
25
  prefix: data.prefix
26
26
  };
27
- case "tags":
27
+ case 'tags':
28
28
  return {
29
- type: "tags",
29
+ type: 'tags',
30
30
  tags: data.tags
31
31
  };
32
- case "and":
32
+ case 'and':
33
33
  return {
34
- type: "and",
34
+ type: 'and',
35
35
  prefix: data.prefix,
36
36
  tags: data.tags
37
37
  };
@@ -40,13 +40,13 @@ function toFilterSpec(data) {
40
40
  function buildS3Filter(data) {
41
41
  const spec = toFilterSpec(data);
42
42
  switch(spec.type){
43
- case "none":
43
+ case 'none':
44
44
  return {};
45
- case "prefix":
45
+ case 'prefix':
46
46
  return {
47
47
  Prefix: spec.prefix
48
48
  };
49
- case "tags":
49
+ case 'tags':
50
50
  if (0 === spec.tags.length) return {};
51
51
  if (1 === spec.tags.length) return {
52
52
  Tag: {
@@ -62,9 +62,9 @@ function buildS3Filter(data) {
62
62
  }))
63
63
  }
64
64
  };
65
- case "and":
65
+ case 'and':
66
66
  {
67
- const hasPrefix = spec.prefix && "" !== spec.prefix.trim();
67
+ const hasPrefix = spec.prefix && '' !== spec.prefix.trim();
68
68
  const hasTags = spec.tags.length > 0;
69
69
  if (!hasTags && !hasPrefix) return {};
70
70
  if (!hasTags && hasPrefix) return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scality/data-browser-library",
3
- "version": "1.0.0-preview.9",
3
+ "version": "1.0.3",
4
4
  "description": "A modular React component library for browsing S3 buckets and objects",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -18,7 +18,9 @@
18
18
  "build": "rslib build",
19
19
  "dev": "rslib build --watch",
20
20
  "type-check": "tsc --noEmit",
21
- "lint": "eslint src --ext .ts,.tsx",
21
+ "lint": "biome check .",
22
+ "lint:fix": "biome check --write .",
23
+ "format": "biome format --write .",
22
24
  "test": "jest",
23
25
  "clean": "rm -rf dist"
24
26
  },
@@ -29,24 +31,24 @@
29
31
  "@aws-sdk/s3-request-presigner": "^3.478.0",
30
32
  "@hookform/resolvers": "^5.2.2",
31
33
  "@monaco-editor/react": "^4.7.0",
34
+ "@scality/zenkoclient": "^2.0.0-preview.1",
32
35
  "@tanstack/react-query": "^5.8.0",
33
36
  "@tanstack/react-query-devtools": "^5.8.0",
34
37
  "@testing-library/user-event": "^14.6.1",
35
38
  "joi": "^18.0.1",
36
39
  "react-dropzone": "^14.2.0",
37
- "react-hook-form": "^7.48.0",
38
- "@scality/zenkoclient": "^2.0.0-preview.1"
40
+ "react-hook-form": "^7.48.0"
39
41
  },
40
42
  "peerDependencies": {
41
- "@scality/core-ui": "^0.174.0",
43
+ "@scality/core-ui": "0.194.0",
42
44
  "react": ">=18.0.0",
43
45
  "react-dom": ">=18.0.0",
44
46
  "react-router-dom": ">=6.0.0",
45
47
  "styled-components": "^5.0.0"
46
48
  },
47
49
  "devDependencies": {
48
- "@rsbuild/plugin-react": "^1.4.1",
49
- "@rslib/core": "^0.14.0",
50
+ "@rsbuild/plugin-react": "^1.4.2",
51
+ "@rslib/core": "^0.18.4",
50
52
  "@testing-library/jest-dom": "^6.8.0",
51
53
  "@testing-library/react": "^15.0.6",
52
54
  "@testing-library/user-event": "^14.6.1",
@@ -57,7 +59,7 @@
57
59
  "identity-obj-proxy": "^3.0.0",
58
60
  "jest": "^30.0.5",
59
61
  "jest-environment-jsdom": "^30.0.5",
60
- "msw": "^0.28.2",
62
+ "msw": "^2.12.3",
61
63
  "ts-jest": "^29.4.1"
62
64
  },
63
65
  "repository": {