@scality/data-browser-library 1.0.7 → 1.0.9
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/__tests__/BucketCorsPage.test.js +67 -9
- package/dist/components/__tests__/BucketDetails.test.js +1 -0
- package/dist/components/__tests__/BucketLifecycleFormPage.test.js +16 -11
- package/dist/components/__tests__/BucketNotificationFormPage.test.js +45 -0
- package/dist/components/__tests__/BucketOverview.test.js +92 -2
- package/dist/components/__tests__/BucketPolicyPage.test.js +70 -51
- package/dist/components/__tests__/BucketReplicationFormPage.test.js +18 -24
- package/dist/components/__tests__/ObjectList.test.js +43 -2
- package/dist/components/buckets/BucketConfigEditButton.d.ts +2 -0
- package/dist/components/buckets/BucketConfigEditButton.js +9 -3
- package/dist/components/buckets/BucketCorsPage.js +57 -20
- package/dist/components/buckets/BucketDetails.js +27 -2
- package/dist/components/buckets/BucketLifecycleFormPage.js +310 -270
- package/dist/components/buckets/BucketOverview.js +21 -18
- package/dist/components/buckets/BucketPolicyPage.js +119 -83
- package/dist/components/buckets/BucketReplicationFormPage.js +39 -29
- package/dist/components/buckets/BucketVersioning.js +16 -10
- package/dist/components/buckets/__tests__/BucketVersioning.test.js +76 -23
- package/dist/components/buckets/notifications/BucketNotificationFormPage.js +13 -5
- package/dist/components/objects/ObjectList.js +22 -25
- package/dist/components/objects/ObjectLock/EditRetentionButton.js +2 -2
- package/dist/components/objects/UploadButton.js +25 -15
- package/dist/config/__tests__/resolveBrandingTheme.test.d.ts +1 -0
- package/dist/config/__tests__/resolveBrandingTheme.test.js +96 -0
- package/dist/config/resolveBrandingTheme.d.ts +16 -0
- package/dist/config/resolveBrandingTheme.js +23 -0
- package/dist/config/types.d.ts +36 -0
- package/dist/hooks/factories/useCreateS3InfiniteQueryHook.js +2 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/objectOperations.d.ts +3 -3
- package/dist/hooks/objectOperations.js +3 -3
- package/dist/hooks/useBucketConfigEditor.d.ts +4 -4
- package/dist/hooks/useBucketConfigEditor.js +16 -31
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/test/mocks/esmOnlyModules.js +4 -0
- package/dist/types/index.d.ts +0 -1
- package/dist/utils/__tests__/proxyMiddleware.test.js +34 -0
- package/dist/utils/proxyMiddleware.js +2 -0
- package/package.json +4 -4
- package/dist/components/Editor.d.ts +0 -12
- package/dist/components/Editor.js +0 -28
- package/dist/types/monaco.d.ts +0 -13
- package/dist/types/monaco.js +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { JSONSchema7 } from 'json-schema';
|
|
2
2
|
import { useForm } from 'react-hook-form';
|
|
3
3
|
type FormValues = {
|
|
4
4
|
content: string;
|
|
@@ -13,10 +13,9 @@ export type BucketConfigEditorConfig = {
|
|
|
13
13
|
initialContent: string | undefined;
|
|
14
14
|
defaultTemplate: string;
|
|
15
15
|
isLoading: boolean;
|
|
16
|
-
notFoundErrorNames: string[];
|
|
17
16
|
errorInstance: Error | null;
|
|
18
17
|
validate: (content: string) => ValidationResult;
|
|
19
|
-
|
|
18
|
+
jsonSchema?: JSONSchema7;
|
|
20
19
|
};
|
|
21
20
|
export type BucketConfigEditorResult = {
|
|
22
21
|
bucketName: string;
|
|
@@ -24,8 +23,9 @@ export type BucketConfigEditorResult = {
|
|
|
24
23
|
content: string;
|
|
25
24
|
isCreateMode: boolean;
|
|
26
25
|
isValidFormat: boolean;
|
|
27
|
-
|
|
26
|
+
jsonSchema?: JSONSchema7;
|
|
28
27
|
navigateToBucket: () => void;
|
|
28
|
+
loadTemplate: () => void;
|
|
29
29
|
};
|
|
30
30
|
export declare const useBucketConfigEditor: (config: BucketConfigEditorConfig) => BucketConfigEditorResult;
|
|
31
31
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo } from "react";
|
|
2
2
|
import { useForm } from "react-hook-form";
|
|
3
|
+
import { isNotFoundError } from "../utils/errorHandling.js";
|
|
3
4
|
import { useDataBrowserNavigate } from "./useDataBrowserNavigate.js";
|
|
4
5
|
const useBucketConfigEditor = (config)=>{
|
|
5
6
|
const navigate = useDataBrowserNavigate();
|
|
@@ -12,12 +13,8 @@ const useBucketConfigEditor = (config)=>{
|
|
|
12
13
|
});
|
|
13
14
|
const { watch, reset } = form;
|
|
14
15
|
const content = watch('content');
|
|
15
|
-
const isCreateMode = useMemo(()=>
|
|
16
|
-
|
|
17
|
-
return config.notFoundErrorNames.some((name)=>config.errorInstance?.name === name);
|
|
18
|
-
}, [
|
|
19
|
-
config.errorInstance,
|
|
20
|
-
config.notFoundErrorNames
|
|
16
|
+
const isCreateMode = useMemo(()=>isNotFoundError(config.errorInstance), [
|
|
17
|
+
config.errorInstance
|
|
21
18
|
]);
|
|
22
19
|
const initialValue = useMemo(()=>{
|
|
23
20
|
if (config.initialContent) try {
|
|
@@ -26,10 +23,9 @@ const useBucketConfigEditor = (config)=>{
|
|
|
26
23
|
} catch {
|
|
27
24
|
return config.initialContent;
|
|
28
25
|
}
|
|
29
|
-
return
|
|
26
|
+
return '';
|
|
30
27
|
}, [
|
|
31
|
-
config.initialContent
|
|
32
|
-
config.defaultTemplate
|
|
28
|
+
config.initialContent
|
|
33
29
|
]);
|
|
34
30
|
useEffect(()=>{
|
|
35
31
|
reset({
|
|
@@ -43,40 +39,29 @@ const useBucketConfigEditor = (config)=>{
|
|
|
43
39
|
content,
|
|
44
40
|
config.validate
|
|
45
41
|
]);
|
|
46
|
-
const handleBeforeMount = useCallback((monaco)=>{
|
|
47
|
-
const jsonLanguage = monaco.languages.json;
|
|
48
|
-
if (jsonLanguage?.jsonDefaults) if (config.monacoSchema) jsonLanguage.jsonDefaults.setDiagnosticsOptions({
|
|
49
|
-
validate: true,
|
|
50
|
-
schemas: [
|
|
51
|
-
{
|
|
52
|
-
uri: 'http://myserver/schema.json',
|
|
53
|
-
fileMatch: [
|
|
54
|
-
'*'
|
|
55
|
-
],
|
|
56
|
-
schema: config.monacoSchema
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
});
|
|
60
|
-
else jsonLanguage.jsonDefaults.setDiagnosticsOptions({
|
|
61
|
-
validate: true
|
|
62
|
-
});
|
|
63
|
-
}, [
|
|
64
|
-
config.monacoSchema
|
|
65
|
-
]);
|
|
66
42
|
const navigateToBucket = useCallback(()=>{
|
|
67
43
|
navigate(`/buckets/${bucketName}`);
|
|
68
44
|
}, [
|
|
69
45
|
navigate,
|
|
70
46
|
bucketName
|
|
71
47
|
]);
|
|
48
|
+
const loadTemplate = useCallback(()=>{
|
|
49
|
+
form.setValue('content', config.defaultTemplate, {
|
|
50
|
+
shouldDirty: true
|
|
51
|
+
});
|
|
52
|
+
}, [
|
|
53
|
+
form,
|
|
54
|
+
config.defaultTemplate
|
|
55
|
+
]);
|
|
72
56
|
return {
|
|
73
57
|
bucketName,
|
|
74
58
|
form,
|
|
75
59
|
content,
|
|
76
60
|
isCreateMode,
|
|
77
61
|
isValidFormat,
|
|
78
|
-
|
|
79
|
-
navigateToBucket
|
|
62
|
+
jsonSchema: config.jsonSchema,
|
|
63
|
+
navigateToBucket,
|
|
64
|
+
loadTemplate
|
|
80
65
|
};
|
|
81
66
|
};
|
|
82
67
|
export { useBucketConfigEditor };
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/types/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ import type { S3ClientConfig } from '@aws-sdk/client-s3';
|
|
|
2
2
|
import type { AwsCredentialIdentity } from '@aws-sdk/types';
|
|
3
3
|
import type { ProxyConfiguration, S3EventType } from '../config/types';
|
|
4
4
|
export type { _Object, Bucket, BucketCannedACL, BucketLocationConstraint, CopyObjectCommandInput, CopyObjectCommandOutput, CreateBucketCommandInput, CreateBucketCommandOutput, DeleteBucketCommandInput, DeleteBucketCommandOutput, DeleteBucketCorsCommandOutput, DeleteBucketLifecycleCommandOutput, DeleteBucketPolicyCommandOutput, DeleteBucketReplicationCommandOutput, DeleteBucketTaggingCommandOutput, DeleteMarkerEntry, DeleteObjectCommandInput, DeleteObjectCommandOutput, DeleteObjectsCommandInput, DeleteObjectsCommandOutput, DeleteObjectTaggingCommandOutput, GetBucketAclCommandOutput, GetBucketCorsCommandOutput, GetBucketEncryptionCommandOutput, GetBucketLifecycleConfigurationCommandOutput, GetBucketLocationCommandInput, GetBucketLocationCommandOutput, GetBucketNotificationConfigurationCommandOutput, GetBucketPolicyCommandOutput, GetBucketReplicationCommandOutput, GetBucketTaggingCommandOutput, GetBucketVersioningCommandOutput, GetObjectAclCommandOutput, GetObjectAttributesCommandInput, GetObjectAttributesCommandOutput, GetObjectCommandInput, GetObjectCommandOutput, GetObjectLegalHoldCommandOutput, GetObjectLockConfigurationCommandOutput, GetObjectRetentionCommandOutput, GetObjectTaggingCommandOutput, GetObjectTorrentCommandOutput, HeadObjectCommandInput, HeadObjectCommandOutput, ListBucketsCommandOutput, ListMultipartUploadsCommandInput, ListMultipartUploadsCommandOutput, ListObjectsV2CommandInput, ListObjectsV2CommandOutput, ListObjectVersionsCommandInput, ListObjectVersionsCommandOutput, ObjectCannedACL, ObjectVersion, Owner, PutBucketAclCommandInput, PutBucketCorsCommandInput, PutBucketEncryptionCommandInput, PutBucketLifecycleConfigurationCommandInput, PutBucketNotificationConfigurationCommandInput, PutBucketPolicyCommandInput, PutBucketReplicationCommandInput, PutBucketTaggingCommandInput, PutBucketTaggingCommandOutput, PutBucketVersioningCommandInput, PutObjectAclCommandInput, PutObjectCommandInput, PutObjectCommandOutput, PutObjectLegalHoldCommandInput, PutObjectLockConfigurationCommandInput, PutObjectRetentionCommandInput, PutObjectTaggingCommandInput, RestoreObjectCommandInput, RestoreObjectCommandOutput, SelectObjectContentCommandInput, SelectObjectContentCommandOutput, Tag, } from '@aws-sdk/client-s3';
|
|
5
|
-
export type { MonacoJsonDefaults, MonacoLanguagesJson } from './monaco';
|
|
6
5
|
/**
|
|
7
6
|
* S3 backend capabilities configuration.
|
|
8
7
|
*/
|
|
@@ -333,12 +333,45 @@ describe('createProxyMiddleware', ()=>{
|
|
|
333
333
|
expect(mockRequest.protocol).toBe('http:');
|
|
334
334
|
expect(mockRequest.path).toBe('/api/s3/bucket/key');
|
|
335
335
|
expect(mockRequest.headers.host).toBe('localhost:3000');
|
|
336
|
+
expect(mockRequest.headers['x-s3-target-endpoint']).toBe('https://s3.amazonaws.com');
|
|
336
337
|
expect(mockRequest.query).toEqual({
|
|
337
338
|
param: 'value'
|
|
338
339
|
});
|
|
339
340
|
expect(mockRequest.headers.authorization).toBe('AWS4-HMAC-SHA256 Credential=...');
|
|
340
341
|
expect(mockNext).toHaveBeenCalledTimes(1);
|
|
341
342
|
});
|
|
343
|
+
it('should set X-S3-Target-Endpoint header with custom port', async ()=>{
|
|
344
|
+
const mockNext = jest.fn().mockResolvedValue({
|
|
345
|
+
output: {}
|
|
346
|
+
});
|
|
347
|
+
const mockStack = {
|
|
348
|
+
add: jest.fn((middleware, config)=>{
|
|
349
|
+
if ('finalizeRequest' === config.step) mockStack.postSigningMiddleware = middleware;
|
|
350
|
+
}),
|
|
351
|
+
postSigningMiddleware: null
|
|
352
|
+
};
|
|
353
|
+
const middleware = createProxyMiddleware({
|
|
354
|
+
enabled: true,
|
|
355
|
+
endpoint: 'http://localhost:3000/api/s3',
|
|
356
|
+
target: 'http://s3.local:9000'
|
|
357
|
+
});
|
|
358
|
+
middleware.applyToStack(mockStack);
|
|
359
|
+
const postSigningMiddleware = mockStack.postSigningMiddleware(mockNext);
|
|
360
|
+
const mockRequest = new HttpRequest({
|
|
361
|
+
hostname: 's3.local',
|
|
362
|
+
port: 9000,
|
|
363
|
+
path: '/bucket/key',
|
|
364
|
+
protocol: 'http:',
|
|
365
|
+
headers: {
|
|
366
|
+
host: 's3.local:9000'
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
await postSigningMiddleware({
|
|
370
|
+
request: mockRequest,
|
|
371
|
+
input: {}
|
|
372
|
+
});
|
|
373
|
+
expect(mockRequest.headers['x-s3-target-endpoint']).toBe('http://s3.local:9000');
|
|
374
|
+
});
|
|
342
375
|
it('should preserve authorization header when routing through proxy', async ()=>{
|
|
343
376
|
const mockNext = jest.fn().mockResolvedValue({
|
|
344
377
|
output: {}
|
|
@@ -574,6 +607,7 @@ describe('createProxyMiddleware', ()=>{
|
|
|
574
607
|
expect(mockRequest.hostname).toBe(originalHostname);
|
|
575
608
|
expect(mockRequest.path).toBe(originalPath);
|
|
576
609
|
expect(mockRequest.port).toBe(originalPort);
|
|
610
|
+
expect(mockRequest.headers['x-s3-target-endpoint']).toBeUndefined();
|
|
577
611
|
});
|
|
578
612
|
});
|
|
579
613
|
});
|
|
@@ -52,6 +52,7 @@ const createProxyMiddleware = (config)=>{
|
|
|
52
52
|
const resolvedProxyEndpoint = resolveProxyEndpoint(config.endpoint);
|
|
53
53
|
const target = parseEndpoint(config.target);
|
|
54
54
|
const proxy = parseEndpoint(resolvedProxyEndpoint);
|
|
55
|
+
const targetEndpointUrl = `${target.protocol}//${target.hostname}${80 !== target.port && 443 !== target.port ? `:${target.port}` : ''}`;
|
|
55
56
|
return {
|
|
56
57
|
applyToStack: (clientStack)=>{
|
|
57
58
|
const preSigningMiddleware = (next)=>async (args)=>{
|
|
@@ -90,6 +91,7 @@ const createProxyMiddleware = (config)=>{
|
|
|
90
91
|
request.protocol = proxy.protocol;
|
|
91
92
|
request.path = '' === proxy.pathname || '/' === proxy.pathname ? request.path : proxy.pathname + request.path;
|
|
92
93
|
request.headers.host = proxy.port && 80 !== proxy.port && 443 !== proxy.port ? `${proxy.hostname}:${proxy.port}` : proxy.hostname;
|
|
94
|
+
request.headers['x-s3-target-endpoint'] = targetEndpointUrl;
|
|
93
95
|
request.query = queryParams;
|
|
94
96
|
}
|
|
95
97
|
return next(args);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scality/data-browser-library",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
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",
|
|
@@ -30,8 +30,7 @@
|
|
|
30
30
|
"@aws-sdk/s3-presigned-post": "^3.983.0",
|
|
31
31
|
"@aws-sdk/s3-request-presigner": "^3.983.0",
|
|
32
32
|
"@hookform/resolvers": "^5.2.2",
|
|
33
|
-
"@
|
|
34
|
-
"@scality/zenkoclient": "^2.0.0-preview.1",
|
|
33
|
+
"@scality/cloudserverclient": "^1.0.4",
|
|
35
34
|
"@tanstack/react-query": "^5.8.0",
|
|
36
35
|
"@tanstack/react-query-devtools": "^5.8.0",
|
|
37
36
|
"@testing-library/user-event": "^14.6.1",
|
|
@@ -40,7 +39,7 @@
|
|
|
40
39
|
"react-hook-form": "^7.48.0"
|
|
41
40
|
},
|
|
42
41
|
"peerDependencies": {
|
|
43
|
-
"@scality/core-ui": ">=0.
|
|
42
|
+
"@scality/core-ui": ">=0.202.0",
|
|
44
43
|
"react": ">=18.0.0",
|
|
45
44
|
"react-dom": ">=18.0.0",
|
|
46
45
|
"react-router": ">=7.1.3",
|
|
@@ -54,6 +53,7 @@
|
|
|
54
53
|
"@testing-library/react": "^15.0.6",
|
|
55
54
|
"@testing-library/user-event": "^14.6.1",
|
|
56
55
|
"@types/jest": "^30.0.0",
|
|
56
|
+
"@types/json-schema": "^7.0.15",
|
|
57
57
|
"@types/react": "^18.2.0",
|
|
58
58
|
"@types/react-dom": "^18.2.0",
|
|
59
59
|
"@types/styled-components": "^5.1.34",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { type BeforeMount, type EditorProps } from '@monaco-editor/react';
|
|
2
|
-
interface EditorComponentProps {
|
|
3
|
-
value: string;
|
|
4
|
-
onChange: (value: string | undefined) => void;
|
|
5
|
-
readOnly?: boolean;
|
|
6
|
-
language?: string;
|
|
7
|
-
height?: string;
|
|
8
|
-
width?: string;
|
|
9
|
-
beforeMount?: BeforeMount;
|
|
10
|
-
}
|
|
11
|
-
export declare const Editor: React.FC<EditorComponentProps & EditorProps>;
|
|
12
|
-
export {};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import react from "@monaco-editor/react";
|
|
3
|
-
const Editor = ({ value, onChange, readOnly = false, language = 'json', height = '400px', width = '100%', beforeMount, ...rest })=>{
|
|
4
|
-
const editorTheme = 'vs-dark';
|
|
5
|
-
return /*#__PURE__*/ jsx(react, {
|
|
6
|
-
height: height,
|
|
7
|
-
width: width,
|
|
8
|
-
language: language,
|
|
9
|
-
value: value,
|
|
10
|
-
theme: editorTheme,
|
|
11
|
-
onChange: onChange,
|
|
12
|
-
options: {
|
|
13
|
-
readOnly,
|
|
14
|
-
scrollBeyondLastLine: false,
|
|
15
|
-
minimap: {
|
|
16
|
-
enabled: false
|
|
17
|
-
},
|
|
18
|
-
fontSize: 12,
|
|
19
|
-
lineNumbers: 'on',
|
|
20
|
-
automaticLayout: true,
|
|
21
|
-
formatOnPaste: true,
|
|
22
|
-
formatOnType: true
|
|
23
|
-
},
|
|
24
|
-
beforeMount: beforeMount,
|
|
25
|
-
...rest
|
|
26
|
-
});
|
|
27
|
-
};
|
|
28
|
-
export { Editor };
|
package/dist/types/monaco.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export interface MonacoJsonDefaults {
|
|
2
|
-
setDiagnosticsOptions(options: {
|
|
3
|
-
validate: boolean;
|
|
4
|
-
schemas?: Array<{
|
|
5
|
-
uri: string;
|
|
6
|
-
fileMatch: string[];
|
|
7
|
-
schema: unknown;
|
|
8
|
-
}>;
|
|
9
|
-
}): void;
|
|
10
|
-
}
|
|
11
|
-
export interface MonacoLanguagesJson {
|
|
12
|
-
jsonDefaults: MonacoJsonDefaults;
|
|
13
|
-
}
|
package/dist/types/monaco.js
DELETED
|
File without changes
|