dpu-cloud-sdk 1.0.0

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 (51) hide show
  1. package/.env.development +1 -0
  2. package/.env.production +1 -0
  3. package/dist/DPUClient.d.ts +83 -0
  4. package/dist/DPUClient.js +1043 -0
  5. package/dist/ServiceIntegration.d.ts +20 -0
  6. package/dist/ServiceIntegration.js +506 -0
  7. package/dist/api/auth.d.ts +3 -0
  8. package/dist/api/auth.js +10 -0
  9. package/dist/api/compress.d.ts +4 -0
  10. package/dist/api/compress.js +16 -0
  11. package/dist/api/translate.d.ts +8 -0
  12. package/dist/api/translate.js +38 -0
  13. package/dist/index.d.ts +4 -0
  14. package/dist/index.js +4 -0
  15. package/dist/models/RequestModel.d.ts +33 -0
  16. package/dist/models/RequestModel.js +2 -0
  17. package/dist/models/ResponseModel.d.ts +99 -0
  18. package/dist/models/ResponseModel.js +1 -0
  19. package/dist/utils/Config.d.ts +32 -0
  20. package/dist/utils/Config.js +44 -0
  21. package/dist/utils/Constants.d.ts +48 -0
  22. package/dist/utils/Constants.js +55 -0
  23. package/dist/utils/Enum.d.ts +27 -0
  24. package/dist/utils/Enum.js +30 -0
  25. package/dist/utils/Helper.d.ts +4 -0
  26. package/dist/utils/Helper.js +47 -0
  27. package/dist/workerDownloadSingleFile.d.ts +1 -0
  28. package/dist/workerDownloadSingleFile.js +35 -0
  29. package/dist/workerUploadChildFile.d.ts +1 -0
  30. package/dist/workerUploadChildFile.js +82 -0
  31. package/dist/workerUploadSingleFile.d.ts +1 -0
  32. package/dist/workerUploadSingleFile.js +93 -0
  33. package/dpubim-service-1.1.28.tgz +0 -0
  34. package/package.json +33 -0
  35. package/src/DPUClient.ts +1505 -0
  36. package/src/ServiceIntegration.ts +710 -0
  37. package/src/api/auth.ts +18 -0
  38. package/src/api/compress.ts +36 -0
  39. package/src/api/translate.ts +94 -0
  40. package/src/index.ts +4 -0
  41. package/src/models/RequestModel.ts +44 -0
  42. package/src/models/ResponseModel.ts +110 -0
  43. package/src/utils/Config.ts +59 -0
  44. package/src/utils/Constants.ts +61 -0
  45. package/src/utils/Enum.ts +29 -0
  46. package/src/utils/Helper.ts +57 -0
  47. package/src/workerDownloadSingleFile.ts +34 -0
  48. package/src/workerUploadChildFile.ts +85 -0
  49. package/src/workerUploadSingleFile.ts +123 -0
  50. package/tsconfig.json +108 -0
  51. package/webpack.config.js +43 -0
