@internxt/cli 1.5.8 → 1.6.1
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 +187 -95
- package/dist/commands/create-folder.d.ts +3 -3
- package/dist/commands/delete-permanently-file.d.ts +2 -2
- package/dist/commands/delete-permanently-folder.d.ts +2 -2
- package/dist/commands/download-file.d.ts +4 -5
- package/dist/commands/download-file.js +22 -37
- package/dist/commands/list.d.ts +4 -4
- package/dist/commands/login-legacy.d.ts +24 -0
- package/dist/commands/login-legacy.js +175 -0
- package/dist/commands/login.d.ts +3 -9
- package/dist/commands/login.js +18 -132
- package/dist/commands/move-file.d.ts +4 -4
- package/dist/commands/move-folder.d.ts +3 -3
- package/dist/commands/rename-file.d.ts +3 -3
- package/dist/commands/rename-folder.d.ts +3 -3
- package/dist/commands/trash-clear.d.ts +2 -2
- package/dist/commands/trash-file.d.ts +2 -2
- package/dist/commands/trash-file.js +1 -1
- package/dist/commands/trash-folder.d.ts +2 -2
- package/dist/commands/trash-folder.js +1 -1
- package/dist/commands/trash-list.d.ts +2 -2
- package/dist/commands/trash-restore-file.d.ts +4 -4
- package/dist/commands/trash-restore-folder.d.ts +3 -3
- package/dist/commands/upload-file.d.ts +8 -8
- package/dist/commands/upload-file.js +7 -40
- package/dist/commands/upload-folder.d.ts +16 -0
- package/dist/commands/upload-folder.js +87 -0
- package/dist/commands/webdav-config.d.ts +6 -6
- package/dist/commands/webdav.d.ts +1 -1
- package/dist/commands/whoami.js +1 -1
- package/dist/hooks/prerun/auth_check.js +2 -1
- package/dist/services/auth.service.d.ts +1 -2
- package/dist/services/auth.service.js +11 -26
- package/dist/services/crypto.service.js +1 -1
- package/dist/services/database/drive-file/drive-file.domain.js +1 -0
- package/dist/services/database/drive-folder/drive-folder.domain.js +1 -0
- package/dist/services/drive/drive-file.service.js +1 -0
- package/dist/services/drive/drive-folder.service.d.ts +1 -1
- package/dist/services/drive/trash.service.d.ts +1 -1
- package/dist/services/local-filesystem/local-filesystem.service.d.ts +6 -0
- package/dist/services/local-filesystem/local-filesystem.service.js +57 -0
- package/dist/services/local-filesystem/local-filesystem.types.d.ts +13 -0
- package/dist/services/local-filesystem/local-filesystem.types.js +2 -0
- package/dist/services/network/upload/upload-facade.service.d.ts +9 -0
- package/dist/services/network/upload/upload-facade.service.js +53 -0
- package/dist/services/network/upload/upload-file.service.d.ts +7 -0
- package/dist/services/network/upload/upload-file.service.js +112 -0
- package/dist/services/network/upload/upload-folder.service.d.ts +6 -0
- package/dist/services/network/upload/upload-folder.service.js +62 -0
- package/dist/services/network/upload/upload.types.d.ts +53 -0
- package/dist/services/network/upload/upload.types.js +6 -0
- package/dist/services/thumbnail.service.js +1 -34
- package/dist/services/universal-link.service.d.ts +10 -0
- package/dist/services/universal-link.service.js +85 -0
- package/dist/types/command.types.d.ts +3 -2
- package/dist/types/command.types.js +8 -1
- package/dist/types/drive.types.d.ts +2 -0
- package/dist/types/fast-xml-parser.types.d.ts +59 -0
- package/dist/types/fast-xml-parser.types.js +2 -0
- package/dist/types/webdav.types.d.ts +0 -1
- package/dist/utils/cli.utils.d.ts +13 -2
- package/dist/utils/cli.utils.js +47 -0
- package/dist/utils/drive.utils.js +3 -0
- package/dist/utils/errors.utils.d.ts +1 -0
- package/dist/utils/errors.utils.js +5 -0
- package/dist/utils/logger.utils.js +10 -0
- package/dist/utils/network.utils.d.ts +2 -2
- package/dist/utils/network.utils.js +7 -5
- package/dist/utils/thumbnail.utils.d.ts +17 -0
- package/dist/utils/thumbnail.utils.js +29 -1
- package/dist/utils/webdav.utils.d.ts +12 -10
- package/dist/utils/webdav.utils.js +39 -29
- package/dist/utils/xml.utils.d.ts +1 -1
- package/dist/webdav/handlers/DELETE.handler.js +5 -5
- package/dist/webdav/handlers/GET.handler.js +43 -33
- package/dist/webdav/handlers/HEAD.handler.js +5 -10
- package/dist/webdav/handlers/MKCOL.handler.js +4 -4
- package/dist/webdav/handlers/MOVE.handler.js +19 -17
- package/dist/webdav/handlers/OPTIONS.handler.js +3 -3
- package/dist/webdav/handlers/PROPFIND.handler.js +7 -31
- package/dist/webdav/handlers/PUT.handler.d.ts +2 -0
- package/dist/webdav/handlers/PUT.handler.js +10 -8
- package/dist/webdav/services/webdav-folder.service.js +5 -4
- package/dist/webdav/webdav-server.js +1 -0
- package/oclif.manifest.json +121 -3
- package/package.json +33 -32
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UploadFacade = void 0;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const cli_utils_1 = require("../../../utils/cli.utils");
|
|
6
|
+
const logger_utils_1 = require("../../../utils/logger.utils");
|
|
7
|
+
const local_filesystem_service_1 = require("../../local-filesystem/local-filesystem.service");
|
|
8
|
+
const upload_folder_service_1 = require("./upload-folder.service");
|
|
9
|
+
const upload_file_service_1 = require("./upload-file.service");
|
|
10
|
+
const async_utils_1 = require("../../../utils/async.utils");
|
|
11
|
+
class UploadFacade {
|
|
12
|
+
static instance = new UploadFacade();
|
|
13
|
+
async uploadFolder({ localPath, destinationFolderUuid, loginUserDetails, jsonFlag, onProgress }) {
|
|
14
|
+
const timer = cli_utils_1.CLIUtils.timer();
|
|
15
|
+
const network = cli_utils_1.CLIUtils.prepareNetwork({ jsonFlag, loginUserDetails });
|
|
16
|
+
const scanResult = await local_filesystem_service_1.LocalFilesystemService.instance.scanLocalDirectory(localPath);
|
|
17
|
+
logger_utils_1.logger.info(`Scanned folder ${localPath}: found ${scanResult.totalItems} items, total size ${scanResult.totalBytes} bytes.`);
|
|
18
|
+
const currentProgress = { itemsUploaded: 0, bytesUploaded: 0 };
|
|
19
|
+
const emitProgress = () => {
|
|
20
|
+
const itemProgress = currentProgress.itemsUploaded / scanResult.totalItems;
|
|
21
|
+
const sizeProgress = currentProgress.bytesUploaded / scanResult.totalBytes;
|
|
22
|
+
const percentage = Math.floor((itemProgress * 0.5 + sizeProgress * 0.5) * 100);
|
|
23
|
+
onProgress({ percentage });
|
|
24
|
+
};
|
|
25
|
+
const folderMap = await upload_folder_service_1.UploadFolderService.instance.createFolders({
|
|
26
|
+
foldersToCreate: scanResult.folders,
|
|
27
|
+
destinationFolderUuid,
|
|
28
|
+
currentProgress,
|
|
29
|
+
emitProgress,
|
|
30
|
+
});
|
|
31
|
+
if (folderMap.size === 0) {
|
|
32
|
+
throw new Error('Failed to create folders, cannot upload files');
|
|
33
|
+
}
|
|
34
|
+
await async_utils_1.AsyncUtils.sleep(500);
|
|
35
|
+
const totalBytes = await upload_file_service_1.UploadFileService.instance.uploadFilesInChunks({
|
|
36
|
+
network,
|
|
37
|
+
filesToUpload: scanResult.files,
|
|
38
|
+
folderMap,
|
|
39
|
+
bucket: loginUserDetails.bucket,
|
|
40
|
+
destinationFolderUuid,
|
|
41
|
+
currentProgress,
|
|
42
|
+
emitProgress,
|
|
43
|
+
});
|
|
44
|
+
const rootFolderName = (0, node_path_1.basename)(localPath);
|
|
45
|
+
const rootFolderId = folderMap.get(rootFolderName) ?? '';
|
|
46
|
+
return {
|
|
47
|
+
totalBytes,
|
|
48
|
+
rootFolderId,
|
|
49
|
+
uploadTimeMs: timer.stop(),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.UploadFacade = UploadFacade;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { UploadFilesInBatchesParams, UploadFileWithRetryParams } from './upload.types';
|
|
2
|
+
export declare class UploadFileService {
|
|
3
|
+
static readonly instance: UploadFileService;
|
|
4
|
+
uploadFilesInChunks({ network, filesToUpload, folderMap, bucket, destinationFolderUuid, currentProgress, emitProgress, }: UploadFilesInBatchesParams): Promise<number>;
|
|
5
|
+
uploadFileWithRetry({ file, network, bucket, parentFolderUuid, }: UploadFileWithRetryParams): Promise<string | null>;
|
|
6
|
+
private chunkArray;
|
|
7
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UploadFileService = void 0;
|
|
4
|
+
const logger_utils_1 = require("../../../utils/logger.utils");
|
|
5
|
+
const upload_types_1 = require("./upload.types");
|
|
6
|
+
const drive_file_service_1 = require("../../drive/drive-file.service");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const errors_utils_1 = require("../../../utils/errors.utils");
|
|
9
|
+
const promises_1 = require("node:fs/promises");
|
|
10
|
+
const types_1 = require("@internxt/sdk/dist/drive/storage/types");
|
|
11
|
+
const thumbnail_utils_1 = require("../../../utils/thumbnail.utils");
|
|
12
|
+
class UploadFileService {
|
|
13
|
+
static instance = new UploadFileService();
|
|
14
|
+
async uploadFilesInChunks({ network, filesToUpload, folderMap, bucket, destinationFolderUuid, currentProgress, emitProgress, }) {
|
|
15
|
+
let bytesUploaded = 0;
|
|
16
|
+
const chunks = this.chunkArray(filesToUpload, upload_types_1.MAX_CONCURRENT_UPLOADS);
|
|
17
|
+
for (const chunk of chunks) {
|
|
18
|
+
await Promise.allSettled(chunk.map(async (file) => {
|
|
19
|
+
const parentPath = (0, node_path_1.dirname)(file.relativePath);
|
|
20
|
+
const parentFolderUuid = parentPath === '.' || parentPath === '' ? destinationFolderUuid : folderMap.get(parentPath);
|
|
21
|
+
if (!parentFolderUuid) {
|
|
22
|
+
logger_utils_1.logger.warn(`Parent folder not found for ${file.relativePath}, skipping...`);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const createdFileUuid = await this.uploadFileWithRetry({
|
|
26
|
+
file,
|
|
27
|
+
network,
|
|
28
|
+
bucket,
|
|
29
|
+
parentFolderUuid,
|
|
30
|
+
});
|
|
31
|
+
if (createdFileUuid) {
|
|
32
|
+
bytesUploaded += file.size;
|
|
33
|
+
currentProgress.bytesUploaded += file.size;
|
|
34
|
+
currentProgress.itemsUploaded++;
|
|
35
|
+
}
|
|
36
|
+
emitProgress();
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
return bytesUploaded;
|
|
40
|
+
}
|
|
41
|
+
async uploadFileWithRetry({ file, network, bucket, parentFolderUuid, }) {
|
|
42
|
+
for (let attempt = 0; attempt <= upload_types_1.MAX_RETRIES; attempt++) {
|
|
43
|
+
try {
|
|
44
|
+
const stats = await (0, promises_1.stat)(file.absolutePath);
|
|
45
|
+
if (!stats.size) {
|
|
46
|
+
logger_utils_1.logger.warn(`Skipping empty file: ${file.relativePath}`);
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const fileType = (0, node_path_1.extname)(file.absolutePath).replaceAll('.', '');
|
|
50
|
+
const { fileStream, bufferStream } = (0, thumbnail_utils_1.createFileStreamWithBuffer)({
|
|
51
|
+
path: file.absolutePath,
|
|
52
|
+
fileType,
|
|
53
|
+
});
|
|
54
|
+
const fileId = await new Promise((resolve, reject) => {
|
|
55
|
+
network.uploadFile(fileStream, stats.size, bucket, (err, res) => {
|
|
56
|
+
if (err) {
|
|
57
|
+
return reject(err);
|
|
58
|
+
}
|
|
59
|
+
resolve(res);
|
|
60
|
+
}, () => { });
|
|
61
|
+
});
|
|
62
|
+
const createdDriveFile = await drive_file_service_1.DriveFileService.instance.createFile({
|
|
63
|
+
plainName: file.name,
|
|
64
|
+
type: fileType,
|
|
65
|
+
size: stats.size,
|
|
66
|
+
folderUuid: parentFolderUuid,
|
|
67
|
+
fileId,
|
|
68
|
+
bucket,
|
|
69
|
+
encryptVersion: types_1.EncryptionVersion.Aes03,
|
|
70
|
+
creationTime: stats.birthtime?.toISOString(),
|
|
71
|
+
modificationTime: stats.mtime?.toISOString(),
|
|
72
|
+
});
|
|
73
|
+
if (bufferStream) {
|
|
74
|
+
void (0, thumbnail_utils_1.tryUploadThumbnail)({
|
|
75
|
+
bufferStream,
|
|
76
|
+
fileType,
|
|
77
|
+
userBucket: bucket,
|
|
78
|
+
fileUuid: createdDriveFile.uuid,
|
|
79
|
+
networkFacade: network,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return createdDriveFile.fileId;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if ((0, errors_utils_1.isAlreadyExistsError)(error)) {
|
|
86
|
+
const msg = `File ${file.name} already exists, skipping...`;
|
|
87
|
+
logger_utils_1.logger.info(msg);
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
if (attempt < upload_types_1.MAX_RETRIES) {
|
|
91
|
+
const delay = upload_types_1.DELAYS_MS[attempt];
|
|
92
|
+
const retryMsg = `Failed to upload file ${file.name}, retrying in ${delay}ms...`;
|
|
93
|
+
logger_utils_1.logger.warn(`${retryMsg} (attempt ${attempt + 1}/${upload_types_1.MAX_RETRIES + 1})`);
|
|
94
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
logger_utils_1.logger.error(`Failed to upload file ${file.name} after ${upload_types_1.MAX_RETRIES + 1} attempts`);
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
chunkArray(array, chunkSize) {
|
|
105
|
+
const chunks = [];
|
|
106
|
+
for (let i = 0; i < array.length; i += chunkSize) {
|
|
107
|
+
chunks.push(array.slice(i, i + chunkSize));
|
|
108
|
+
}
|
|
109
|
+
return chunks;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.UploadFileService = UploadFileService;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CreateFoldersParams, CreateFolderWithRetryParams } from './upload.types';
|
|
2
|
+
export declare class UploadFolderService {
|
|
3
|
+
static readonly instance: UploadFolderService;
|
|
4
|
+
createFolders({ foldersToCreate, destinationFolderUuid, currentProgress, emitProgress, }: CreateFoldersParams): Promise<Map<string, string>>;
|
|
5
|
+
createFolderWithRetry({ folderName, parentFolderUuid }: CreateFolderWithRetryParams): Promise<string | null>;
|
|
6
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UploadFolderService = void 0;
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
5
|
+
const errors_utils_1 = require("../../../utils/errors.utils");
|
|
6
|
+
const logger_utils_1 = require("../../../utils/logger.utils");
|
|
7
|
+
const drive_folder_service_1 = require("../../drive/drive-folder.service");
|
|
8
|
+
const upload_types_1 = require("./upload.types");
|
|
9
|
+
class UploadFolderService {
|
|
10
|
+
static instance = new UploadFolderService();
|
|
11
|
+
async createFolders({ foldersToCreate, destinationFolderUuid, currentProgress, emitProgress, }) {
|
|
12
|
+
const folderMap = new Map();
|
|
13
|
+
for (const folder of foldersToCreate) {
|
|
14
|
+
const parentPath = (0, node_path_1.dirname)(folder.relativePath);
|
|
15
|
+
const parentUuid = parentPath === '.' ? destinationFolderUuid : folderMap.get(parentPath);
|
|
16
|
+
if (!parentUuid) {
|
|
17
|
+
logger_utils_1.logger.warn(`Parent folder not found for ${folder.relativePath}, skipping...`);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const createdFolderUuid = await this.createFolderWithRetry({
|
|
21
|
+
folderName: folder.name,
|
|
22
|
+
parentFolderUuid: parentUuid,
|
|
23
|
+
});
|
|
24
|
+
if (createdFolderUuid) {
|
|
25
|
+
folderMap.set(folder.relativePath, createdFolderUuid);
|
|
26
|
+
currentProgress.itemsUploaded++;
|
|
27
|
+
emitProgress();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return folderMap;
|
|
31
|
+
}
|
|
32
|
+
async createFolderWithRetry({ folderName, parentFolderUuid }) {
|
|
33
|
+
for (let attempt = 0; attempt <= upload_types_1.MAX_RETRIES; attempt++) {
|
|
34
|
+
try {
|
|
35
|
+
const [createFolderPromise] = drive_folder_service_1.DriveFolderService.instance.createFolder({
|
|
36
|
+
plainName: folderName,
|
|
37
|
+
parentFolderUuid,
|
|
38
|
+
});
|
|
39
|
+
const createdFolder = await createFolderPromise;
|
|
40
|
+
return createdFolder.uuid;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if ((0, errors_utils_1.isAlreadyExistsError)(error)) {
|
|
44
|
+
logger_utils_1.logger.info(`Folder ${folderName} already exists, skipping...`);
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
if (attempt < upload_types_1.MAX_RETRIES) {
|
|
48
|
+
const delay = upload_types_1.DELAYS_MS[attempt];
|
|
49
|
+
logger_utils_1.logger.warn(`Failed to create folder ${folderName},
|
|
50
|
+
retrying in ${delay}ms... (attempt ${attempt + 1}/${upload_types_1.MAX_RETRIES + 1})`);
|
|
51
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
logger_utils_1.logger.error(`Failed to create folder ${folderName} after ${upload_types_1.MAX_RETRIES + 1} attempts`);
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.UploadFolderService = UploadFolderService;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { LoginUserDetails } from '../../../types/command.types';
|
|
2
|
+
import { FileSystemNode } from '../../local-filesystem/local-filesystem.types';
|
|
3
|
+
import { NetworkFacade } from '../network-facade.service';
|
|
4
|
+
export interface UploadResult {
|
|
5
|
+
totalBytes: number;
|
|
6
|
+
rootFolderId: string;
|
|
7
|
+
uploadTimeMs: number;
|
|
8
|
+
}
|
|
9
|
+
export interface UploadFolderParams {
|
|
10
|
+
localPath: string;
|
|
11
|
+
destinationFolderUuid: string;
|
|
12
|
+
loginUserDetails: LoginUserDetails;
|
|
13
|
+
jsonFlag?: boolean;
|
|
14
|
+
onProgress: (progress: UploadProgress) => void;
|
|
15
|
+
}
|
|
16
|
+
export interface UploadProgress {
|
|
17
|
+
percentage: number;
|
|
18
|
+
currentFile?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface CreateFoldersParams {
|
|
21
|
+
foldersToCreate: FileSystemNode[];
|
|
22
|
+
destinationFolderUuid: string;
|
|
23
|
+
currentProgress: {
|
|
24
|
+
itemsUploaded: number;
|
|
25
|
+
bytesUploaded: number;
|
|
26
|
+
};
|
|
27
|
+
emitProgress: () => void;
|
|
28
|
+
}
|
|
29
|
+
export interface CreateFolderWithRetryParams {
|
|
30
|
+
folderName: string;
|
|
31
|
+
parentFolderUuid: string;
|
|
32
|
+
}
|
|
33
|
+
export interface UploadFilesInBatchesParams {
|
|
34
|
+
network: NetworkFacade;
|
|
35
|
+
filesToUpload: FileSystemNode[];
|
|
36
|
+
folderMap: Map<string, string>;
|
|
37
|
+
bucket: string;
|
|
38
|
+
destinationFolderUuid: string;
|
|
39
|
+
currentProgress: {
|
|
40
|
+
itemsUploaded: number;
|
|
41
|
+
bytesUploaded: number;
|
|
42
|
+
};
|
|
43
|
+
emitProgress: () => void;
|
|
44
|
+
}
|
|
45
|
+
export interface UploadFileWithRetryParams {
|
|
46
|
+
file: FileSystemNode;
|
|
47
|
+
network: NetworkFacade;
|
|
48
|
+
bucket: string;
|
|
49
|
+
parentFolderUuid: string;
|
|
50
|
+
}
|
|
51
|
+
export declare const MAX_CONCURRENT_UPLOADS = 5;
|
|
52
|
+
export declare const DELAYS_MS: number[];
|
|
53
|
+
export declare const MAX_RETRIES = 2;
|
|
@@ -1,37 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
3
|
exports.ThumbnailService = void 0;
|
|
37
4
|
const node_stream_1 = require("node:stream");
|
|
@@ -42,7 +9,7 @@ let sharpDependency = null;
|
|
|
42
9
|
const getSharp = async () => {
|
|
43
10
|
if (!sharpDependency) {
|
|
44
11
|
try {
|
|
45
|
-
sharpDependency = (await
|
|
12
|
+
sharpDependency = (await import('sharp')).default;
|
|
46
13
|
}
|
|
47
14
|
catch {
|
|
48
15
|
return null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { LoginCredentials } from '../types/command.types';
|
|
2
|
+
export declare class UniversalLinkService {
|
|
3
|
+
static readonly instance: UniversalLinkService;
|
|
4
|
+
getUserCredentials: (userSession: {
|
|
5
|
+
mnemonic: string;
|
|
6
|
+
token: string;
|
|
7
|
+
}) => Promise<LoginCredentials>;
|
|
8
|
+
buildLoginUrl: (redirectUri: string) => string;
|
|
9
|
+
loginSSO: (jsonFlag: boolean, reporter: (message: string) => void, hostIp?: string, forcedPort?: number) => Promise<LoginCredentials>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.UniversalLinkService = void 0;
|
|
7
|
+
const node_http_1 = __importDefault(require("node:http"));
|
|
8
|
+
const open_1 = __importDefault(require("open"));
|
|
9
|
+
const config_service_1 = require("./config.service");
|
|
10
|
+
const auth_service_1 = require("./auth.service");
|
|
11
|
+
const cli_utils_1 = require("../utils/cli.utils");
|
|
12
|
+
class UniversalLinkService {
|
|
13
|
+
static instance = new UniversalLinkService();
|
|
14
|
+
getUserCredentials = async (userSession) => {
|
|
15
|
+
const clearMnemonic = Buffer.from(userSession.mnemonic, 'base64').toString('utf-8');
|
|
16
|
+
const clearToken = Buffer.from(userSession.token, 'base64').toString('utf-8');
|
|
17
|
+
const loginCredentials = await auth_service_1.AuthService.instance.refreshUserToken(clearToken, clearMnemonic);
|
|
18
|
+
return {
|
|
19
|
+
user: {
|
|
20
|
+
...loginCredentials.user,
|
|
21
|
+
mnemonic: clearMnemonic,
|
|
22
|
+
},
|
|
23
|
+
token: clearToken,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
buildLoginUrl = (redirectUri) => {
|
|
27
|
+
const loginURL = `${config_service_1.ConfigService.instance.get('DRIVE_WEB_URL')}/login`;
|
|
28
|
+
const params = new URLSearchParams({
|
|
29
|
+
universalLink: 'true',
|
|
30
|
+
redirectUri: redirectUri,
|
|
31
|
+
});
|
|
32
|
+
return `${loginURL}?${params.toString()}`;
|
|
33
|
+
};
|
|
34
|
+
loginSSO = async (jsonFlag, reporter, hostIp = '127.0.0.1', forcedPort = 0) => {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const server = node_http_1.default.createServer(async (req, res) => {
|
|
37
|
+
if (!req.url)
|
|
38
|
+
return;
|
|
39
|
+
const parsedUrl = new URL(req.url, `http://${req.headers.host}`);
|
|
40
|
+
const driveUrl = config_service_1.ConfigService.instance.get('DRIVE_WEB_URL');
|
|
41
|
+
try {
|
|
42
|
+
const mnemonic = parsedUrl.searchParams.get('mnemonic');
|
|
43
|
+
const token = parsedUrl.searchParams.get('newToken');
|
|
44
|
+
if (!mnemonic || !token) {
|
|
45
|
+
throw new Error('Login has failed, please try again');
|
|
46
|
+
}
|
|
47
|
+
const loginCredentials = await this.getUserCredentials({ mnemonic, token });
|
|
48
|
+
res.writeHead(302, {
|
|
49
|
+
Location: `${driveUrl}/auth-link-ok`,
|
|
50
|
+
});
|
|
51
|
+
res.end();
|
|
52
|
+
resolve(loginCredentials);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
res.writeHead(302, {
|
|
56
|
+
Location: `${driveUrl}/auth-link-error`,
|
|
57
|
+
});
|
|
58
|
+
res.end();
|
|
59
|
+
reject(error);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
server.closeAllConnections();
|
|
63
|
+
server.close();
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
server.listen(forcedPort, async () => {
|
|
67
|
+
const { port } = server.address();
|
|
68
|
+
const redirectUri = Buffer.from(`http://${hostIp}:${port}/callback`).toString('base64');
|
|
69
|
+
const loginUrl = this.buildLoginUrl(redirectUri);
|
|
70
|
+
cli_utils_1.CLIUtils.log(reporter, 'Opening browser for login...');
|
|
71
|
+
cli_utils_1.CLIUtils.log(reporter, 'If the browser doesn’t open automatically, visit:');
|
|
72
|
+
const printLoginUrl = jsonFlag ? `{ "loginUrl": "${loginUrl}" }` : loginUrl;
|
|
73
|
+
cli_utils_1.CLIUtils.consoleLog(printLoginUrl);
|
|
74
|
+
try {
|
|
75
|
+
await (0, open_1.default)(loginUrl);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
cli_utils_1.CLIUtils.warning(reporter, 'Could not open browser automatically.');
|
|
79
|
+
}
|
|
80
|
+
cli_utils_1.CLIUtils.log(reporter, 'Waiting for authentication...');
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
exports.UniversalLinkService = UniversalLinkService;
|
|
@@ -26,8 +26,6 @@ export interface LoginUserDetails {
|
|
|
26
26
|
export interface LoginCredentials {
|
|
27
27
|
user: LoginUserDetails;
|
|
28
28
|
token: string;
|
|
29
|
-
lastLoggedInAt: string;
|
|
30
|
-
lastTokenRefreshAt: string;
|
|
31
29
|
}
|
|
32
30
|
export interface WebdavConfig {
|
|
33
31
|
host: string;
|
|
@@ -51,6 +49,9 @@ export declare class NotValidFolderUuidError extends Error {
|
|
|
51
49
|
export declare class NotValidFileUuidError extends Error {
|
|
52
50
|
constructor();
|
|
53
51
|
}
|
|
52
|
+
export declare class NotValidFileIdError extends Error {
|
|
53
|
+
constructor();
|
|
54
|
+
}
|
|
54
55
|
export declare class NoRootFolderIdFoundError extends Error {
|
|
55
56
|
constructor();
|
|
56
57
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.NotValidFileError = exports.NotValidDirectoryError = exports.NotValidPortError = exports.EmptyFolderNameError = exports.EmptyFileNameError = exports.InvalidCredentialsError = exports.ExpiredCredentialsError = exports.MissingCredentialsError = exports.NoRootFolderIdFoundError = exports.NotValidFileUuidError = exports.NotValidFolderUuidError = exports.NotValidTwoFactorCodeError = exports.EmptyPasswordError = exports.NotValidEmailError = void 0;
|
|
3
|
+
exports.NotValidFileError = exports.NotValidDirectoryError = exports.NotValidPortError = exports.EmptyFolderNameError = exports.EmptyFileNameError = exports.InvalidCredentialsError = exports.ExpiredCredentialsError = exports.MissingCredentialsError = exports.NoRootFolderIdFoundError = exports.NotValidFileIdError = exports.NotValidFileUuidError = exports.NotValidFolderUuidError = exports.NotValidTwoFactorCodeError = exports.EmptyPasswordError = exports.NotValidEmailError = void 0;
|
|
4
4
|
class NotValidEmailError extends Error {
|
|
5
5
|
constructor() {
|
|
6
6
|
super('Email is not valid');
|
|
@@ -36,6 +36,13 @@ class NotValidFileUuidError extends Error {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
exports.NotValidFileUuidError = NotValidFileUuidError;
|
|
39
|
+
class NotValidFileIdError extends Error {
|
|
40
|
+
constructor() {
|
|
41
|
+
super('FileId is not valid');
|
|
42
|
+
Object.setPrototypeOf(this, NotValidFileIdError.prototype);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.NotValidFileIdError = NotValidFileIdError;
|
|
39
46
|
class NoRootFolderIdFoundError extends Error {
|
|
40
47
|
constructor() {
|
|
41
48
|
super('No root folder id found on your account');
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DriveFolderData, FileMeta } from '@internxt/sdk/dist/drive/storage/types';
|
|
2
2
|
export type DriveFileItem = Omit<FileMeta, 'plainName' | 'userId' | 'encryptVersion' | 'size' | 'createdAt' | 'updatedAt' | 'creationTime' | 'modificationTime' | 'type'> & {
|
|
3
|
+
itemType: 'file';
|
|
3
4
|
size: number;
|
|
4
5
|
createdAt: Date;
|
|
5
6
|
updatedAt: Date;
|
|
@@ -8,6 +9,7 @@ export type DriveFileItem = Omit<FileMeta, 'plainName' | 'userId' | 'encryptVers
|
|
|
8
9
|
type?: string | null;
|
|
9
10
|
};
|
|
10
11
|
export type DriveFolderItem = Pick<DriveFolderData, 'name' | 'bucket' | 'id' | 'parentId'> & {
|
|
12
|
+
itemType: 'folder';
|
|
11
13
|
encryptedName: string;
|
|
12
14
|
uuid: string;
|
|
13
15
|
createdAt: Date;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
type strnumOptions = {
|
|
2
|
+
hex: boolean;
|
|
3
|
+
leadingZeros: boolean;
|
|
4
|
+
skipLike?: RegExp;
|
|
5
|
+
eNotation?: boolean;
|
|
6
|
+
};
|
|
7
|
+
export type X2jOptions = {
|
|
8
|
+
preserveOrder?: boolean;
|
|
9
|
+
attributeNamePrefix?: string;
|
|
10
|
+
attributesGroupName?: false | string;
|
|
11
|
+
textNodeName?: string;
|
|
12
|
+
ignoreAttributes?: boolean | (string | RegExp)[] | ((attrName: string, jPath: string) => boolean);
|
|
13
|
+
removeNSPrefix?: boolean;
|
|
14
|
+
allowBooleanAttributes?: boolean;
|
|
15
|
+
parseTagValue?: boolean;
|
|
16
|
+
parseAttributeValue?: boolean;
|
|
17
|
+
trimValues?: boolean;
|
|
18
|
+
cdataPropName?: false | string;
|
|
19
|
+
commentPropName?: false | string;
|
|
20
|
+
tagValueProcessor?: (tagName: string, tagValue: string, jPath: string, hasAttributes: boolean, isLeafNode: boolean) => unknown;
|
|
21
|
+
attributeValueProcessor?: (attrName: string, attrValue: string, jPath: string) => unknown;
|
|
22
|
+
numberParseOptions?: strnumOptions;
|
|
23
|
+
stopNodes?: string[];
|
|
24
|
+
unpairedTags?: string[];
|
|
25
|
+
alwaysCreateTextNode?: boolean;
|
|
26
|
+
isArray?: (tagName: string, jPath: string, isLeafNode: boolean, isAttribute: boolean) => boolean;
|
|
27
|
+
processEntities?: boolean;
|
|
28
|
+
htmlEntities?: boolean;
|
|
29
|
+
ignoreDeclaration?: boolean;
|
|
30
|
+
ignorePiTags?: boolean;
|
|
31
|
+
transformTagName?: ((tagName: string) => string) | false;
|
|
32
|
+
transformAttributeName?: ((attributeName: string) => string) | false;
|
|
33
|
+
updateTag?: (tagName: string, jPath: string, attrs: {
|
|
34
|
+
[k: string]: string;
|
|
35
|
+
}) => string | boolean;
|
|
36
|
+
captureMetaData?: boolean;
|
|
37
|
+
};
|
|
38
|
+
export type XmlBuilderOptions = {
|
|
39
|
+
attributeNamePrefix?: string;
|
|
40
|
+
attributesGroupName?: false | string;
|
|
41
|
+
textNodeName?: string;
|
|
42
|
+
ignoreAttributes?: boolean | (string | RegExp)[] | ((attrName: string, jPath: string) => boolean);
|
|
43
|
+
cdataPropName?: false | string;
|
|
44
|
+
commentPropName?: false | string;
|
|
45
|
+
format?: boolean;
|
|
46
|
+
indentBy?: string;
|
|
47
|
+
arrayNodeName?: string;
|
|
48
|
+
suppressEmptyNode?: boolean;
|
|
49
|
+
suppressUnpairedNode?: boolean;
|
|
50
|
+
suppressBooleanAttributes?: boolean;
|
|
51
|
+
preserveOrder?: boolean;
|
|
52
|
+
unpairedTags?: string[];
|
|
53
|
+
stopNodes?: string[];
|
|
54
|
+
tagValueProcessor?: (name: string, value: unknown) => unknown;
|
|
55
|
+
attributeValueProcessor?: (name: string, value: unknown) => unknown;
|
|
56
|
+
processEntities?: boolean;
|
|
57
|
+
oneListGroup?: boolean;
|
|
58
|
+
};
|
|
59
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import cliProgress from 'cli-progress';
|
|
2
2
|
import { Header } from 'tty-table';
|
|
3
|
-
import { PromptOptions } from '../types/command.types';
|
|
3
|
+
import { LoginUserDetails, PromptOptions } from '../types/command.types';
|
|
4
|
+
import { NetworkFacade } from '../services/network/network-facade.service';
|
|
4
5
|
export declare class CLIUtils {
|
|
5
6
|
static readonly clearPreviousLine: (jsonFlag?: boolean) => void;
|
|
6
7
|
static readonly warning: (reporter: (message: string) => void, message: string) => void;
|
|
@@ -15,7 +16,7 @@ export declare class CLIUtils {
|
|
|
15
16
|
static readonly table: (reporter: (message: string) => void, header: Header[], rows: object[]) => void;
|
|
16
17
|
static readonly generateTableHeaderFromType: <T extends object>() => Header[];
|
|
17
18
|
static readonly CommonFlags: {
|
|
18
|
-
'non-interactive': import("@oclif/core/
|
|
19
|
+
'non-interactive': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
20
|
};
|
|
20
21
|
static readonly getValueFromFlag: (flag: {
|
|
21
22
|
value?: string;
|
|
@@ -32,6 +33,12 @@ export declare class CLIUtils {
|
|
|
32
33
|
error: Error;
|
|
33
34
|
canBeEmpty?: boolean;
|
|
34
35
|
}, reporter: (message: string) => void) => Promise<string>;
|
|
36
|
+
static readonly getDestinationFolderUuid: ({ destinationFolderUuidFlag, destinationFlagName, nonInteractive, reporter, }: {
|
|
37
|
+
destinationFolderUuidFlag: string | undefined;
|
|
38
|
+
destinationFlagName: string;
|
|
39
|
+
nonInteractive: boolean;
|
|
40
|
+
reporter: (message: string) => void;
|
|
41
|
+
}) => Promise<string | undefined>;
|
|
35
42
|
private static readonly promptWithAttempts;
|
|
36
43
|
static readonly timer: () => {
|
|
37
44
|
stop: () => number;
|
|
@@ -43,6 +50,10 @@ export declare class CLIUtils {
|
|
|
43
50
|
jsonFlag?: boolean;
|
|
44
51
|
}) => void;
|
|
45
52
|
static readonly parseEmpty: (input: string) => Promise<string>;
|
|
53
|
+
static readonly prepareNetwork: ({ jsonFlag, loginUserDetails, }: {
|
|
54
|
+
jsonFlag?: boolean;
|
|
55
|
+
loginUserDetails: LoginUserDetails;
|
|
56
|
+
}) => NetworkFacade;
|
|
46
57
|
}
|
|
47
58
|
export declare class NoFlagProvidedError extends Error {
|
|
48
59
|
constructor(flag: string);
|