@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,236 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
3
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
4
|
+
import { renderHook } from "@testing-library/react";
|
|
5
|
+
import "react";
|
|
6
|
+
import { DataBrowserProvider } from "../components/providers/DataBrowserProvider.js";
|
|
7
|
+
import { coreUIAvailableThemes } from "@scality/core-ui/dist/style/theme";
|
|
8
|
+
import { CoreUiThemeProvider } from "@scality/core-ui/dist/next";
|
|
9
|
+
import { ToastProvider } from "@scality/core-ui";
|
|
10
|
+
import { overrideHandlers, setupMswServer } from "./msw/index.js";
|
|
11
|
+
var __webpack_require__ = {};
|
|
12
|
+
(()=>{
|
|
13
|
+
__webpack_require__.g = (()=>{
|
|
14
|
+
if ('object' == typeof globalThis) return globalThis;
|
|
15
|
+
try {
|
|
16
|
+
return this || new Function('return this')();
|
|
17
|
+
} catch (e) {
|
|
18
|
+
if ('object' == typeof window) return window;
|
|
19
|
+
}
|
|
20
|
+
})();
|
|
21
|
+
})();
|
|
22
|
+
const testConfig = {
|
|
23
|
+
endpoint: "https://s3.amazonaws.com",
|
|
24
|
+
region: "us-east-1",
|
|
25
|
+
forcePathStyle: false
|
|
26
|
+
};
|
|
27
|
+
const testCredentials = {
|
|
28
|
+
accessKeyId: "test-access-key",
|
|
29
|
+
secretAccessKey: "test-secret-key",
|
|
30
|
+
sessionToken: "test-session-token"
|
|
31
|
+
};
|
|
32
|
+
const mockS3Client = {
|
|
33
|
+
send: jest.fn()
|
|
34
|
+
};
|
|
35
|
+
const MockedS3Client = S3Client;
|
|
36
|
+
const MockedPutObjectCommand = PutObjectCommand;
|
|
37
|
+
function mockOffsetSize(width, height) {
|
|
38
|
+
__webpack_require__.g.ResizeObserver = jest.fn().mockImplementation(()=>({
|
|
39
|
+
observe: jest.fn(),
|
|
40
|
+
unobserve: jest.fn(),
|
|
41
|
+
disconnect: jest.fn()
|
|
42
|
+
}));
|
|
43
|
+
Element.prototype.getBoundingClientRect = jest.fn(()=>({
|
|
44
|
+
width: width || 800,
|
|
45
|
+
height: height || 600,
|
|
46
|
+
top: 0,
|
|
47
|
+
left: 0,
|
|
48
|
+
bottom: height || 600,
|
|
49
|
+
right: width || 800,
|
|
50
|
+
x: 0,
|
|
51
|
+
y: 0,
|
|
52
|
+
toJSON: jest.fn()
|
|
53
|
+
}));
|
|
54
|
+
Object.defineProperties(window.HTMLElement.prototype, {
|
|
55
|
+
offsetHeight: {
|
|
56
|
+
get: ()=>height || 600,
|
|
57
|
+
configurable: true
|
|
58
|
+
},
|
|
59
|
+
offsetWidth: {
|
|
60
|
+
get: ()=>width || 800,
|
|
61
|
+
configurable: true
|
|
62
|
+
},
|
|
63
|
+
scrollHeight: {
|
|
64
|
+
get: ()=>height || 600,
|
|
65
|
+
configurable: true
|
|
66
|
+
},
|
|
67
|
+
scrollWidth: {
|
|
68
|
+
get: ()=>width || 800,
|
|
69
|
+
configurable: true
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const mockComputedStyle = {
|
|
73
|
+
fontSize: "14px",
|
|
74
|
+
paddingLeft: "0px",
|
|
75
|
+
paddingRight: "0px",
|
|
76
|
+
paddingTop: "0px",
|
|
77
|
+
paddingBottom: "0px",
|
|
78
|
+
getPropertyValue: jest.fn((prop)=>{
|
|
79
|
+
const styles = {
|
|
80
|
+
"font-size": "14px",
|
|
81
|
+
"padding-left": "0px",
|
|
82
|
+
"padding-right": "0px",
|
|
83
|
+
"padding-top": "0px",
|
|
84
|
+
"padding-bottom": "0px"
|
|
85
|
+
};
|
|
86
|
+
return styles[prop] || "";
|
|
87
|
+
})
|
|
88
|
+
};
|
|
89
|
+
jest.spyOn(window, "getComputedStyle").mockImplementation(()=>mockComputedStyle);
|
|
90
|
+
}
|
|
91
|
+
const createQueryWrapper = ()=>{
|
|
92
|
+
const queryClient = new QueryClient({
|
|
93
|
+
defaultOptions: {
|
|
94
|
+
queries: {
|
|
95
|
+
retry: false
|
|
96
|
+
},
|
|
97
|
+
mutations: {
|
|
98
|
+
retry: false
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
const theme = coreUIAvailableThemes.darkRebrand;
|
|
103
|
+
return ({ children })=>/*#__PURE__*/ jsx(QueryClientProvider, {
|
|
104
|
+
client: queryClient,
|
|
105
|
+
children: /*#__PURE__*/ jsx(CoreUiThemeProvider, {
|
|
106
|
+
theme: theme,
|
|
107
|
+
children: children
|
|
108
|
+
})
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
const createTestWrapper = (config = testConfig, credentials = testCredentials)=>{
|
|
112
|
+
const queryClient = new QueryClient({
|
|
113
|
+
defaultOptions: {
|
|
114
|
+
queries: {
|
|
115
|
+
retry: false
|
|
116
|
+
},
|
|
117
|
+
mutations: {
|
|
118
|
+
retry: false
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
const getConfig = ()=>({
|
|
123
|
+
...config,
|
|
124
|
+
credentials
|
|
125
|
+
});
|
|
126
|
+
const theme = coreUIAvailableThemes.darkRebrand;
|
|
127
|
+
return ({ children })=>/*#__PURE__*/ jsx(DataBrowserProvider, {
|
|
128
|
+
queryClient: queryClient,
|
|
129
|
+
getS3Config: getConfig,
|
|
130
|
+
theme: theme,
|
|
131
|
+
enableDevtools: false,
|
|
132
|
+
children: /*#__PURE__*/ jsx(CoreUiThemeProvider, {
|
|
133
|
+
theme: theme,
|
|
134
|
+
children: /*#__PURE__*/ jsx(ToastProvider, {
|
|
135
|
+
children: children
|
|
136
|
+
})
|
|
137
|
+
})
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
const renderHookWithWrapper = (hook, options)=>{
|
|
141
|
+
const { config, credentials, ...renderOptions } = options || {};
|
|
142
|
+
return renderHook(hook, {
|
|
143
|
+
wrapper: createTestWrapper(config, credentials),
|
|
144
|
+
...renderOptions
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
const createTestFile = (name, content, type = "text/plain")=>new File([
|
|
148
|
+
content
|
|
149
|
+
], name, {
|
|
150
|
+
type
|
|
151
|
+
});
|
|
152
|
+
const setupS3Mocks = ()=>{
|
|
153
|
+
jest.clearAllMocks();
|
|
154
|
+
MockedS3Client.mockImplementation(()=>mockS3Client);
|
|
155
|
+
MockedPutObjectCommand.mockImplementation((input)=>({
|
|
156
|
+
input,
|
|
157
|
+
resolveMiddleware: jest.fn()
|
|
158
|
+
}));
|
|
159
|
+
};
|
|
160
|
+
const setupCommonMocks = ()=>{
|
|
161
|
+
setupS3Mocks();
|
|
162
|
+
};
|
|
163
|
+
const overrideGlobalConfig = (overrides)=>{
|
|
164
|
+
const currentS3 = globalThis.__S3_CONFIG__;
|
|
165
|
+
const currentDev = globalThis.__DEV_CONFIG__;
|
|
166
|
+
if (overrides.s3) globalThis.__S3_CONFIG__ = {
|
|
167
|
+
...currentS3,
|
|
168
|
+
...overrides.s3
|
|
169
|
+
};
|
|
170
|
+
if (overrides.dev) globalThis.__DEV_CONFIG__ = {
|
|
171
|
+
...currentDev,
|
|
172
|
+
...overrides.dev
|
|
173
|
+
};
|
|
174
|
+
if (overrides.environment) {
|
|
175
|
+
if (void 0 !== overrides.environment.isDevelopment) globalThis.__IS_DEVELOPMENT__ = overrides.environment.isDevelopment;
|
|
176
|
+
if (void 0 !== overrides.environment.isProduction) globalThis.__IS_PRODUCTION__ = overrides.environment.isProduction;
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
const resetGlobalConfig = ()=>{
|
|
180
|
+
globalThis.__S3_CONFIG__ = {
|
|
181
|
+
endpoint: "http://localhost:8000",
|
|
182
|
+
region: "us-east-1",
|
|
183
|
+
realHost: "s3.amazonaws.com",
|
|
184
|
+
forcePathStyle: true
|
|
185
|
+
};
|
|
186
|
+
globalThis.__DEV_CONFIG__ = {
|
|
187
|
+
useProxy: false,
|
|
188
|
+
proxyEndpoint: "http://localhost:3000/api/s3",
|
|
189
|
+
proxyBasePath: "/api/s3",
|
|
190
|
+
proxyHost: "localhost",
|
|
191
|
+
proxyPort: 3000
|
|
192
|
+
};
|
|
193
|
+
globalThis.__IS_DEVELOPMENT__ = true;
|
|
194
|
+
globalThis.__IS_PRODUCTION__ = false;
|
|
195
|
+
};
|
|
196
|
+
const withGlobalConfig = (overrides, testFn)=>async ()=>{
|
|
197
|
+
overrideGlobalConfig(overrides);
|
|
198
|
+
try {
|
|
199
|
+
await testFn();
|
|
200
|
+
} finally{
|
|
201
|
+
resetGlobalConfig();
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const validateFactoryHook = (hook, operationName)=>{
|
|
205
|
+
if ("function" != typeof hook) throw createFactoryTestError("Factory Validation", operationName, "hook should be a function - check if useCreate*Hook factory is properly returning a hook function");
|
|
206
|
+
};
|
|
207
|
+
const createFactoryTestError = (testContext, operationName, details)=>new Error(`Factory Test Failure [${testContext}]: ${operationName} - ${details || "Unknown error"}. Check factory implementation and hook usage patterns.`);
|
|
208
|
+
const validateHookResult = (result, hookType)=>{
|
|
209
|
+
const commonProps = [
|
|
210
|
+
"isError",
|
|
211
|
+
"isSuccess",
|
|
212
|
+
"data",
|
|
213
|
+
"error"
|
|
214
|
+
];
|
|
215
|
+
const queryProps = [
|
|
216
|
+
"isLoading"
|
|
217
|
+
];
|
|
218
|
+
const mutationProps = [
|
|
219
|
+
"mutate",
|
|
220
|
+
"mutateAsync",
|
|
221
|
+
"isPending"
|
|
222
|
+
];
|
|
223
|
+
const infiniteProps = [
|
|
224
|
+
"hasNextPage",
|
|
225
|
+
"fetchNextPage",
|
|
226
|
+
"isFetchingNextPage"
|
|
227
|
+
];
|
|
228
|
+
const expectedProps = [
|
|
229
|
+
...commonProps,
|
|
230
|
+
..."query" === hookType ? queryProps : [],
|
|
231
|
+
..."mutation" === hookType ? mutationProps : [],
|
|
232
|
+
..."infiniteQuery" === hookType ? infiniteProps : []
|
|
233
|
+
];
|
|
234
|
+
for (const prop of expectedProps)if (!(prop in result)) throw createFactoryTestError("Hook Validation", hookType, `Missing property '${prop}' - check if factory is returning proper React Query hook result`);
|
|
235
|
+
};
|
|
236
|
+
export { MockedPutObjectCommand, MockedS3Client, createFactoryTestError, createQueryWrapper, createTestFile, createTestWrapper, mockOffsetSize, mockS3Client, overrideGlobalConfig, overrideHandlers, renderHookWithWrapper, resetGlobalConfig, setupCommonMocks, setupMswServer, setupS3Mocks, testConfig, testCredentials, validateFactoryHook, validateHookResult, withGlobalConfig };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
import { EnhancedS3Error, ErrorCategory, createS3Error, createS3OperationError, isEnhancedS3Error, isS3ServiceException, shouldRetryError } from "../../utils/errorHandling.js";
|
|
2
|
+
const TEST_CONSTANTS = {
|
|
3
|
+
REQUEST_ID: "test-request-id",
|
|
4
|
+
ATTEMPTS: 1,
|
|
5
|
+
RETRY_DELAY: 0,
|
|
6
|
+
BUCKET: "test-bucket",
|
|
7
|
+
KEY: "test-key",
|
|
8
|
+
MESSAGES: {
|
|
9
|
+
NO_SUCH_BUCKET: "The specified bucket does not exist",
|
|
10
|
+
NO_SUCH_KEY: "The specified key does not exist",
|
|
11
|
+
INVALID_REQUEST: "Invalid request",
|
|
12
|
+
ACCESS_DENIED: "Access denied",
|
|
13
|
+
INTERNAL_ERROR: "Internal error",
|
|
14
|
+
NETWORK_FAILED: "Network connection failed",
|
|
15
|
+
SERVICE_UNAVAILABLE: "Service temporarily unavailable"
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const createMockAWSError = (errorType, message, statusCode = 500)=>{
|
|
19
|
+
const error = new Error(message);
|
|
20
|
+
Object.defineProperty(error, "name", {
|
|
21
|
+
value: errorType,
|
|
22
|
+
writable: true
|
|
23
|
+
});
|
|
24
|
+
error.$metadata = {
|
|
25
|
+
httpStatusCode: statusCode,
|
|
26
|
+
requestId: TEST_CONSTANTS.REQUEST_ID,
|
|
27
|
+
attempts: TEST_CONSTANTS.ATTEMPTS,
|
|
28
|
+
totalRetryDelay: TEST_CONSTANTS.RETRY_DELAY
|
|
29
|
+
};
|
|
30
|
+
return error;
|
|
31
|
+
};
|
|
32
|
+
const TestErrors = {
|
|
33
|
+
noSuchBucket: ()=>createMockAWSError("NoSuchBucket", TEST_CONSTANTS.MESSAGES.NO_SUCH_BUCKET, 404),
|
|
34
|
+
noSuchKey: ()=>createMockAWSError("NoSuchKey", TEST_CONSTANTS.MESSAGES.NO_SUCH_KEY, 404),
|
|
35
|
+
invalidRequest: ()=>createMockAWSError("InvalidRequest", TEST_CONSTANTS.MESSAGES.INVALID_REQUEST, 400),
|
|
36
|
+
accessDenied: ()=>createMockAWSError("AccessDenied", TEST_CONSTANTS.MESSAGES.ACCESS_DENIED, 403),
|
|
37
|
+
internalError: ()=>createMockAWSError("InternalError", TEST_CONSTANTS.MESSAGES.INTERNAL_ERROR, 500),
|
|
38
|
+
serviceUnavailable: ()=>createMockAWSError("ServiceUnavailable", TEST_CONSTANTS.MESSAGES.SERVICE_UNAVAILABLE, 503),
|
|
39
|
+
abortError: ()=>{
|
|
40
|
+
const error = new Error("Operation aborted");
|
|
41
|
+
Object.defineProperty(error, "name", {
|
|
42
|
+
value: "AbortError",
|
|
43
|
+
writable: true
|
|
44
|
+
});
|
|
45
|
+
return error;
|
|
46
|
+
},
|
|
47
|
+
networkError: ()=>new Error(TEST_CONSTANTS.MESSAGES.NETWORK_FAILED),
|
|
48
|
+
timeoutError: ()=>{
|
|
49
|
+
const error = new Error("Request timeout");
|
|
50
|
+
Object.defineProperty(error, "name", {
|
|
51
|
+
value: "TimeoutError",
|
|
52
|
+
writable: true
|
|
53
|
+
});
|
|
54
|
+
return error;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
const TestEnhancedErrors = {
|
|
58
|
+
server: ()=>new EnhancedS3Error("Server error", "ServerError", ErrorCategory.SERVER_ERROR, new Error()),
|
|
59
|
+
network: ()=>new EnhancedS3Error("Network error", "NetworkError", ErrorCategory.NETWORK_ERROR, new Error()),
|
|
60
|
+
client: ()=>new EnhancedS3Error("Client error", "ClientError", ErrorCategory.CLIENT_ERROR, new Error()),
|
|
61
|
+
auth: ()=>new EnhancedS3Error("Auth error", "AuthError", ErrorCategory.AUTHORIZATION, new Error()),
|
|
62
|
+
notFound: ()=>new EnhancedS3Error("Not found", "NotFoundError", ErrorCategory.NOT_FOUND, new Error()),
|
|
63
|
+
cancelled: ()=>new EnhancedS3Error("Cancelled", "CancelError", ErrorCategory.CANCELLATION, new Error()),
|
|
64
|
+
unknown: ()=>new EnhancedS3Error("Unknown", "UnknownError", ErrorCategory.UNKNOWN, new Error())
|
|
65
|
+
};
|
|
66
|
+
describe("ErrorCategory", ()=>{
|
|
67
|
+
test("contains all expected categories", ()=>{
|
|
68
|
+
expect(ErrorCategory.CLIENT_ERROR).toBe("CLIENT_ERROR");
|
|
69
|
+
expect(ErrorCategory.SERVER_ERROR).toBe("SERVER_ERROR");
|
|
70
|
+
expect(ErrorCategory.NETWORK_ERROR).toBe("NETWORK_ERROR");
|
|
71
|
+
expect(ErrorCategory.CANCELLATION).toBe("CANCELLATION");
|
|
72
|
+
expect(ErrorCategory.AUTHORIZATION).toBe("AUTHORIZATION");
|
|
73
|
+
expect(ErrorCategory.NOT_FOUND).toBe("NOT_FOUND");
|
|
74
|
+
expect(ErrorCategory.UNKNOWN).toBe("UNKNOWN");
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
describe("EnhancedS3Error", ()=>{
|
|
78
|
+
test("creates error with all properties", ()=>{
|
|
79
|
+
const originalError = new Error("Original error");
|
|
80
|
+
const metadata = {
|
|
81
|
+
httpStatusCode: 400,
|
|
82
|
+
requestId: TEST_CONSTANTS.REQUEST_ID,
|
|
83
|
+
attempts: TEST_CONSTANTS.ATTEMPTS,
|
|
84
|
+
totalRetryDelay: TEST_CONSTANTS.RETRY_DELAY
|
|
85
|
+
};
|
|
86
|
+
const context = {
|
|
87
|
+
operation: "test",
|
|
88
|
+
bucket: TEST_CONSTANTS.BUCKET
|
|
89
|
+
};
|
|
90
|
+
const error = new EnhancedS3Error("Test error", "TestError", ErrorCategory.CLIENT_ERROR, originalError, 400, metadata, context);
|
|
91
|
+
expect(error.message).toBe("Test error");
|
|
92
|
+
expect(error.name).toBe("TestError");
|
|
93
|
+
expect(error.category).toBe(ErrorCategory.CLIENT_ERROR);
|
|
94
|
+
expect(error.statusCode).toBe(400);
|
|
95
|
+
expect(error.metadata).toBe(metadata);
|
|
96
|
+
expect(error.originalError).toBe(originalError);
|
|
97
|
+
expect(error.context).toBe(context);
|
|
98
|
+
expect(error instanceof Error).toBe(true);
|
|
99
|
+
expect(error instanceof EnhancedS3Error).toBe(true);
|
|
100
|
+
});
|
|
101
|
+
describe("shouldRetry", ()=>{
|
|
102
|
+
test("returns true for retryable categories", ()=>{
|
|
103
|
+
expect(TestEnhancedErrors.server().shouldRetry()).toBe(true);
|
|
104
|
+
expect(TestEnhancedErrors.network().shouldRetry()).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
test("returns false for non-retryable categories", ()=>{
|
|
107
|
+
expect(TestEnhancedErrors.client().shouldRetry()).toBe(false);
|
|
108
|
+
expect(TestEnhancedErrors.auth().shouldRetry()).toBe(false);
|
|
109
|
+
expect(TestEnhancedErrors.notFound().shouldRetry()).toBe(false);
|
|
110
|
+
expect(TestEnhancedErrors.cancelled().shouldRetry()).toBe(false);
|
|
111
|
+
expect(TestEnhancedErrors.unknown().shouldRetry()).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
describe("Type Guards", ()=>{
|
|
116
|
+
describe("isS3ServiceException", ()=>{
|
|
117
|
+
test("returns true for S3ServiceException", ()=>{
|
|
118
|
+
expect(isS3ServiceException(TestErrors.invalidRequest())).toBe(true);
|
|
119
|
+
});
|
|
120
|
+
test("returns false for regular Error", ()=>{
|
|
121
|
+
expect(isS3ServiceException(new Error("Regular error"))).toBe(false);
|
|
122
|
+
});
|
|
123
|
+
test("returns false for non-Error objects", ()=>{
|
|
124
|
+
expect(isS3ServiceException("string")).toBe(false);
|
|
125
|
+
expect(isS3ServiceException(null)).toBe(false);
|
|
126
|
+
expect(isS3ServiceException(void 0)).toBe(false);
|
|
127
|
+
expect(isS3ServiceException({})).toBe(false);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe("isEnhancedS3Error", ()=>{
|
|
131
|
+
test("returns true for EnhancedS3Error", ()=>{
|
|
132
|
+
expect(isEnhancedS3Error(TestEnhancedErrors.unknown())).toBe(true);
|
|
133
|
+
});
|
|
134
|
+
test("returns false for other error types", ()=>{
|
|
135
|
+
expect(isEnhancedS3Error(new Error("Regular error"))).toBe(false);
|
|
136
|
+
expect(isEnhancedS3Error(TestErrors.invalidRequest())).toBe(false);
|
|
137
|
+
expect(isEnhancedS3Error("string")).toBe(false);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe("createS3Error", ()=>{
|
|
142
|
+
test("handles AbortError", ()=>{
|
|
143
|
+
const abortError = TestErrors.abortError();
|
|
144
|
+
const result = createS3Error(abortError);
|
|
145
|
+
expect(result.message).toBe("Operation was cancelled");
|
|
146
|
+
expect(result.name).toBe("AbortError");
|
|
147
|
+
expect(result.category).toBe(ErrorCategory.CANCELLATION);
|
|
148
|
+
expect(result.originalError).toBe(abortError);
|
|
149
|
+
});
|
|
150
|
+
test("handles specific AWS errors", ()=>{
|
|
151
|
+
const testCases = [
|
|
152
|
+
{
|
|
153
|
+
error: TestErrors.noSuchBucket(),
|
|
154
|
+
expectedCategory: ErrorCategory.NOT_FOUND,
|
|
155
|
+
expectedName: "NoSuchBucket",
|
|
156
|
+
expectedStatus: 404
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
error: TestErrors.noSuchKey(),
|
|
160
|
+
expectedCategory: ErrorCategory.NOT_FOUND,
|
|
161
|
+
expectedName: "NoSuchKey",
|
|
162
|
+
expectedStatus: 404
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
error: TestErrors.invalidRequest(),
|
|
166
|
+
expectedCategory: ErrorCategory.CLIENT_ERROR,
|
|
167
|
+
expectedName: "InvalidRequest",
|
|
168
|
+
expectedStatus: 400
|
|
169
|
+
}
|
|
170
|
+
];
|
|
171
|
+
testCases.forEach(({ error, expectedCategory, expectedName, expectedStatus })=>{
|
|
172
|
+
const result = createS3Error(error);
|
|
173
|
+
expect(result.category).toBe(expectedCategory);
|
|
174
|
+
expect(result.name).toBe(expectedName);
|
|
175
|
+
expect(result.statusCode).toBe(expectedStatus);
|
|
176
|
+
expect(result.metadata).toBe(error.$metadata);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
test("handles status code classification", ()=>{
|
|
180
|
+
const testCases = [
|
|
181
|
+
{
|
|
182
|
+
error: TestErrors.accessDenied(),
|
|
183
|
+
expectedCategory: ErrorCategory.AUTHORIZATION
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
error: TestErrors.internalError(),
|
|
187
|
+
expectedCategory: ErrorCategory.SERVER_ERROR
|
|
188
|
+
}
|
|
189
|
+
];
|
|
190
|
+
testCases.forEach(({ error, expectedCategory })=>{
|
|
191
|
+
const result = createS3Error(error);
|
|
192
|
+
expect(result.category).toBe(expectedCategory);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
test("handles network errors", ()=>{
|
|
196
|
+
const testCases = [
|
|
197
|
+
TestErrors.networkError(),
|
|
198
|
+
TestErrors.timeoutError()
|
|
199
|
+
];
|
|
200
|
+
testCases.forEach((error)=>{
|
|
201
|
+
const result = createS3Error(error);
|
|
202
|
+
expect(result.category).toBe(ErrorCategory.NETWORK_ERROR);
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
test("handles edge cases", ()=>{
|
|
206
|
+
const testCases = [
|
|
207
|
+
{
|
|
208
|
+
input: new Error("Some error"),
|
|
209
|
+
expectedCategory: ErrorCategory.UNKNOWN,
|
|
210
|
+
expectedMessage: "Some error"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
input: "String error",
|
|
214
|
+
expectedCategory: ErrorCategory.UNKNOWN,
|
|
215
|
+
expectedMessage: "String error",
|
|
216
|
+
expectedName: "UnknownError"
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
input: null,
|
|
220
|
+
expectedCategory: ErrorCategory.UNKNOWN,
|
|
221
|
+
expectedMessage: "Unknown error occurred"
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
input: void 0,
|
|
225
|
+
expectedCategory: ErrorCategory.UNKNOWN,
|
|
226
|
+
expectedMessage: "Unknown error occurred"
|
|
227
|
+
}
|
|
228
|
+
];
|
|
229
|
+
testCases.forEach(({ input, expectedCategory, expectedMessage, expectedName })=>{
|
|
230
|
+
const result = createS3Error(input);
|
|
231
|
+
expect(result.category).toBe(expectedCategory);
|
|
232
|
+
expect(result.message).toBe(expectedMessage);
|
|
233
|
+
if (expectedName) expect(result.name).toBe(expectedName);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
test("preserves context", ()=>{
|
|
237
|
+
const context = {
|
|
238
|
+
operation: "test",
|
|
239
|
+
bucket: TEST_CONSTANTS.BUCKET
|
|
240
|
+
};
|
|
241
|
+
const result = createS3Error(new Error("Test error"), context);
|
|
242
|
+
expect(result.context).toBe(context);
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
describe("createS3OperationError", ()=>{
|
|
246
|
+
test("message modification scenarios", ()=>{
|
|
247
|
+
const testCases = [
|
|
248
|
+
{
|
|
249
|
+
name: "preserves existing operation in message",
|
|
250
|
+
error: new Error("ListObjectsV2 failed: Access denied"),
|
|
251
|
+
operation: "ListObjectsV2",
|
|
252
|
+
bucket: TEST_CONSTANTS.BUCKET,
|
|
253
|
+
expectedMessage: "ListObjectsV2 failed: Access denied"
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
name: "enhances message with operation context",
|
|
257
|
+
error: new Error(TEST_CONSTANTS.MESSAGES.ACCESS_DENIED),
|
|
258
|
+
operation: "GetObject",
|
|
259
|
+
bucket: TEST_CONSTANTS.BUCKET,
|
|
260
|
+
key: TEST_CONSTANTS.KEY,
|
|
261
|
+
expectedMessage: `GetObject failed for bucket '${TEST_CONSTANTS.BUCKET}', key '${TEST_CONSTANTS.KEY}': ${TEST_CONSTANTS.MESSAGES.ACCESS_DENIED}`
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
name: "handles operation without bucket",
|
|
265
|
+
error: new Error(TEST_CONSTANTS.MESSAGES.SERVICE_UNAVAILABLE),
|
|
266
|
+
operation: "ListBuckets",
|
|
267
|
+
expectedMessage: `ListBuckets failed: ${TEST_CONSTANTS.MESSAGES.SERVICE_UNAVAILABLE}`
|
|
268
|
+
}
|
|
269
|
+
];
|
|
270
|
+
testCases.forEach(({ error, operation, bucket, key, expectedMessage })=>{
|
|
271
|
+
const result = createS3OperationError(error, operation, bucket, key);
|
|
272
|
+
expect(result.message).toBe(expectedMessage);
|
|
273
|
+
expect(result.context).toEqual({
|
|
274
|
+
operation,
|
|
275
|
+
bucketName: bucket || void 0,
|
|
276
|
+
objectKey: key || void 0,
|
|
277
|
+
timestamp: expect.any(String)
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
test("preserves all error properties", ()=>{
|
|
282
|
+
const originalError = TestErrors.noSuchBucket();
|
|
283
|
+
const result = createS3OperationError(originalError, "HeadObject", TEST_CONSTANTS.BUCKET, TEST_CONSTANTS.KEY);
|
|
284
|
+
expect(result.category).toBe(ErrorCategory.NOT_FOUND);
|
|
285
|
+
expect(result.statusCode).toBe(404);
|
|
286
|
+
expect(result.metadata).toBe(originalError.$metadata);
|
|
287
|
+
expect(result.originalError).toBe(originalError);
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
describe("shouldRetryError", ()=>{
|
|
291
|
+
test("respects maxRetries limit", ()=>{
|
|
292
|
+
const retryableError = TestEnhancedErrors.server();
|
|
293
|
+
const maxRetries = 3;
|
|
294
|
+
expect(shouldRetryError(retryableError, 0, maxRetries)).toBe(true);
|
|
295
|
+
expect(shouldRetryError(retryableError, 2, maxRetries)).toBe(true);
|
|
296
|
+
expect(shouldRetryError(retryableError, 3, maxRetries)).toBe(false);
|
|
297
|
+
expect(shouldRetryError(retryableError, 5, maxRetries)).toBe(false);
|
|
298
|
+
});
|
|
299
|
+
test("uses error category for retry decision", ()=>{
|
|
300
|
+
const testCases = [
|
|
301
|
+
{
|
|
302
|
+
error: TestEnhancedErrors.server(),
|
|
303
|
+
shouldRetry: true
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
error: TestEnhancedErrors.network(),
|
|
307
|
+
shouldRetry: true
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
error: TestEnhancedErrors.client(),
|
|
311
|
+
shouldRetry: false
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
error: TestEnhancedErrors.auth(),
|
|
315
|
+
shouldRetry: false
|
|
316
|
+
}
|
|
317
|
+
];
|
|
318
|
+
testCases.forEach(({ error, shouldRetry })=>{
|
|
319
|
+
expect(shouldRetryError(error, 0)).toBe(shouldRetry);
|
|
320
|
+
});
|
|
321
|
+
});
|
|
322
|
+
test("converts and retries AWS errors", ()=>{
|
|
323
|
+
const testCases = [
|
|
324
|
+
{
|
|
325
|
+
error: TestErrors.internalError(),
|
|
326
|
+
shouldRetry: true
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
error: TestErrors.invalidRequest(),
|
|
330
|
+
shouldRetry: false
|
|
331
|
+
}
|
|
332
|
+
];
|
|
333
|
+
testCases.forEach(({ error, shouldRetry })=>{
|
|
334
|
+
expect(shouldRetryError(error, 0)).toBe(shouldRetry);
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
test("uses default maxRetries of 3", ()=>{
|
|
338
|
+
const retryableError = TestEnhancedErrors.server();
|
|
339
|
+
expect(shouldRetryError(retryableError, 0)).toBe(true);
|
|
340
|
+
expect(shouldRetryError(retryableError, 3)).toBe(false);
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
describe("Integration Tests", ()=>{
|
|
344
|
+
test("complete error processing workflow", ()=>{
|
|
345
|
+
const testCases = [
|
|
346
|
+
{
|
|
347
|
+
name: "NoSuchBucket - non-retryable",
|
|
348
|
+
originalError: TestErrors.noSuchBucket(),
|
|
349
|
+
operation: "ListObjectsV2",
|
|
350
|
+
bucket: TEST_CONSTANTS.BUCKET,
|
|
351
|
+
expectedCategory: ErrorCategory.NOT_FOUND,
|
|
352
|
+
shouldRetry: false
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
name: "Server error - retryable",
|
|
356
|
+
originalError: TestErrors.serviceUnavailable(),
|
|
357
|
+
operation: "PutObject",
|
|
358
|
+
bucket: TEST_CONSTANTS.BUCKET,
|
|
359
|
+
key: TEST_CONSTANTS.KEY,
|
|
360
|
+
expectedCategory: ErrorCategory.SERVER_ERROR,
|
|
361
|
+
shouldRetry: true
|
|
362
|
+
}
|
|
363
|
+
];
|
|
364
|
+
testCases.forEach(({ originalError, operation, bucket, key, expectedCategory, shouldRetry })=>{
|
|
365
|
+
const operationError = createS3OperationError(originalError, operation, bucket, key);
|
|
366
|
+
expect(operationError.category).toBe(expectedCategory);
|
|
367
|
+
expect(operationError.shouldRetry()).toBe(shouldRetry);
|
|
368
|
+
expect(isEnhancedS3Error(operationError)).toBe(true);
|
|
369
|
+
expect(shouldRetryError(operationError, 0)).toBe(shouldRetry);
|
|
370
|
+
expect(shouldRetryError(operationError, 3)).toBe(false);
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
test("retry attempt progression", ()=>{
|
|
374
|
+
const serverError = TestErrors.serviceUnavailable();
|
|
375
|
+
const operationError = createS3OperationError(serverError, "PutObject", TEST_CONSTANTS.BUCKET, TEST_CONSTANTS.KEY);
|
|
376
|
+
[
|
|
377
|
+
0,
|
|
378
|
+
1,
|
|
379
|
+
2
|
|
380
|
+
].forEach((attempt)=>{
|
|
381
|
+
expect(shouldRetryError(operationError, attempt)).toBe(true);
|
|
382
|
+
});
|
|
383
|
+
expect(shouldRetryError(operationError, 3)).toBe(false);
|
|
384
|
+
});
|
|
385
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { S3ClientConfig } from "@aws-sdk/client-s3";
|
|
2
|
+
import type { AwsCredentialIdentity } from "@aws-sdk/types";
|
|
3
|
+
export interface S3BrowserConfig extends Omit<S3ClientConfig, "credentials"> {
|
|
4
|
+
endpoint?: string;
|
|
5
|
+
region: string;
|
|
6
|
+
forcePathStyle?: boolean;
|
|
7
|
+
useDevProxy?: boolean;
|
|
8
|
+
realS3Host?: string;
|
|
9
|
+
proxyPath?: string;
|
|
10
|
+
publicAclIndicator?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface S3Credentials extends AwsCredentialIdentity {
|
|
13
|
+
roleArn?: string;
|
|
14
|
+
features?: string[];
|
|
15
|
+
}
|
|
16
|
+
export type GetConfigFunction = () => S3BrowserConfig & {
|
|
17
|
+
credentials: S3Credentials;
|
|
18
|
+
};
|
|
19
|
+
export interface ObjectInfo {
|
|
20
|
+
key: string;
|
|
21
|
+
size?: number;
|
|
22
|
+
lastModified?: Date;
|
|
23
|
+
etag?: string;
|
|
24
|
+
storageClass?: string;
|
|
25
|
+
owner?: {
|
|
26
|
+
displayName?: string;
|
|
27
|
+
id?: string;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface ObjectVersion extends ObjectInfo {
|
|
31
|
+
versionId: string;
|
|
32
|
+
isLatest: boolean;
|
|
33
|
+
isDeleteMarker?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface CommonPrefix {
|
|
36
|
+
prefix: string;
|
|
37
|
+
}
|
|
38
|
+
export interface ListObjectsResult {
|
|
39
|
+
objects: ObjectInfo[];
|
|
40
|
+
commonPrefixes: CommonPrefix[];
|
|
41
|
+
nextContinuationToken?: string;
|
|
42
|
+
isTruncated: boolean;
|
|
43
|
+
}
|
|
44
|
+
export type S3ErrorCode = "AccessDenied" | "NoSuchBucket" | "NoSuchKey" | "InvalidBucketName" | "BucketNotFound" | "NetworkError" | "UnknownError";
|
|
45
|
+
export interface S3Error extends Error {
|
|
46
|
+
code?: S3ErrorCode;
|
|
47
|
+
statusCode?: number;
|
|
48
|
+
}
|
|
File without changes
|