@@ -0,0 +1,18 @@
1
+ import { BaseReponseModel, Token } from "../models/ResponseModel";
2
+ import { Path, PathAuth } from "../utils/Constants";
3
+ import { Scope } from "../utils/Enum";
4
+ import { baseFetch } from "./translate";
5
+
6
+ export const GetToken = async (clientId: string, clientSecret: string, scopes: Scope[]): Promise<BaseReponseModel<Token>> => {
7
+ const request = {
8
+ clientId,
9
+ clientSecret,
10
+ scopes: [0,1,2,3,4,5,6,7,8,9,10,11,12]
11
+ }
12
+ return baseFetch<Token, typeof request>(
13
+ `${Path.BaseURL}${PathAuth.GetToken}`,
14
+ "POST",
15
+ "",
16
+ request
17
+ );
18
+ }
@@ -0,0 +1,36 @@
1
+ import { CompressFolderRequest, GetStatusCompressionRequest } from "../models/RequestModel";
2
+ import { BaseReponseModel, CompressionResponse, CompressStatus } from "../models/ResponseModel";
3
+ import { Path, PathManagement } from "../utils/Constants";
4
+ import { baseFetch } from "./translate";
5
+
6
+ export const CompressFolder = async (accessToken: string, bucketName: string, rootFolder?: string): Promise<BaseReponseModel<CompressionResponse>> => {
7
+ return baseFetch<CompressionResponse, CompressFolderRequest>(
8
+ `${Path.BaseURL}${PathManagement.CompressFolder}`,
9
+ "POST",
10
+ accessToken,
11
+ {
12
+ bucketName,
13
+ rootFolder
14
+ }
15
+ );
16
+ };
17
+
18
+ export const GetStatusCompress = async (requestIds: string[], accessToken: string): Promise<BaseReponseModel<CompressStatus>> => {
19
+ return baseFetch<CompressStatus, GetStatusCompressionRequest>(
20
+ `${Path.BaseURL}${PathManagement.GetStatusCompress}`,
21
+ "POST",
22
+ accessToken,
23
+ {
24
+ requestIds
25
+ }
26
+ );
27
+ };
28
+
29
+ export const CancelDownload = async (requestId: string, accessToken: string): Promise<BaseReponseModel<boolean>> => {
30
+ return baseFetch<boolean, string>(
31
+ `${Path.BaseURL}${PathManagement.CancelDownload}`,
32
+ "DELETE",
33
+ accessToken,
34
+ requestId
35
+ );
36
+ };
@@ -0,0 +1,94 @@
1
+ import {
2
+ GetStatusTranslateRequest,
3
+ TranslateRequest,
4
+ } from "../models/RequestModel";
5
+ import {
6
+ BaseReponseModel,
7
+ TranslateInfo,
8
+ TranslateStatusInfo,
9
+ } from "../models/ResponseModel";
10
+ import { ApiStatus, Path, PathManagement } from "../utils/Constants";
11
+
12
+ export const baseFetch = async <T, T1>(
13
+ url: string,
14
+ method: string,
15
+ accessToken: string,
16
+ request?: T1
17
+ ): Promise<BaseReponseModel<T>> => {
18
+ const response = await fetch(url, {
19
+ method: method,
20
+ headers: {
21
+ "Content-Type": "application/json",
22
+ Authorization: `Bearer ${accessToken}`,
23
+ 'ngrok-skip-browser-warning': true
24
+ } as any,
25
+ body: JSON.stringify(request),
26
+ });
27
+ if (response.ok) return response.json();
28
+ if (response.status === 401)
29
+ return {
30
+ statusCode: ApiStatus.Unauthorized,
31
+ message: "Unauthorized",
32
+ data: null,
33
+ } as BaseReponseModel<T>;
34
+ return new Promise((resolve, reject) => {
35
+ reject(response.text);
36
+ });
37
+ };
38
+
39
+ export const TranslateFile = async (
40
+ accessToken: string,
41
+ request: TranslateRequest
42
+ ): Promise<BaseReponseModel<TranslateInfo>> => {
43
+ return baseFetch<TranslateInfo, TranslateRequest>(
44
+ `${Path.BaseURL}${PathManagement.TranslateFile}`,
45
+ "POST",
46
+ accessToken,
47
+ request
48
+ );
49
+ };
50
+
51
+ export const GetStatusTranslate = async (
52
+ accessToken: string,
53
+ request: string[]
54
+ ): Promise<BaseReponseModel<TranslateStatusInfo[]>> => {
55
+ return baseFetch<TranslateStatusInfo[], string[]>(
56
+ `${Path.BaseURL}${PathManagement.GetStatusTranslate}`,
57
+ "POST",
58
+ accessToken,
59
+ request
60
+ );
61
+ };
62
+
63
+ export const GetStatusTranslateFile = async (
64
+ accessToken: string,
65
+ request: GetStatusTranslateRequest[]
66
+ ): Promise<BaseReponseModel<TranslateStatusInfo[]>> => {
67
+ return baseFetch<TranslateStatusInfo[], GetStatusTranslateRequest[]>(
68
+ `${Path.BaseURL}${PathManagement.GetStatusTranslateFile}`,
69
+ "POST",
70
+ accessToken,
71
+ request
72
+ );
73
+ };
74
+
75
+ export const GetEPSGRegionCode = async (
76
+ accessToken: string
77
+ ): Promise<BaseReponseModel<string[]>> => {
78
+ return baseFetch<string[], undefined>(
79
+ `${Path.BaseURL}${PathManagement.GetEPSGRegionCode}`,
80
+ "GET",
81
+ accessToken,
82
+ );
83
+ };
84
+
85
+ export const GetFileTileSet = async (
86
+ accessToken: string,
87
+ translateId: string
88
+ ): Promise<BaseReponseModel<string>> => {
89
+ return baseFetch<string, undefined>(
90
+ `${Path.BaseURL}${PathManagement.GetFileTileSet}?translateId=${translateId}`,
91
+ "GET",
92
+ accessToken,
93
+ );
94
+ };
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./DPUClient";
2
+ export * from "./models/RequestModel";
3
+ export * from "./models/ResponseModel";
4
+ export { dpuConfig } from "./utils/Config";
@@ -0,0 +1,44 @@
1
+ export type FileDownloadInfo = {
2
+ fullName: string;
3
+ contentLength?: number;
4
+ };
5
+
6
+ //#region Compress
7
+ export type CompressFolderRequest = {
8
+ bucketName: string;
9
+ rootFolder?: string;
10
+ };
11
+
12
+ export type GetStatusCompressionRequest = {
13
+ requestIds: string[];
14
+ };
15
+ //#endregion
16
+
17
+ //#region Translate
18
+ export interface TranslateRequest {
19
+ modelType: string;
20
+ epsgCode: string;
21
+ translatePos?: number[];
22
+ }
23
+
24
+ export interface FileTranslateRequest extends TranslateRequest {
25
+ bucketName?: string;
26
+ fileName?: string;
27
+ versionId?: string;
28
+ url?: string;
29
+ }
30
+
31
+ export interface URNTranslateRequest extends TranslateRequest {
32
+ urn?: string;
33
+ accessToken: string | null;
34
+ clientId: string | null;
35
+ clientSecret: string | null;
36
+ }
37
+
38
+ export interface GetStatusTranslateRequest {
39
+ bucketName: string;
40
+ fileName: string;
41
+ versionId: string;
42
+ }
43
+
44
+ //#endregion
@@ -0,0 +1,110 @@
1
+ import { StatusTranslate } from "../utils/Enum";
2
+
3
+ export type BaseReponseModel<T> = {
4
+ statusCode: number,
5
+ message: string,
6
+ data: T
7
+ }
8
+
9
+ export interface PresignURLResponse {
10
+ url: string;
11
+ headers: { [key: string]: string; };
12
+ }
13
+
14
+ export interface MultiPresignURLResponse {
15
+ urls: { [key: string]: string; };
16
+ headers: { [key: string]: string; };
17
+ }
18
+
19
+ export interface InitUploadResponse {
20
+ uploadId: string;
21
+ headers: { [key: string]: string; };
22
+ }
23
+
24
+ export type CompressionResponse = {
25
+ bucketName: string;
26
+ rootFolder: string;
27
+ requestId: string;
28
+ }
29
+
30
+ export interface CompressStatus {
31
+ compressData: CompressResponse;
32
+ compressInfo: FileCompressInfo;
33
+ }
34
+
35
+ export interface FileCompressInfo {
36
+ bucketName: string;
37
+ rootFolder: string;
38
+ requestId: string;
39
+ }
40
+
41
+ export interface CompressResponse {
42
+ status: CompressStatus;
43
+ percent: number;
44
+ fileCompressed: number;
45
+ totalFile: number;
46
+ urlsDownload: string[] | null;
47
+ expireTime: Date | null;
48
+ compressTime: Date;
49
+ message: string[];
50
+ }
51
+
52
+ export interface ObjectDetail {
53
+ bucketKey: string;
54
+ lastModified: string;
55
+ versionId: string;
56
+ objectKey: string;
57
+ contentLength: number | null;
58
+ }
59
+
60
+ export interface CompleteMultipartUploadResponse {
61
+ key: string;
62
+ eTag: string;
63
+ versionId: string;
64
+ }
65
+
66
+ export interface TranslateStatusInfo {
67
+ translateId: string;
68
+ modelType: string;
69
+ translateType: string;
70
+ extensionSaveFile: string;
71
+ ePSGCode: string;
72
+ translatePos: number[] | null;
73
+ translateStatus: TranslateStatus;
74
+ objectTranslateInfo: ObjectTranslateInfo;
75
+ }
76
+
77
+ export interface ObjectTranslateInfo {
78
+
79
+ }
80
+
81
+ export interface FileTranslateInfo extends ObjectTranslateInfo {
82
+ fileName: string;
83
+ bucketName: string;
84
+ versionId: string;
85
+ }
86
+
87
+ export interface URNTranslateInfo extends ObjectTranslateInfo {
88
+ urn: string;
89
+ clientID: string;
90
+ }
91
+
92
+ export interface TranslateStatus {
93
+ status: StatusTranslate;
94
+ percentTranslateGeometry: number | null;
95
+ percentTranslateMetadata: number | null;
96
+ }
97
+
98
+ export interface Token{
99
+ accessToken: string;
100
+ expiresIn: number;
101
+ }
102
+
103
+ export interface Dictionary<T> {
104
+ [key: string]: T;
105
+ }
106
+
107
+ export interface TranslateInfo {
108
+ listError: Dictionary<string>;
109
+ translateStatusInfo: TranslateStatusInfo[];
110
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Global configuration for DPU Storage
3
+ * This allows external packages to customize the BaseURL for their domains
4
+ */
5
+ interface IConfig {
6
+ baseURL: string;
7
+ }
8
+
9
+ class DPUConfig {
10
+ private static instance: DPUConfig;
11
+ private config: IConfig = {
12
+ baseURL: 'https://translateservicedev.corebim.com', // Default URL
13
+ };
14
+
15
+ private constructor() {}
16
+
17
+ public static getInstance(): DPUConfig {
18
+ if (!DPUConfig.instance) {
19
+ DPUConfig.instance = new DPUConfig();
20
+ }
21
+ return DPUConfig.instance;
22
+ }
23
+
24
+ /**
25
+ * Set the base URL for API requests
26
+ * @param baseURL The base URL for all API calls
27
+ */
28
+ public setBaseURL(baseURL: string): void {
29
+ if (!baseURL || typeof baseURL !== 'string') {
30
+ throw new Error('Invalid baseURL. Must be a non-empty string.');
31
+ }
32
+ this.config.baseURL = baseURL.trim();
33
+ }
34
+
35
+ /**
36
+ * Get the current base URL
37
+ */
38
+ public getBaseURL(): string {
39
+ return this.config.baseURL;
40
+ }
41
+
42
+ /**
43
+ * Set multiple configuration values at once
44
+ */
45
+ public setConfig(config: Partial<IConfig>): void {
46
+ if (config.baseURL) {
47
+ this.setBaseURL(config.baseURL);
48
+ }
49
+ }
50
+
51
+ /**
52
+ * Get the entire configuration object
53
+ */
54
+ public getConfig(): IConfig {
55
+ return { ...this.config };
56
+ }
57
+ }
58
+
59
+ export const dpuConfig = DPUConfig.getInstance();
@@ -0,0 +1,61 @@
1
+ import { dpuConfig } from './Config';
2
+
3
+ export const Path = {
4
+ get BaseURL() {
5
+ return dpuConfig.getBaseURL();
6
+ },
7
+ InitiateMultipartUpload: '/fileApi/Object/InitiateMultipartUpload',
8
+ GeneratePresignedUrls: '/fileApi/Object/GeneratePresignedUrls',
9
+ GeneratePresignedUrl: '/fileApi/Object/GeneratePresignedUrl',
10
+ GenerateMultiPresignedURL: '/fileApi/Object/GenerateMultiPresignedURL',
11
+ CompleteMultipartUpload: '/fileApi/Object/CompleteMultipartUpload',
12
+ AbortMultipartUpload: '/fileApi/Object/AbortMultipartUpload',
13
+ GetObjectDetail: '/fileApi/Object/GetObjectDetail',
14
+ GetObjects: '/fileApi/Object/GetObjects',
15
+ GetUrlDownload: '/fileApi/Object/GetUrlDownload',
16
+ ApplyPermissionToObjects: '/fileApi/Object/ApplyPermissionToObjects',
17
+ }
18
+
19
+ export const PathManagement = {
20
+ //#region Compress
21
+ CompressFolder: "/manageTranslateApi/Compress/CompressFolder",
22
+ GetStatusCompress: "/manageTranslateApi/Compress/GetStatusCompress",
23
+ CancelDownload: "/manageTranslateApi/Compress/CancelDownload",
24
+ //#endregion
25
+ //#region Translate
26
+ TranslateFile: "/manageTranslateApi/Translate/TranslateFile",
27
+ GetStatusTranslate: "/manageTranslateApi/Translate/GetStatusTranslate",
28
+ GetStatusTranslateFile: "/manageTranslateApi/Translate/GetStatusTranslateFile",
29
+ GetEPSGRegionCode: "/manageTranslateApi/Translate/GetEPSGRegionCode",
30
+ GetFileTileSet: "/manageTranslateApi/Translate/GetFileTileSet",
31
+ //#endregion
32
+ }
33
+
34
+ export const PathAuth = {
35
+ GetToken: '/authApi/user/GetToken',
36
+ }
37
+
38
+ export const ApiStatus = {
39
+ Success: 200,
40
+ BadRequest: 400,
41
+ Unauthorized: 401,
42
+ Forbidden: 403,
43
+ NotFound: 404,
44
+ InternalServerError: 500
45
+ }
46
+
47
+ export const ConfigFileRules = {
48
+ ChunkSize: 5 * 1024 * 1024, // 5MB
49
+ MaxChunkCountAllowed: 10000,
50
+ MaxRetryOnUrlExpiry: 2,
51
+ MaxRetry: 3,
52
+ MaxRetryOnTokenExpiry: 2,
53
+ MaxWebWorker: 20,
54
+ LimitFile: 200,
55
+ TaskCurrently: 10,
56
+ MaxFileInChunk: 2000,
57
+ }
58
+
59
+ export const ConfigBase = {
60
+ PageSize: 1000
61
+ }
@@ -0,0 +1,29 @@
1
+ export enum StatusWorker {
2
+ Success = "Success",
3
+ Error = "Error"
4
+ }
5
+
6
+ export enum StatusTranslate {
7
+ InQueue,
8
+ Translating,
9
+ Translated,
10
+ TranslateError,
11
+ Canceled,
12
+ NotFound
13
+ }
14
+
15
+ export enum Scope {
16
+ DataRead,
17
+ DataWrite,
18
+ DataCreate,
19
+ DataSearch,
20
+ BucketCreate,
21
+ BucketRead,
22
+ BucketUpdate,
23
+ BucketDelete,
24
+ CodeAll,
25
+ AccountRead,
26
+ AccountWrite,
27
+ UserProfileRead,
28
+ ViewablesRead
29
+ }
@@ -0,0 +1,57 @@
1
+ import { Buffer } from "buffer";
2
+
3
+ export const validString = (value?: string): boolean => {
4
+ if (value === null || value === undefined || value === "") {
5
+ return false;
6
+ }
7
+
8
+ return true;
9
+ };
10
+
11
+ // large file is not supported (> 2GB)
12
+ // export const readFileDataAsBase64 = async (file: File): Promise<Buffer> => {
13
+ // const chunkSize = 1024 * 1024 * 10; // 10 MB chunks
14
+ // const totalSize = file.size;
15
+ // let bytesRead = 0;
16
+
17
+ // const reader = file.stream().getReader(); // Create a ReadableStream reader
18
+
19
+ // // Create a buffer to store the file data incrementally
20
+ // const arrayBuffer = new Uint8Array(totalSize);
21
+
22
+ // while (true) {
23
+ // const { done, value } = await reader.read(); // Read a chunk
24
+ // if (done) break;
25
+
26
+ // // Copy the chunk into the ArrayBuffer
27
+ // arrayBuffer.set(value, bytesRead);
28
+ // bytesRead += value.byteLength;
29
+ // }
30
+ // return Buffer.from(arrayBuffer);
31
+ // };
32
+ export const readFileDataAsBase64 = (file: File): Promise<Buffer> => {
33
+ return new Promise((resolve, reject) => {
34
+ const reader = new FileReader();
35
+
36
+ reader.onload = (event: any) => {
37
+ const buffer = Buffer.from(event.target.result);
38
+ resolve(buffer);
39
+ };
40
+
41
+ reader.onerror = (err: any) => {
42
+ console.error("error when read file", err);
43
+ reject(err);
44
+ };
45
+
46
+ reader.readAsArrayBuffer(file);
47
+ });
48
+ };
49
+ export const chunkArray = <T>(array: T[], max: number): T[][] => {
50
+ if (max <= 0) throw new Error("max must be a positive number");
51
+
52
+ const result: T[][] = [];
53
+ for (let i = 0; i < array.length; i += max) {
54
+ result.push(array.slice(i, i + max));
55
+ }
56
+ return result;
57
+ };
@@ -0,0 +1,34 @@
1
+ import { ServiceIntegration } from "./ServiceIntegration";
2
+ import { StatusWorker } from "./utils/Enum";
3
+ // tạm thời chưa làm phần token
4
+ self.onmessage = async (message) => {
5
+ const { data } = message;
6
+ try {
7
+ const chunk = await downloadSingleFile(data);
8
+ const result = {
9
+ status: StatusWorker.Success,
10
+ chunk: chunk,
11
+ requestId: data.requestId,
12
+ index: data.index,
13
+ };
14
+ self.postMessage(result, [chunk]); // Send the result back to the main thread
15
+ } catch (error) {
16
+ const result = {
17
+ status: StatusWorker.Error,
18
+ requestId: data.requestId,
19
+ };
20
+ self.postMessage(result);
21
+ }
22
+ };
23
+
24
+ async function downloadSingleFile(data: any) {
25
+ const { url, start, end } = data;
26
+ try {
27
+ const service = new ServiceIntegration();
28
+ const response = await service.fetchChunkFile(url, start, end);
29
+ return response;
30
+ } catch (error) {
31
+ console.error(`Error when download single file: ${error}`);
32
+ throw error;
33
+ }
34
+ }
@@ -0,0 +1,85 @@
1
+ import { ApiStatus } from "./utils/Constants";
2
+ import { Buffer } from "buffer";
3
+ import { StatusWorker } from "./utils/Enum";
4
+
5
+ let abortController: AbortController | null = null;
6
+ let workerPortRoot: MessagePort | null = null;
7
+
8
+ self.onmessage = async (message) => {
9
+ const { data } = message;
10
+ if (data.port) {
11
+ workerPortRoot = data.port;
12
+ } else {
13
+ // Handle abort message
14
+ if (data.type === "abort") {
15
+ if (abortController) {
16
+ abortController.abort();
17
+ abortController = null;
18
+ }
19
+ return;
20
+ }
21
+
22
+ try {
23
+ const responseUpload = await uploadChildFile(data);
24
+ const result = {
25
+ status: StatusWorker.Success,
26
+ responseUpload,
27
+ requestId: data.requestId,
28
+ contentLength: data.arrayBuffer.byteLength,
29
+ };
30
+ self.postMessage(result); // Send the result back to the main thread
31
+ if (workerPortRoot) {
32
+ workerPortRoot.postMessage({
33
+ type: "progressUpload",
34
+ progress: {
35
+ dataUploadId: data.dataUploadId,
36
+ percentCompleted: 0,
37
+ fileKey: data.fileName,
38
+ contentLength: data.arrayBuffer.byteLength,
39
+ },
40
+ });
41
+ }
42
+ } catch (error) {
43
+ const result = {
44
+ status: StatusWorker.Error,
45
+ requestId: data.requestId,
46
+ error: error instanceof Error ? error.message : String(error),
47
+ };
48
+ self.postMessage(result);
49
+ }
50
+ }
51
+ };
52
+
53
+ async function uploadChildFile(data: any) {
54
+ const { currentPresignUrl, arrayBuffer, partNumber } = data;
55
+ const buffer = Buffer.from(arrayBuffer);
56
+
57
+ // Create new AbortController for this request
58
+ abortController = new AbortController();
59
+
60
+ try {
61
+ const response = await fetch(currentPresignUrl.url, {
62
+ method: "PUT",
63
+ headers: currentPresignUrl.headers,
64
+ body: buffer,
65
+ signal: abortController.signal,
66
+ });
67
+ if (response.status === ApiStatus.Success) {
68
+ var eTag = response.headers.get("ETag");
69
+ if (eTag) {
70
+ const result = {
71
+ eTag: eTag.replace(/^"|"$/g, ""),
72
+ partNumber: partNumber,
73
+ };
74
+ return result;
75
+ }
76
+ }
77
+ throw new Error(`Error when upload child file: ${response.statusText}`);
78
+ } catch (error) {
79
+ if (error instanceof Error && error.name === "AbortError") {
80
+ throw new Error("Upload cancelled");
81
+ }
82
+ console.error(`Error when upload child file: ${error}`);
83
+ throw new Error(`Error when upload child file: ${error}`);
84
+ }
85
+ }