@internxt/cli 1.6.2 → 1.6.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.
- package/README.md +410 -71
- package/dist/commands/add-cert.d.ts +1 -1
- package/dist/commands/add-cert.js +1 -1
- package/dist/commands/config.d.ts +7 -1
- package/dist/commands/config.js +36 -5
- package/dist/commands/create-folder.d.ts +2 -1
- package/dist/commands/create-folder.js +10 -7
- package/dist/commands/delete-permanently-file.d.ts +1 -0
- package/dist/commands/delete-permanently-folder.d.ts +1 -0
- package/dist/commands/download-file.d.ts +1 -0
- package/dist/commands/download-file.js +4 -2
- package/dist/commands/list.d.ts +1 -0
- package/dist/commands/list.js +2 -4
- package/dist/commands/login-legacy.d.ts +1 -0
- package/dist/commands/move-file.d.ts +1 -1
- package/dist/commands/move-file.js +7 -21
- package/dist/commands/move-folder.d.ts +1 -1
- package/dist/commands/move-folder.js +7 -21
- package/dist/commands/rename-file.d.ts +1 -0
- package/dist/commands/rename-folder.d.ts +1 -0
- package/dist/commands/trash-clear.d.ts +1 -0
- package/dist/commands/trash-file.d.ts +1 -0
- package/dist/commands/trash-folder.d.ts +1 -0
- package/dist/commands/trash-restore-file.d.ts +1 -1
- package/dist/commands/trash-restore-file.js +7 -21
- package/dist/commands/trash-restore-folder.d.ts +1 -1
- package/dist/commands/trash-restore-folder.js +7 -21
- package/dist/commands/upload-file.d.ts +4 -5
- package/dist/commands/upload-file.js +32 -21
- package/dist/commands/upload-folder.d.ts +1 -0
- package/dist/commands/upload-folder.js +11 -6
- package/dist/commands/webdav-config.d.ts +19 -1
- package/dist/commands/webdav-config.js +81 -3
- package/dist/commands/webdav.d.ts +1 -1
- package/dist/commands/webdav.js +10 -5
- package/dist/commands/whoami.js +2 -1
- package/dist/commands/workspaces-list.d.ts +20 -0
- package/dist/commands/workspaces-list.js +67 -0
- package/dist/commands/workspaces-unset.d.ts +23 -0
- package/dist/commands/workspaces-unset.js +45 -0
- package/dist/commands/workspaces-use.d.ts +27 -0
- package/dist/commands/workspaces-use.js +113 -0
- package/dist/constants/configs.d.ts +2 -1
- package/dist/constants/configs.js +4 -3
- package/dist/hooks/prerun/auth_check.js +13 -4
- package/dist/services/auth.service.d.ts +5 -2
- package/dist/services/auth.service.js +69 -12
- package/dist/services/config.service.d.ts +1 -1
- package/dist/services/config.service.js +12 -4
- package/dist/services/crypto.service.d.ts +5 -0
- package/dist/services/crypto.service.js +43 -0
- package/dist/services/database/database.service.d.ts +9 -0
- package/dist/services/database/database.service.js +39 -0
- package/dist/services/database/drive-file/drive-file.attributes.d.ts +3 -6
- package/dist/services/database/drive-file/drive-file.domain.d.ts +3 -6
- package/dist/services/database/drive-file/drive-file.domain.js +1 -12
- package/dist/services/database/drive-file/drive-file.model.d.ts +15 -0
- package/dist/services/database/drive-file/drive-file.model.js +67 -0
- package/dist/services/database/drive-file/drive-file.repository.d.ts +11 -0
- package/dist/services/database/drive-file/drive-file.repository.js +63 -0
- package/dist/services/database/drive-folder/drive-folder.attributes.d.ts +3 -4
- package/dist/services/database/drive-folder/drive-folder.domain.d.ts +4 -5
- package/dist/services/database/drive-folder/drive-folder.domain.js +11 -15
- package/dist/services/database/drive-folder/drive-folder.model.d.ts +11 -0
- package/dist/services/database/drive-folder/drive-folder.model.js +51 -0
- package/dist/services/database/drive-folder/drive-folder.repository.d.ts +13 -0
- package/dist/services/database/drive-folder/drive-folder.repository.js +99 -0
- package/dist/services/drive/drive-file.service.d.ts +2 -0
- package/dist/services/drive/drive-file.service.js +71 -15
- package/dist/services/drive/drive-folder.service.d.ts +6 -1
- package/dist/services/drive/drive-folder.service.js +157 -31
- package/dist/services/drive/trash.service.d.ts +3 -0
- package/dist/services/drive/trash.service.js +52 -16
- package/dist/services/drive/workspace.service.d.ts +7 -0
- package/dist/services/drive/workspace.service.js +30 -0
- package/dist/services/keys.service.d.ts +7 -0
- package/dist/services/keys.service.js +55 -0
- package/dist/services/local-filesystem/local-filesystem.service.d.ts +2 -2
- package/dist/services/local-filesystem/local-filesystem.service.js +4 -4
- package/dist/services/network/download.service.d.ts +2 -2
- package/dist/services/network/download.service.js +2 -2
- package/dist/services/network/network-facade.service.d.ts +3 -7
- package/dist/services/network/network-facade.service.js +9 -11
- package/dist/services/network/upload/upload-facade.service.d.ts +1 -1
- package/dist/services/network/upload/upload-facade.service.js +14 -7
- package/dist/services/network/upload/upload-file.service.d.ts +3 -3
- package/dist/services/network/upload/upload-file.service.js +33 -23
- package/dist/services/network/upload/upload-folder.service.d.ts +2 -2
- package/dist/services/network/upload/upload-folder.service.js +15 -10
- package/dist/services/network/upload/upload.types.d.ts +11 -0
- package/dist/services/sdk-manager.service.d.ts +9 -7
- package/dist/services/sdk-manager.service.js +27 -13
- package/dist/services/thumbnail.service.d.ts +19 -1
- package/dist/services/thumbnail.service.js +29 -2
- package/dist/services/universal-link.service.d.ts +3 -1
- package/dist/services/universal-link.service.js +15 -3
- package/dist/services/usage.service.d.ts +1 -2
- package/dist/services/usage.service.js +1 -1
- package/dist/services/validation.service.js +14 -4
- package/dist/{webdav/services → services/webdav}/webdav-folder.service.d.ts +1 -7
- package/dist/{webdav/services → services/webdav}/webdav-folder.service.js +6 -10
- package/dist/types/command.types.d.ts +44 -1
- package/dist/types/command.types.js +29 -1
- package/dist/types/config.types.d.ts +1 -0
- package/dist/types/drive.types.d.ts +7 -6
- package/dist/types/network.types.d.ts +6 -0
- package/dist/utils/async.utils.d.ts +2 -1
- package/dist/utils/async.utils.js +13 -2
- package/dist/utils/cli.utils.d.ts +20 -15
- package/dist/utils/cli.utils.js +48 -18
- package/dist/utils/crypto.utils.d.ts +3 -1
- package/dist/utils/crypto.utils.js +15 -2
- package/dist/utils/database.utils.d.ts +11 -0
- package/dist/utils/database.utils.js +26 -0
- package/dist/utils/drive.utils.js +7 -10
- package/dist/utils/errors.utils.d.ts +4 -4
- package/dist/utils/errors.utils.js +16 -19
- package/dist/utils/format.utils.d.ts +1 -0
- package/dist/utils/format.utils.js +3 -0
- package/dist/utils/inquirer.utils.js +10 -1
- package/dist/utils/path.utils.d.ts +7 -0
- package/dist/utils/path.utils.js +18 -0
- package/dist/utils/thumbnail.utils.d.ts +6 -20
- package/dist/utils/thumbnail.utils.js +16 -41
- package/dist/utils/webdav.utils.d.ts +4 -20
- package/dist/utils/webdav.utils.js +12 -14
- package/dist/webdav/handlers/DELETE.handler.d.ts +0 -9
- package/dist/webdav/handlers/DELETE.handler.js +18 -16
- package/dist/webdav/handlers/GET.handler.d.ts +0 -13
- package/dist/webdav/handlers/GET.handler.js +6 -11
- package/dist/webdav/handlers/HEAD.handler.d.ts +0 -5
- package/dist/webdav/handlers/HEAD.handler.js +11 -23
- package/dist/webdav/handlers/MKCOL.handler.d.ts +0 -7
- package/dist/webdav/handlers/MKCOL.handler.js +5 -12
- package/dist/webdav/handlers/MOVE.handler.d.ts +0 -9
- package/dist/webdav/handlers/MOVE.handler.js +10 -16
- package/dist/webdav/handlers/PROPFIND.handler.d.ts +0 -7
- package/dist/webdav/handlers/PROPFIND.handler.js +7 -19
- package/dist/webdav/handlers/PUT.handler.d.ts +0 -15
- package/dist/webdav/handlers/PUT.handler.js +24 -26
- package/dist/webdav/index.js +6 -8
- package/dist/webdav/middewares/auth.middleware.d.ts +1 -2
- package/dist/webdav/middewares/auth.middleware.js +5 -4
- package/dist/webdav/middewares/errors.middleware.js +2 -2
- package/dist/webdav/middewares/webdav-auth.middleware.d.ts +3 -0
- package/dist/webdav/middewares/webdav-auth.middleware.js +44 -0
- package/dist/webdav/webdav-server.d.ts +3 -16
- package/dist/webdav/webdav-server.js +29 -87
- package/oclif.manifest.json +429 -6
- package/package.json +25 -20
|
@@ -3,18 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.UploadFacade = void 0;
|
|
4
4
|
const node_path_1 = require("node:path");
|
|
5
5
|
const cli_utils_1 = require("../../../utils/cli.utils");
|
|
6
|
-
const logger_utils_1 = require("../../../utils/logger.utils");
|
|
7
6
|
const local_filesystem_service_1 = require("../../local-filesystem/local-filesystem.service");
|
|
8
7
|
const upload_folder_service_1 = require("./upload-folder.service");
|
|
9
8
|
const upload_file_service_1 = require("./upload-file.service");
|
|
10
9
|
const async_utils_1 = require("../../../utils/async.utils");
|
|
11
10
|
class UploadFacade {
|
|
12
11
|
static instance = new UploadFacade();
|
|
13
|
-
async
|
|
12
|
+
uploadFolder = async ({ localPath, destinationFolderUuid, loginUserDetails, jsonFlag, debugMode, onProgress, reporter, }) => {
|
|
14
13
|
const timer = cli_utils_1.CLIUtils.timer();
|
|
15
|
-
|
|
14
|
+
cli_utils_1.CLIUtils.doing('Preparing Network', jsonFlag);
|
|
15
|
+
const { networkFacade, bucket } = await cli_utils_1.CLIUtils.prepareNetwork(loginUserDetails);
|
|
16
|
+
cli_utils_1.CLIUtils.done(jsonFlag);
|
|
16
17
|
const scanResult = await local_filesystem_service_1.LocalFilesystemService.instance.scanLocalDirectory(localPath);
|
|
17
|
-
|
|
18
|
+
if (debugMode) {
|
|
19
|
+
cli_utils_1.CLIUtils.success(reporter, `Scanned folder ${localPath}: found ${scanResult.totalItems} items, total size ${scanResult.totalBytes} bytes.`);
|
|
20
|
+
}
|
|
18
21
|
const currentProgress = { itemsUploaded: 0, bytesUploaded: 0 };
|
|
19
22
|
const emitProgress = () => {
|
|
20
23
|
const itemProgress = currentProgress.itemsUploaded / scanResult.totalItems;
|
|
@@ -27,19 +30,23 @@ class UploadFacade {
|
|
|
27
30
|
destinationFolderUuid,
|
|
28
31
|
currentProgress,
|
|
29
32
|
emitProgress,
|
|
33
|
+
reporter,
|
|
34
|
+
debugMode,
|
|
30
35
|
});
|
|
31
36
|
if (folderMap.size === 0) {
|
|
32
37
|
throw new Error('Failed to create folders, cannot upload files');
|
|
33
38
|
}
|
|
34
39
|
await async_utils_1.AsyncUtils.sleep(500);
|
|
35
40
|
const totalBytes = await upload_file_service_1.UploadFileService.instance.uploadFilesConcurrently({
|
|
36
|
-
network,
|
|
41
|
+
network: networkFacade,
|
|
37
42
|
filesToUpload: scanResult.files,
|
|
38
43
|
folderMap,
|
|
39
|
-
bucket
|
|
44
|
+
bucket,
|
|
40
45
|
destinationFolderUuid,
|
|
41
46
|
currentProgress,
|
|
42
47
|
emitProgress,
|
|
48
|
+
debugMode,
|
|
49
|
+
reporter,
|
|
43
50
|
});
|
|
44
51
|
const rootFolderName = (0, node_path_1.basename)(localPath);
|
|
45
52
|
const rootFolderId = folderMap.get(rootFolderName) ?? '';
|
|
@@ -48,6 +55,6 @@ class UploadFacade {
|
|
|
48
55
|
rootFolderId,
|
|
49
56
|
uploadTimeMs: timer.stop(),
|
|
50
57
|
};
|
|
51
|
-
}
|
|
58
|
+
};
|
|
52
59
|
}
|
|
53
60
|
exports.UploadFacade = UploadFacade;
|
|
@@ -2,7 +2,7 @@ import { UploadFilesConcurrentlyParams, UploadFileWithRetryParams } from './uplo
|
|
|
2
2
|
import { DriveFileItem } from '../../../types/drive.types';
|
|
3
3
|
export declare class UploadFileService {
|
|
4
4
|
static readonly instance: UploadFileService;
|
|
5
|
-
uploadFilesConcurrently({ network, filesToUpload, folderMap, bucket, destinationFolderUuid, currentProgress, emitProgress, }: UploadFilesConcurrentlyParams)
|
|
6
|
-
uploadFileWithRetry({ file, network, bucket, parentFolderUuid, }: UploadFileWithRetryParams)
|
|
7
|
-
private concurrencyArray;
|
|
5
|
+
uploadFilesConcurrently: ({ network, filesToUpload, folderMap, bucket, destinationFolderUuid, currentProgress, emitProgress, debugMode, reporter, }: UploadFilesConcurrentlyParams) => Promise<number>;
|
|
6
|
+
uploadFileWithRetry: ({ file, network, bucket, parentFolderUuid, debugMode, reporter, }: UploadFileWithRetryParams) => Promise<DriveFileItem | null>;
|
|
7
|
+
private readonly concurrencyArray;
|
|
8
8
|
}
|
|
@@ -8,11 +8,11 @@ const node_path_1 = require("node:path");
|
|
|
8
8
|
const errors_utils_1 = require("../../../utils/errors.utils");
|
|
9
9
|
const promises_1 = require("node:fs/promises");
|
|
10
10
|
const types_1 = require("@internxt/sdk/dist/drive/storage/types");
|
|
11
|
-
const thumbnail_utils_1 = require("../../../utils/thumbnail.utils");
|
|
12
11
|
const cli_utils_1 = require("../../../utils/cli.utils");
|
|
12
|
+
const thumbnail_service_1 = require("../../thumbnail.service");
|
|
13
13
|
class UploadFileService {
|
|
14
14
|
static instance = new UploadFileService();
|
|
15
|
-
async
|
|
15
|
+
uploadFilesConcurrently = async ({ network, filesToUpload, folderMap, bucket, destinationFolderUuid, currentProgress, emitProgress, debugMode, reporter, }) => {
|
|
16
16
|
let bytesUploaded = 0;
|
|
17
17
|
const concurrentFiles = this.concurrencyArray(filesToUpload, upload_types_1.MAX_CONCURRENT_UPLOADS);
|
|
18
18
|
for (const fileArray of concurrentFiles) {
|
|
@@ -20,7 +20,9 @@ class UploadFileService {
|
|
|
20
20
|
const parentPath = (0, node_path_1.dirname)(file.relativePath);
|
|
21
21
|
const parentFolderUuid = parentPath === '.' || parentPath === '' ? destinationFolderUuid : folderMap.get(parentPath);
|
|
22
22
|
if (!parentFolderUuid) {
|
|
23
|
-
|
|
23
|
+
if (debugMode) {
|
|
24
|
+
cli_utils_1.CLIUtils.warning(reporter, `Parent folder not found for ${file.relativePath}, skipping...`);
|
|
25
|
+
}
|
|
24
26
|
return null;
|
|
25
27
|
}
|
|
26
28
|
const createdFileUuid = await this.uploadFileWithRetry({
|
|
@@ -28,6 +30,8 @@ class UploadFileService {
|
|
|
28
30
|
network,
|
|
29
31
|
bucket,
|
|
30
32
|
parentFolderUuid,
|
|
33
|
+
debugMode,
|
|
34
|
+
reporter,
|
|
31
35
|
});
|
|
32
36
|
if (createdFileUuid) {
|
|
33
37
|
bytesUploaded += file.size;
|
|
@@ -38,8 +42,8 @@ class UploadFileService {
|
|
|
38
42
|
}));
|
|
39
43
|
}
|
|
40
44
|
return bytesUploaded;
|
|
41
|
-
}
|
|
42
|
-
async
|
|
45
|
+
};
|
|
46
|
+
uploadFileWithRetry = async ({ file, network, bucket, parentFolderUuid, debugMode, reporter, }) => {
|
|
43
47
|
for (let attempt = 0; attempt <= upload_types_1.MAX_RETRIES; attempt++) {
|
|
44
48
|
try {
|
|
45
49
|
const stats = await (0, promises_1.stat)(file.absolutePath);
|
|
@@ -53,7 +57,7 @@ class UploadFileService {
|
|
|
53
57
|
thumbnailUpload: 0,
|
|
54
58
|
};
|
|
55
59
|
if (fileSize > 0) {
|
|
56
|
-
const { fileStream, bufferStream } =
|
|
60
|
+
const { fileStream, bufferStream } = thumbnail_service_1.ThumbnailService.instance.createFileStreamWithBuffer({
|
|
57
61
|
path: file.absolutePath,
|
|
58
62
|
fileType,
|
|
59
63
|
});
|
|
@@ -84,51 +88,57 @@ class UploadFileService {
|
|
|
84
88
|
timings.driveUpload = driveTimer.stop();
|
|
85
89
|
const thumbnailTimer = cli_utils_1.CLIUtils.timer();
|
|
86
90
|
if (thumbnailStream && fileSize > 0) {
|
|
87
|
-
|
|
91
|
+
await thumbnail_service_1.ThumbnailService.instance.tryUploadThumbnail({
|
|
88
92
|
bufferStream: thumbnailStream,
|
|
89
93
|
fileType,
|
|
90
|
-
|
|
94
|
+
bucket,
|
|
91
95
|
fileUuid: createdDriveFile.uuid,
|
|
92
96
|
networkFacade: network,
|
|
97
|
+
size: fileSize,
|
|
93
98
|
});
|
|
94
99
|
}
|
|
95
100
|
timings.thumbnailUpload = thumbnailTimer.stop();
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
if (debugMode) {
|
|
102
|
+
const totalTime = Object.values(timings).reduce((sum, time) => sum + time, 0);
|
|
103
|
+
const throughputMBps = cli_utils_1.CLIUtils.calculateThroughputMBps(stats.size, timings.networkUpload);
|
|
104
|
+
cli_utils_1.CLIUtils.success(reporter, `Uploaded '${file.name}' (${cli_utils_1.CLIUtils.formatBytesToString(stats.size)})`);
|
|
105
|
+
cli_utils_1.CLIUtils.log(reporter, 'Timing breakdown:\n' +
|
|
106
|
+
`Network upload: ${cli_utils_1.CLIUtils.formatDuration(timings.networkUpload)}` +
|
|
107
|
+
` (${throughputMBps.toFixed(2)} MB/s)\n` +
|
|
108
|
+
`Drive upload: ${cli_utils_1.CLIUtils.formatDuration(timings.driveUpload)}\n` +
|
|
109
|
+
`Thumbnail: ${cli_utils_1.CLIUtils.formatDuration(timings.thumbnailUpload)}\n` +
|
|
110
|
+
`Total: ${cli_utils_1.CLIUtils.formatDuration(totalTime)}\n`);
|
|
111
|
+
}
|
|
104
112
|
return createdDriveFile;
|
|
105
113
|
}
|
|
106
114
|
catch (error) {
|
|
107
|
-
if (
|
|
115
|
+
if (errors_utils_1.ErrorUtils.isAlreadyExistsError(error)) {
|
|
108
116
|
const msg = `File ${file.name} already exists, skipping...`;
|
|
109
117
|
logger_utils_1.logger.info(msg);
|
|
110
118
|
return null;
|
|
111
119
|
}
|
|
112
120
|
if (attempt < upload_types_1.MAX_RETRIES) {
|
|
113
121
|
const delay = upload_types_1.DELAYS_MS[attempt];
|
|
114
|
-
|
|
115
|
-
|
|
122
|
+
if (debugMode) {
|
|
123
|
+
const retryMsg = `Failed to upload file ${file.name}, retrying in ${delay}ms...`;
|
|
124
|
+
cli_utils_1.CLIUtils.warning(reporter, `${retryMsg} (attempt ${attempt + 1}/${upload_types_1.MAX_RETRIES + 1})`);
|
|
125
|
+
}
|
|
116
126
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
117
127
|
}
|
|
118
128
|
else {
|
|
119
|
-
|
|
129
|
+
cli_utils_1.CLIUtils.error(reporter, `Failed to upload file '${file.name}' after ${upload_types_1.MAX_RETRIES + 1} attempts`);
|
|
120
130
|
return null;
|
|
121
131
|
}
|
|
122
132
|
}
|
|
123
133
|
}
|
|
124
134
|
return null;
|
|
125
|
-
}
|
|
126
|
-
concurrencyArray(array, arraySize) {
|
|
135
|
+
};
|
|
136
|
+
concurrencyArray = (array, arraySize) => {
|
|
127
137
|
const arrays = [];
|
|
128
138
|
for (let i = 0; i < array.length; i += arraySize) {
|
|
129
139
|
arrays.push(array.slice(i, i + arraySize));
|
|
130
140
|
}
|
|
131
141
|
return arrays;
|
|
132
|
-
}
|
|
142
|
+
};
|
|
133
143
|
}
|
|
134
144
|
exports.UploadFileService = UploadFileService;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CreateFoldersParams, CreateFolderWithRetryParams } from './upload.types';
|
|
2
2
|
export declare class UploadFolderService {
|
|
3
3
|
static readonly instance: UploadFolderService;
|
|
4
|
-
createFolders({ foldersToCreate, destinationFolderUuid, currentProgress, emitProgress, }: CreateFoldersParams)
|
|
5
|
-
createFolderWithRetry({ folderName, parentFolderUuid }: CreateFolderWithRetryParams)
|
|
4
|
+
createFolders: ({ foldersToCreate, destinationFolderUuid, currentProgress, emitProgress, debugMode, reporter, }: CreateFoldersParams) => Promise<Map<string, string>>;
|
|
5
|
+
createFolderWithRetry: ({ folderName, parentFolderUuid, debugMode, reporter, }: CreateFolderWithRetryParams) => Promise<string | null>;
|
|
6
6
|
}
|
|
@@ -6,9 +6,10 @@ const errors_utils_1 = require("../../../utils/errors.utils");
|
|
|
6
6
|
const logger_utils_1 = require("../../../utils/logger.utils");
|
|
7
7
|
const drive_folder_service_1 = require("../../drive/drive-folder.service");
|
|
8
8
|
const upload_types_1 = require("./upload.types");
|
|
9
|
+
const cli_utils_1 = require("../../../utils/cli.utils");
|
|
9
10
|
class UploadFolderService {
|
|
10
11
|
static instance = new UploadFolderService();
|
|
11
|
-
async
|
|
12
|
+
createFolders = async ({ foldersToCreate, destinationFolderUuid, currentProgress, emitProgress, debugMode, reporter, }) => {
|
|
12
13
|
const folderMap = new Map();
|
|
13
14
|
for (const folder of foldersToCreate) {
|
|
14
15
|
const parentPath = (0, node_path_1.dirname)(folder.relativePath);
|
|
@@ -20,6 +21,8 @@ class UploadFolderService {
|
|
|
20
21
|
const createdFolderUuid = await this.createFolderWithRetry({
|
|
21
22
|
folderName: folder.name,
|
|
22
23
|
parentFolderUuid: parentUuid,
|
|
24
|
+
debugMode,
|
|
25
|
+
reporter,
|
|
23
26
|
});
|
|
24
27
|
if (createdFolderUuid) {
|
|
25
28
|
folderMap.set(folder.relativePath, createdFolderUuid);
|
|
@@ -28,11 +31,11 @@ class UploadFolderService {
|
|
|
28
31
|
}
|
|
29
32
|
}
|
|
30
33
|
return folderMap;
|
|
31
|
-
}
|
|
32
|
-
async
|
|
34
|
+
};
|
|
35
|
+
createFolderWithRetry = async ({ folderName, parentFolderUuid, debugMode, reporter, }) => {
|
|
33
36
|
for (let attempt = 0; attempt <= upload_types_1.MAX_RETRIES; attempt++) {
|
|
34
37
|
try {
|
|
35
|
-
const [createFolderPromise] = drive_folder_service_1.DriveFolderService.instance.createFolder({
|
|
38
|
+
const [createFolderPromise] = await drive_folder_service_1.DriveFolderService.instance.createFolder({
|
|
36
39
|
plainName: folderName,
|
|
37
40
|
parentFolderUuid,
|
|
38
41
|
});
|
|
@@ -40,23 +43,25 @@ class UploadFolderService {
|
|
|
40
43
|
return createdFolder.uuid;
|
|
41
44
|
}
|
|
42
45
|
catch (error) {
|
|
43
|
-
if (
|
|
44
|
-
logger_utils_1.logger.
|
|
46
|
+
if (errors_utils_1.ErrorUtils.isAlreadyExistsError(error)) {
|
|
47
|
+
logger_utils_1.logger.warn(`Folder ${folderName} already exists, skipping...`);
|
|
45
48
|
return null;
|
|
46
49
|
}
|
|
47
50
|
if (attempt < upload_types_1.MAX_RETRIES) {
|
|
48
51
|
const delay = upload_types_1.DELAYS_MS[attempt];
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
if (debugMode) {
|
|
53
|
+
cli_utils_1.CLIUtils.warning(reporter, `Failed to create folder '${folderName}', retrying in ${delay}ms... ` +
|
|
54
|
+
`(attempt ${attempt + 1}/${upload_types_1.MAX_RETRIES + 1})`);
|
|
55
|
+
}
|
|
51
56
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
52
57
|
}
|
|
53
58
|
else {
|
|
54
|
-
|
|
59
|
+
cli_utils_1.CLIUtils.error(reporter, `Failed to create folder '${folderName}' after ${upload_types_1.MAX_RETRIES + 1} attempts`);
|
|
55
60
|
throw error;
|
|
56
61
|
}
|
|
57
62
|
}
|
|
58
63
|
}
|
|
59
64
|
return null;
|
|
60
|
-
}
|
|
65
|
+
};
|
|
61
66
|
}
|
|
62
67
|
exports.UploadFolderService = UploadFolderService;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LoginUserDetails } from '../../../types/command.types';
|
|
2
|
+
import { LogReporter } from '../../../utils/cli.utils';
|
|
2
3
|
import { FileSystemNode } from '../../local-filesystem/local-filesystem.types';
|
|
3
4
|
import { NetworkFacade } from '../network-facade.service';
|
|
4
5
|
export interface UploadResult {
|
|
@@ -12,6 +13,8 @@ export interface UploadFolderParams {
|
|
|
12
13
|
loginUserDetails: LoginUserDetails;
|
|
13
14
|
jsonFlag?: boolean;
|
|
14
15
|
onProgress: (progress: UploadProgress) => void;
|
|
16
|
+
debugMode: boolean;
|
|
17
|
+
reporter: LogReporter;
|
|
15
18
|
}
|
|
16
19
|
export interface UploadProgress {
|
|
17
20
|
percentage: number;
|
|
@@ -25,10 +28,14 @@ export interface CreateFoldersParams {
|
|
|
25
28
|
bytesUploaded: number;
|
|
26
29
|
};
|
|
27
30
|
emitProgress: () => void;
|
|
31
|
+
debugMode: boolean;
|
|
32
|
+
reporter: LogReporter;
|
|
28
33
|
}
|
|
29
34
|
export interface CreateFolderWithRetryParams {
|
|
30
35
|
folderName: string;
|
|
31
36
|
parentFolderUuid: string;
|
|
37
|
+
debugMode: boolean;
|
|
38
|
+
reporter: LogReporter;
|
|
32
39
|
}
|
|
33
40
|
export interface UploadFilesConcurrentlyParams {
|
|
34
41
|
network: NetworkFacade;
|
|
@@ -41,12 +48,16 @@ export interface UploadFilesConcurrentlyParams {
|
|
|
41
48
|
bytesUploaded: number;
|
|
42
49
|
};
|
|
43
50
|
emitProgress: () => void;
|
|
51
|
+
debugMode: boolean;
|
|
52
|
+
reporter: LogReporter;
|
|
44
53
|
}
|
|
45
54
|
export interface UploadFileWithRetryParams {
|
|
46
55
|
file: FileSystemNode;
|
|
47
56
|
network: NetworkFacade;
|
|
48
57
|
bucket: string;
|
|
49
58
|
parentFolderUuid: string;
|
|
59
|
+
debugMode: boolean;
|
|
60
|
+
reporter: LogReporter;
|
|
50
61
|
}
|
|
51
62
|
export declare const MAX_CONCURRENT_UPLOADS = 10;
|
|
52
63
|
export declare const DELAYS_MS: number[];
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Auth, Drive, Network as NetworkModule } from '@internxt/sdk';
|
|
2
2
|
import { ApiSecurity, AppDetails } from '@internxt/sdk/dist/shared';
|
|
3
|
+
import { Workspaces } from '@internxt/sdk/dist/workspaces';
|
|
3
4
|
export type SdkManagerApiSecurity = ApiSecurity;
|
|
4
5
|
export declare class SdkManager {
|
|
5
6
|
static readonly instance: SdkManager;
|
|
@@ -10,13 +11,14 @@ export declare class SdkManager {
|
|
|
10
11
|
throwErrorOnMissingCredentials?: boolean | undefined;
|
|
11
12
|
}) => SdkManagerApiSecurity;
|
|
12
13
|
static readonly getAppDetails: () => AppDetails;
|
|
13
|
-
getAuth()
|
|
14
|
-
getUsers()
|
|
15
|
-
getStorage()
|
|
16
|
-
getTrash()
|
|
17
|
-
getShare()
|
|
18
|
-
|
|
14
|
+
getAuth: () => Auth;
|
|
15
|
+
getUsers: () => Drive.Users;
|
|
16
|
+
getStorage: () => Drive.Storage;
|
|
17
|
+
getTrash: () => Drive.Trash;
|
|
18
|
+
getShare: () => Drive.Share;
|
|
19
|
+
getWorkspaces: () => Workspaces;
|
|
20
|
+
getNetwork: (credentials: {
|
|
19
21
|
user: string;
|
|
20
22
|
pass: string;
|
|
21
|
-
})
|
|
23
|
+
}) => NetworkModule.Network;
|
|
22
24
|
}
|
|
@@ -9,11 +9,19 @@ const drive_1 = require("@internxt/sdk/dist/drive");
|
|
|
9
9
|
const config_service_1 = require("./config.service");
|
|
10
10
|
const package_json_1 = __importDefault(require("../../package.json"));
|
|
11
11
|
const network_utils_1 = require("../utils/network.utils");
|
|
12
|
+
const workspaces_1 = require("@internxt/sdk/dist/workspaces");
|
|
13
|
+
const MAX_RETRIES = 3;
|
|
12
14
|
class SdkManager {
|
|
13
15
|
static instance = new SdkManager();
|
|
14
16
|
static apiSecurity;
|
|
15
17
|
static init = (apiSecurity) => {
|
|
16
|
-
|
|
18
|
+
const newApiSecurity = {
|
|
19
|
+
...apiSecurity,
|
|
20
|
+
retryOptions: {
|
|
21
|
+
maxRetries: MAX_RETRIES,
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
SdkManager.apiSecurity = newApiSecurity;
|
|
17
25
|
};
|
|
18
26
|
static clean = () => {
|
|
19
27
|
SdkManager.apiSecurity = undefined;
|
|
@@ -30,37 +38,43 @@ class SdkManager {
|
|
|
30
38
|
desktopHeader: config_service_1.ConfigService.instance.get('DESKTOP_HEADER'),
|
|
31
39
|
};
|
|
32
40
|
};
|
|
33
|
-
getAuth() {
|
|
41
|
+
getAuth = () => {
|
|
34
42
|
const DRIVE_API_URL = config_service_1.ConfigService.instance.get('DRIVE_NEW_API_URL');
|
|
35
43
|
const apiSecurity = SdkManager.getApiSecurity({ throwErrorOnMissingCredentials: false });
|
|
36
44
|
const appDetails = SdkManager.getAppDetails();
|
|
37
45
|
return sdk_1.Auth.client(DRIVE_API_URL, appDetails, apiSecurity);
|
|
38
|
-
}
|
|
39
|
-
getUsers() {
|
|
46
|
+
};
|
|
47
|
+
getUsers = () => {
|
|
40
48
|
const DRIVE_API_URL = config_service_1.ConfigService.instance.get('DRIVE_NEW_API_URL');
|
|
41
49
|
const apiSecurity = SdkManager.getApiSecurity({ throwErrorOnMissingCredentials: false });
|
|
42
50
|
const appDetails = SdkManager.getAppDetails();
|
|
43
51
|
return sdk_1.Drive.Users.client(DRIVE_API_URL, appDetails, apiSecurity);
|
|
44
|
-
}
|
|
45
|
-
getStorage() {
|
|
52
|
+
};
|
|
53
|
+
getStorage = () => {
|
|
46
54
|
const DRIVE_API_URL = config_service_1.ConfigService.instance.get('DRIVE_NEW_API_URL');
|
|
47
55
|
const apiSecurity = SdkManager.getApiSecurity();
|
|
48
56
|
const appDetails = SdkManager.getAppDetails();
|
|
49
57
|
return sdk_1.Drive.Storage.client(DRIVE_API_URL, appDetails, apiSecurity);
|
|
50
|
-
}
|
|
51
|
-
getTrash() {
|
|
58
|
+
};
|
|
59
|
+
getTrash = () => {
|
|
52
60
|
const DRIVE_NEW_API_URL = config_service_1.ConfigService.instance.get('DRIVE_NEW_API_URL');
|
|
53
61
|
const apiSecurity = SdkManager.getApiSecurity();
|
|
54
62
|
const appDetails = SdkManager.getAppDetails();
|
|
55
63
|
return drive_1.Trash.client(DRIVE_NEW_API_URL, appDetails, apiSecurity);
|
|
56
|
-
}
|
|
57
|
-
getShare() {
|
|
64
|
+
};
|
|
65
|
+
getShare = () => {
|
|
58
66
|
const DRIVE_NEW_API_URL = config_service_1.ConfigService.instance.get('DRIVE_NEW_API_URL');
|
|
59
67
|
const apiSecurity = SdkManager.getApiSecurity();
|
|
60
68
|
const appDetails = SdkManager.getAppDetails();
|
|
61
69
|
return sdk_1.Drive.Share.client(DRIVE_NEW_API_URL, appDetails, apiSecurity);
|
|
62
|
-
}
|
|
63
|
-
|
|
70
|
+
};
|
|
71
|
+
getWorkspaces = () => {
|
|
72
|
+
const DRIVE_NEW_API_URL = config_service_1.ConfigService.instance.get('DRIVE_NEW_API_URL');
|
|
73
|
+
const apiSecurity = SdkManager.getApiSecurity();
|
|
74
|
+
const appDetails = SdkManager.getAppDetails();
|
|
75
|
+
return workspaces_1.Workspaces.client(DRIVE_NEW_API_URL, appDetails, apiSecurity);
|
|
76
|
+
};
|
|
77
|
+
getNetwork = (credentials) => {
|
|
64
78
|
const appDetails = SdkManager.getAppDetails();
|
|
65
79
|
const auth = network_utils_1.NetworkUtils.getAuthFromCredentials({
|
|
66
80
|
user: credentials.user,
|
|
@@ -70,6 +84,6 @@ class SdkManager {
|
|
|
70
84
|
bridgeUser: auth.username,
|
|
71
85
|
userId: auth.password,
|
|
72
86
|
});
|
|
73
|
-
}
|
|
87
|
+
};
|
|
74
88
|
}
|
|
75
89
|
exports.SdkManager = SdkManager;
|
|
@@ -1,7 +1,25 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
1
2
|
import { StorageTypes } from '@internxt/sdk/dist/drive';
|
|
2
3
|
import { NetworkFacade } from './network/network-facade.service';
|
|
4
|
+
import { BufferStream } from '../utils/stream.utils';
|
|
3
5
|
export declare class ThumbnailService {
|
|
4
6
|
static readonly instance: ThumbnailService;
|
|
5
|
-
|
|
7
|
+
private static readonly MAX_THUMBNAIL_TIMEOUT;
|
|
8
|
+
uploadThumbnail: (fileContent: Buffer, fileType: string, userBucket: string, file_id: string, networkFacade: NetworkFacade, fileSize: number) => Promise<StorageTypes.Thumbnail | undefined>;
|
|
6
9
|
private readonly getThumbnailFromImageBuffer;
|
|
10
|
+
tryUploadThumbnail: ({ bufferStream, fileType, bucket, fileUuid, networkFacade, size, }: {
|
|
11
|
+
bufferStream?: BufferStream;
|
|
12
|
+
fileType: string;
|
|
13
|
+
bucket: string;
|
|
14
|
+
fileUuid: string;
|
|
15
|
+
networkFacade: NetworkFacade;
|
|
16
|
+
size: number;
|
|
17
|
+
}) => Promise<void>;
|
|
18
|
+
createFileStreamWithBuffer: ({ path, fileType, }: {
|
|
19
|
+
path: string;
|
|
20
|
+
fileType: string;
|
|
21
|
+
}) => {
|
|
22
|
+
bufferStream?: BufferStream;
|
|
23
|
+
fileStream: Readable;
|
|
24
|
+
};
|
|
7
25
|
}
|
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ThumbnailService = void 0;
|
|
4
4
|
const node_stream_1 = require("node:stream");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
5
6
|
const drive_file_service_1 = require("./drive/drive-file.service");
|
|
6
7
|
const drive_1 = require("@internxt/sdk/dist/drive");
|
|
7
8
|
const thumbnail_utils_1 = require("../utils/thumbnail.utils");
|
|
9
|
+
const stream_utils_1 = require("../utils/stream.utils");
|
|
10
|
+
const errors_utils_1 = require("../utils/errors.utils");
|
|
11
|
+
const async_utils_1 = require("../utils/async.utils");
|
|
8
12
|
let sharpDependency = null;
|
|
9
13
|
const getSharp = async () => {
|
|
10
14
|
if (!sharpDependency) {
|
|
@@ -19,9 +23,10 @@ const getSharp = async () => {
|
|
|
19
23
|
};
|
|
20
24
|
class ThumbnailService {
|
|
21
25
|
static instance = new ThumbnailService();
|
|
22
|
-
|
|
26
|
+
static MAX_THUMBNAIL_TIMEOUT = 30000;
|
|
27
|
+
uploadThumbnail = async (fileContent, fileType, userBucket, file_id, networkFacade, fileSize) => {
|
|
23
28
|
let thumbnailBuffer;
|
|
24
|
-
if (
|
|
29
|
+
if (thumbnail_utils_1.ThumbnailUtils.isImageThumbnailable(fileType, fileSize)) {
|
|
25
30
|
thumbnailBuffer = await this.getThumbnailFromImageBuffer(fileContent);
|
|
26
31
|
}
|
|
27
32
|
if (thumbnailBuffer) {
|
|
@@ -62,5 +67,27 @@ class ThumbnailService {
|
|
|
62
67
|
.toBuffer();
|
|
63
68
|
}
|
|
64
69
|
};
|
|
70
|
+
tryUploadThumbnail = async ({ bufferStream, fileType, bucket, fileUuid, networkFacade, size, }) => {
|
|
71
|
+
try {
|
|
72
|
+
const thumbnailBuffer = bufferStream?.getBuffer();
|
|
73
|
+
if (thumbnailBuffer) {
|
|
74
|
+
await async_utils_1.AsyncUtils.withTimeout(ThumbnailService.instance.uploadThumbnail(thumbnailBuffer, fileType, bucket, fileUuid, networkFacade, size), ThumbnailService.MAX_THUMBNAIL_TIMEOUT, 'Thumbnail upload timeout');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
errors_utils_1.ErrorUtils.report(error);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
createFileStreamWithBuffer = ({ path, fileType, }) => {
|
|
82
|
+
const readable = (0, node_fs_1.createReadStream)(path);
|
|
83
|
+
if (thumbnail_utils_1.ThumbnailUtils.isFileThumbnailable(fileType)) {
|
|
84
|
+
const bufferStream = new stream_utils_1.BufferStream();
|
|
85
|
+
return {
|
|
86
|
+
bufferStream,
|
|
87
|
+
fileStream: readable.pipe(bufferStream),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return { fileStream: readable };
|
|
91
|
+
};
|
|
65
92
|
}
|
|
66
93
|
exports.ThumbnailService = ThumbnailService;
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { LoginCredentials } from '../types/command.types';
|
|
2
|
+
import { LogReporter } from '../utils/cli.utils';
|
|
2
3
|
export declare class UniversalLinkService {
|
|
3
4
|
static readonly instance: UniversalLinkService;
|
|
4
5
|
getUserCredentials: (userSession: {
|
|
5
6
|
mnemonic: string;
|
|
6
7
|
token: string;
|
|
8
|
+
privateKey: string;
|
|
7
9
|
}) => Promise<LoginCredentials>;
|
|
8
10
|
buildLoginUrl: (redirectUri: string) => string;
|
|
9
|
-
loginSSO: (jsonFlag: boolean, reporter:
|
|
11
|
+
loginSSO: (jsonFlag: boolean, reporter: LogReporter, hostIp?: string, forcedPort?: number) => Promise<LoginCredentials>;
|
|
10
12
|
}
|
|
@@ -14,11 +14,22 @@ class UniversalLinkService {
|
|
|
14
14
|
getUserCredentials = async (userSession) => {
|
|
15
15
|
const clearMnemonic = Buffer.from(userSession.mnemonic, 'base64').toString('utf-8');
|
|
16
16
|
const clearToken = Buffer.from(userSession.token, 'base64').toString('utf-8');
|
|
17
|
-
const
|
|
17
|
+
const clearPrivateKey = Buffer.from(userSession.privateKey, 'base64').toString('utf-8');
|
|
18
|
+
const loginCredentials = await auth_service_1.AuthService.instance.refreshUserToken(clearToken, clearMnemonic, clearPrivateKey);
|
|
18
19
|
return {
|
|
19
20
|
user: {
|
|
20
21
|
...loginCredentials.user,
|
|
21
22
|
mnemonic: clearMnemonic,
|
|
23
|
+
keys: {
|
|
24
|
+
ecc: {
|
|
25
|
+
privateKey: clearPrivateKey,
|
|
26
|
+
publicKey: loginCredentials.user.keys.ecc.publicKey,
|
|
27
|
+
},
|
|
28
|
+
kyber: {
|
|
29
|
+
privateKey: loginCredentials.user.keys.kyber.privateKey,
|
|
30
|
+
publicKey: loginCredentials.user.keys.kyber.publicKey,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
22
33
|
},
|
|
23
34
|
token: clearToken,
|
|
24
35
|
};
|
|
@@ -41,10 +52,11 @@ class UniversalLinkService {
|
|
|
41
52
|
try {
|
|
42
53
|
const mnemonic = parsedUrl.searchParams.get('mnemonic');
|
|
43
54
|
const token = parsedUrl.searchParams.get('newToken');
|
|
44
|
-
|
|
55
|
+
const privateKey = parsedUrl.searchParams.get('privateKey');
|
|
56
|
+
if (!mnemonic || !token || !privateKey) {
|
|
45
57
|
throw new Error('Login has failed, please try again');
|
|
46
58
|
}
|
|
47
|
-
const loginCredentials = await this.getUserCredentials({ mnemonic, token });
|
|
59
|
+
const loginCredentials = await this.getUserCredentials({ mnemonic, token, privateKey });
|
|
48
60
|
res.writeHead(302, {
|
|
49
61
|
Location: `${driveUrl}/auth-link-ok`,
|
|
50
62
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { UsageResponseV2 } from '@internxt/sdk/dist/drive/storage/types';
|
|
2
1
|
export declare class UsageService {
|
|
3
2
|
static readonly instance: UsageService;
|
|
4
3
|
static readonly INFINITE_LIMIT: number;
|
|
5
|
-
fetchUsage: () => Promise<
|
|
4
|
+
fetchUsage: () => Promise<number>;
|
|
6
5
|
fetchSpaceLimit: () => Promise<number>;
|
|
7
6
|
}
|
|
@@ -8,7 +8,7 @@ class UsageService {
|
|
|
8
8
|
fetchUsage = async () => {
|
|
9
9
|
const storageClient = sdk_manager_service_1.SdkManager.instance.getStorage();
|
|
10
10
|
const driveUsage = await storageClient.spaceUsageV2();
|
|
11
|
-
return driveUsage;
|
|
11
|
+
return driveUsage.total;
|
|
12
12
|
};
|
|
13
13
|
fetchSpaceLimit = async () => {
|
|
14
14
|
const storageClient = sdk_manager_service_1.SdkManager.instance.getStorage();
|
|
@@ -31,12 +31,22 @@ class ValidationService {
|
|
|
31
31
|
return str.trim().length > 0;
|
|
32
32
|
};
|
|
33
33
|
validateDirectoryExists = async (path) => {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
try {
|
|
35
|
+
const directoryStat = await promises_1.default.stat(path);
|
|
36
|
+
return directoryStat.isDirectory();
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
36
41
|
};
|
|
37
42
|
validateFileExists = async (path) => {
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
try {
|
|
44
|
+
const fileStat = await promises_1.default.stat(path);
|
|
45
|
+
return fileStat.isFile();
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
40
50
|
};
|
|
41
51
|
validateJwtAndCheckExpiration = (token) => {
|
|
42
52
|
if (!token || typeof token !== 'string' || token.split('.').length !== 3) {
|
|
@@ -1,12 +1,6 @@
|
|
|
1
|
-
import { ConfigService } from '../../services/config.service';
|
|
2
|
-
import { DriveFolderService } from '../../services/drive/drive-folder.service';
|
|
3
1
|
import { DriveFolderItem } from '../../types/drive.types';
|
|
4
2
|
export declare class WebDavFolderService {
|
|
5
|
-
|
|
6
|
-
constructor(dependencies: {
|
|
7
|
-
driveFolderService: DriveFolderService;
|
|
8
|
-
configService: ConfigService;
|
|
9
|
-
});
|
|
3
|
+
static readonly instance: WebDavFolderService;
|
|
10
4
|
getDriveFolderItemFromPath: (path: string) => Promise<DriveFolderItem | undefined>;
|
|
11
5
|
createFolder: ({ folderName, parentFolderUuid, }: {
|
|
12
6
|
folderName: string;
|