@internxt/cli 1.6.0 → 1.6.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/README.md +89 -27
- package/dist/commands/add-cert.js +2 -2
- 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 +5 -5
- package/dist/commands/login.d.ts +2 -2
- package/dist/commands/logs.js +3 -3
- 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-folder.d.ts +2 -2
- 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 +6 -7
- package/dist/commands/upload-file.js +61 -80
- 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/constants/configs.d.ts +12 -0
- package/dist/constants/configs.js +20 -0
- package/dist/services/auth.service.js +11 -6
- package/dist/services/config.service.d.ts +0 -12
- package/dist/services/config.service.js +33 -38
- 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 +8 -0
- package/dist/services/network/upload/upload-file.service.js +134 -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/sdk-manager.service.d.ts +2 -2
- package/dist/services/sdk-manager.service.js +2 -2
- package/dist/services/thumbnail.service.js +1 -34
- package/dist/services/validation.service.d.ts +5 -0
- package/dist/services/validation.service.js +22 -18
- package/dist/types/command.types.d.ts +3 -0
- package/dist/types/command.types.js +8 -1
- package/dist/types/fast-xml-parser.types.d.ts +59 -0
- package/dist/types/fast-xml-parser.types.js +2 -0
- package/dist/utils/cli.utils.d.ts +16 -2
- package/dist/utils/cli.utils.js +84 -3
- package/dist/utils/errors.utils.d.ts +2 -0
- package/dist/utils/errors.utils.js +13 -2
- package/dist/utils/logger.utils.js +5 -5
- package/dist/utils/network.utils.d.ts +2 -2
- package/dist/utils/network.utils.js +24 -23
- package/dist/utils/thumbnail.utils.d.ts +17 -0
- package/dist/utils/thumbnail.utils.js +36 -8
- package/dist/utils/xml.utils.d.ts +2 -2
- package/dist/utils/xml.utils.js +1 -1
- package/dist/webdav/handlers/GET.handler.js +37 -26
- package/dist/webdav/handlers/PUT.handler.js +56 -41
- package/dist/webdav/middewares/errors.middleware.js +1 -1
- package/dist/webdav/webdav-server.js +4 -4
- package/oclif.manifest.json +62 -1
- package/package.json +24 -24
|
@@ -5,8 +5,8 @@ export default class TrashFile extends Command {
|
|
|
5
5
|
static readonly aliases: string[];
|
|
6
6
|
static readonly examples: string[];
|
|
7
7
|
static readonly flags: {
|
|
8
|
-
id: import("@oclif/core/
|
|
9
|
-
'non-interactive': import("@oclif/core/
|
|
8
|
+
id: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'non-interactive': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
};
|
|
11
11
|
static readonly enableJsonFlag = true;
|
|
12
12
|
run: () => Promise<{
|
|
@@ -5,8 +5,8 @@ export default class TrashFolder extends Command {
|
|
|
5
5
|
static readonly aliases: string[];
|
|
6
6
|
static readonly examples: string[];
|
|
7
7
|
static readonly flags: {
|
|
8
|
-
id: import("@oclif/core/
|
|
9
|
-
'non-interactive': import("@oclif/core/
|
|
8
|
+
id: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
'non-interactive': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
10
|
};
|
|
11
11
|
static readonly enableJsonFlag = true;
|
|
12
12
|
run: () => Promise<{
|
|
@@ -5,7 +5,7 @@ export default class TrashList extends Command {
|
|
|
5
5
|
static readonly aliases: string[];
|
|
6
6
|
static readonly examples: string[];
|
|
7
7
|
static readonly flags: {
|
|
8
|
-
extended: import("@oclif/core/
|
|
8
|
+
extended: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
9
|
};
|
|
10
10
|
static readonly enableJsonFlag = true;
|
|
11
11
|
run: () => Promise<{
|
|
@@ -35,7 +35,7 @@ export default class TrashList extends Command {
|
|
|
35
35
|
files: {
|
|
36
36
|
id: number;
|
|
37
37
|
uuid: string;
|
|
38
|
-
fileId: string;
|
|
38
|
+
fileId: string | null;
|
|
39
39
|
name: string;
|
|
40
40
|
type: string;
|
|
41
41
|
size: string;
|
|
@@ -5,9 +5,9 @@ export default class TrashRestoreFile extends Command {
|
|
|
5
5
|
static readonly aliases: string[];
|
|
6
6
|
static readonly examples: string[];
|
|
7
7
|
static readonly flags: {
|
|
8
|
-
id: import("@oclif/core/
|
|
9
|
-
destination: import("@oclif/core/
|
|
10
|
-
'non-interactive': import("@oclif/core/
|
|
8
|
+
id: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
destination: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'non-interactive': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
};
|
|
12
12
|
static readonly enableJsonFlag = true;
|
|
13
13
|
run: () => Promise<{
|
|
@@ -16,7 +16,7 @@ export default class TrashRestoreFile extends Command {
|
|
|
16
16
|
file: {
|
|
17
17
|
id: number;
|
|
18
18
|
uuid: string;
|
|
19
|
-
fileId: string;
|
|
19
|
+
fileId: string | null;
|
|
20
20
|
name: string;
|
|
21
21
|
type: string;
|
|
22
22
|
size: string;
|
|
@@ -5,9 +5,9 @@ export default class TrashRestoreFolder extends Command {
|
|
|
5
5
|
static readonly aliases: string[];
|
|
6
6
|
static readonly examples: string[];
|
|
7
7
|
static readonly flags: {
|
|
8
|
-
id: import("@oclif/core/
|
|
9
|
-
destination: import("@oclif/core/
|
|
10
|
-
'non-interactive': import("@oclif/core/
|
|
8
|
+
id: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
destination: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'non-interactive': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
};
|
|
12
12
|
static readonly enableJsonFlag = true;
|
|
13
13
|
run: () => Promise<{
|
|
@@ -5,9 +5,9 @@ export default class UploadFile extends Command {
|
|
|
5
5
|
static readonly aliases: string[];
|
|
6
6
|
static readonly examples: string[];
|
|
7
7
|
static readonly flags: {
|
|
8
|
-
file: import("@oclif/core/
|
|
9
|
-
destination: import("@oclif/core/
|
|
10
|
-
'non-interactive': import("@oclif/core/
|
|
8
|
+
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
destination: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'non-interactive': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
};
|
|
12
12
|
static readonly enableJsonFlag = true;
|
|
13
13
|
run: () => Promise<{
|
|
@@ -16,13 +16,13 @@ export default class UploadFile extends Command {
|
|
|
16
16
|
file: {
|
|
17
17
|
plainName: string;
|
|
18
18
|
name: string;
|
|
19
|
+
status: "EXISTS" | "TRASHED" | "DELETED";
|
|
19
20
|
id: number;
|
|
20
21
|
uuid: string;
|
|
22
|
+
fileId: string | null;
|
|
21
23
|
bucket: string;
|
|
22
|
-
folderUuid: string;
|
|
23
24
|
folderId: number;
|
|
24
|
-
|
|
25
|
-
fileId: string;
|
|
25
|
+
folderUuid: string;
|
|
26
26
|
itemType: "file";
|
|
27
27
|
size: number;
|
|
28
28
|
createdAt: Date;
|
|
@@ -33,6 +33,5 @@ export default class UploadFile extends Command {
|
|
|
33
33
|
};
|
|
34
34
|
}>;
|
|
35
35
|
catch: (error: Error) => Promise<never>;
|
|
36
|
-
private getDestinationFolderUuid;
|
|
37
36
|
private getFilePath;
|
|
38
37
|
}
|
|
@@ -6,23 +6,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const core_1 = require("@oclif/core");
|
|
7
7
|
const promises_1 = require("node:fs/promises");
|
|
8
8
|
const node_fs_1 = require("node:fs");
|
|
9
|
-
const network_facade_service_1 = require("../services/network/network-facade.service");
|
|
10
|
-
const sdk_manager_service_1 = require("../services/sdk-manager.service");
|
|
11
9
|
const auth_service_1 = require("../services/auth.service");
|
|
12
10
|
const cli_utils_1 = require("../utils/cli.utils");
|
|
13
11
|
const config_service_1 = require("../services/config.service");
|
|
14
12
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
13
|
const drive_file_service_1 = require("../services/drive/drive-file.service");
|
|
16
|
-
const crypto_service_1 = require("../services/crypto.service");
|
|
17
|
-
const download_service_1 = require("../services/network/download.service");
|
|
18
|
-
const errors_utils_1 = require("../utils/errors.utils");
|
|
19
14
|
const command_types_1 = require("../types/command.types");
|
|
20
15
|
const validation_service_1 = require("../services/validation.service");
|
|
21
16
|
const types_1 = require("@internxt/sdk/dist/drive/storage/types");
|
|
22
|
-
const thumbnail_service_1 = require("../services/thumbnail.service");
|
|
23
17
|
const stream_utils_1 = require("../utils/stream.utils");
|
|
24
18
|
const thumbnail_utils_1 = require("../utils/thumbnail.utils");
|
|
25
|
-
const inxt_js_1 = require("@internxt/inxt-js");
|
|
26
19
|
class UploadFile extends core_1.Command {
|
|
27
20
|
static args = {};
|
|
28
21
|
static description = 'Upload a file to Internxt Drive';
|
|
@@ -49,62 +42,59 @@ class UploadFile extends core_1.Command {
|
|
|
49
42
|
const { user } = await auth_service_1.AuthService.instance.getAuthDetails();
|
|
50
43
|
const filePath = await this.getFilePath(flags['file'], nonInteractive);
|
|
51
44
|
const stats = await (0, promises_1.stat)(filePath);
|
|
52
|
-
if (!stats.size) {
|
|
53
|
-
throw new Error('The file is empty. Uploading empty files is not allowed.');
|
|
54
|
-
}
|
|
55
45
|
const fileInfo = node_path_1.default.parse(filePath);
|
|
56
46
|
const fileType = fileInfo.ext.replaceAll('.', '');
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
encryptionKey: user.mnemonic,
|
|
71
|
-
appDetails: sdk_manager_service_1.SdkManager.getAppDetails(),
|
|
72
|
-
});
|
|
73
|
-
const networkFacade = new network_facade_service_1.NetworkFacade(networkModule, environment, download_service_1.DownloadService.instance, crypto_service_1.CryptoService.instance);
|
|
74
|
-
cli_utils_1.CLIUtils.done(flags['json']);
|
|
75
|
-
const readStream = (0, node_fs_1.createReadStream)(filePath);
|
|
76
|
-
const timer = cli_utils_1.CLIUtils.timer();
|
|
47
|
+
const destinationFolderUuid = (await cli_utils_1.CLIUtils.getDestinationFolderUuid({
|
|
48
|
+
destinationFolderUuidFlag: flags['destination'],
|
|
49
|
+
destinationFlagName: UploadFile.flags['destination'].name,
|
|
50
|
+
nonInteractive,
|
|
51
|
+
reporter: this.log.bind(this),
|
|
52
|
+
})) ?? user.rootFolderId;
|
|
53
|
+
const timings = {
|
|
54
|
+
networkUpload: 0,
|
|
55
|
+
driveUpload: 0,
|
|
56
|
+
thumbnailUpload: 0,
|
|
57
|
+
};
|
|
58
|
+
const networkFacade = cli_utils_1.CLIUtils.prepareNetwork({ loginUserDetails: user, jsonFlag: flags['json'] });
|
|
59
|
+
const networkUploadTimer = cli_utils_1.CLIUtils.timer();
|
|
77
60
|
const progressBar = cli_utils_1.CLIUtils.progress({
|
|
78
61
|
format: 'Uploading file [{bar}] {percentage}%',
|
|
79
62
|
linewrap: true,
|
|
80
63
|
}, flags['json']);
|
|
81
64
|
progressBar?.start(100, 0);
|
|
65
|
+
let fileId;
|
|
82
66
|
let bufferStream;
|
|
83
|
-
let fileStream = readStream;
|
|
84
67
|
const isThumbnailable = (0, thumbnail_utils_1.isFileThumbnailable)(fileType);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
68
|
+
const fileSize = stats.size ?? 0;
|
|
69
|
+
if (fileSize > 0) {
|
|
70
|
+
const readStream = (0, node_fs_1.createReadStream)(filePath);
|
|
71
|
+
let fileStream = readStream;
|
|
72
|
+
if (isThumbnailable) {
|
|
73
|
+
bufferStream = new stream_utils_1.BufferStream();
|
|
74
|
+
fileStream = readStream.pipe(bufferStream);
|
|
75
|
+
}
|
|
76
|
+
const progressCallback = (progress) => {
|
|
77
|
+
progressBar?.update(progress * 100 * 0.99);
|
|
78
|
+
};
|
|
79
|
+
fileId = await new Promise((resolve, reject) => {
|
|
80
|
+
const state = networkFacade.uploadFile(fileStream, fileSize, user.bucket, (err, res) => {
|
|
81
|
+
if (err) {
|
|
82
|
+
return reject(err);
|
|
83
|
+
}
|
|
84
|
+
resolve(res);
|
|
85
|
+
}, progressCallback);
|
|
86
|
+
process.on('SIGINT', () => {
|
|
87
|
+
state.stop();
|
|
88
|
+
process.exit(1);
|
|
89
|
+
});
|
|
102
90
|
});
|
|
103
|
-
}
|
|
91
|
+
}
|
|
92
|
+
timings.networkUpload = networkUploadTimer.stop();
|
|
93
|
+
const driveUploadTimer = cli_utils_1.CLIUtils.timer();
|
|
104
94
|
const createdDriveFile = await drive_file_service_1.DriveFileService.instance.createFile({
|
|
105
95
|
plainName: fileInfo.name,
|
|
106
96
|
type: fileType,
|
|
107
|
-
size:
|
|
97
|
+
size: fileSize,
|
|
108
98
|
folderUuid: destinationFolderUuid,
|
|
109
99
|
fileId: fileId,
|
|
110
100
|
bucket: user.bucket,
|
|
@@ -112,29 +102,37 @@ class UploadFile extends core_1.Command {
|
|
|
112
102
|
creationTime: stats.birthtime?.toISOString(),
|
|
113
103
|
modificationTime: stats.mtime?.toISOString(),
|
|
114
104
|
});
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
105
|
+
timings.driveUpload = driveUploadTimer.stop();
|
|
106
|
+
const thumbnailTimer = cli_utils_1.CLIUtils.timer();
|
|
107
|
+
if (fileSize > 0 && isThumbnailable && bufferStream) {
|
|
108
|
+
void (0, thumbnail_utils_1.tryUploadThumbnail)({
|
|
109
|
+
bufferStream,
|
|
110
|
+
fileType,
|
|
111
|
+
userBucket: user.bucket,
|
|
112
|
+
fileUuid: createdDriveFile.uuid,
|
|
113
|
+
networkFacade,
|
|
114
|
+
});
|
|
125
115
|
}
|
|
116
|
+
timings.thumbnailUpload = thumbnailTimer.stop();
|
|
126
117
|
progressBar?.update(100);
|
|
127
118
|
progressBar?.stop();
|
|
128
|
-
const
|
|
119
|
+
const totalTime = Object.values(timings).reduce((sum, time) => sum + time, 0);
|
|
120
|
+
const throughputMBps = cli_utils_1.CLIUtils.calculateThroughputMBps(stats.size, timings.networkUpload);
|
|
121
|
+
this.log('\n');
|
|
122
|
+
this.log(`[PUT] Timing breakdown:\n
|
|
123
|
+
Network upload: ${cli_utils_1.CLIUtils.formatDuration(timings.networkUpload)} (${throughputMBps.toFixed(2)} MB/s)\n
|
|
124
|
+
Drive upload: ${cli_utils_1.CLIUtils.formatDuration(timings.driveUpload)}\n
|
|
125
|
+
Thumbnail: ${cli_utils_1.CLIUtils.formatDuration(timings.thumbnailUpload)}\n`);
|
|
129
126
|
this.log('\n');
|
|
130
|
-
const message = `File uploaded in ${
|
|
127
|
+
const message = `File uploaded successfully in ${cli_utils_1.CLIUtils.formatDuration(totalTime)}, view it at ` +
|
|
128
|
+
`${config_service_1.ConfigService.instance.get('DRIVE_WEB_URL')}/file/${createdDriveFile.uuid}`;
|
|
131
129
|
cli_utils_1.CLIUtils.success(this.log.bind(this), message);
|
|
132
130
|
return {
|
|
133
131
|
success: true,
|
|
134
132
|
message,
|
|
135
133
|
file: {
|
|
136
134
|
...createdDriveFile,
|
|
137
|
-
plainName:
|
|
135
|
+
plainName: createdDriveFile.name,
|
|
138
136
|
},
|
|
139
137
|
};
|
|
140
138
|
};
|
|
@@ -148,23 +146,6 @@ class UploadFile extends core_1.Command {
|
|
|
148
146
|
});
|
|
149
147
|
this.exit(1);
|
|
150
148
|
};
|
|
151
|
-
getDestinationFolderUuid = async (destinationFolderUuidFlag, nonInteractive) => {
|
|
152
|
-
const destinationFolderUuid = await cli_utils_1.CLIUtils.getValueFromFlag({
|
|
153
|
-
value: destinationFolderUuidFlag,
|
|
154
|
-
name: UploadFile.flags['destination'].name,
|
|
155
|
-
}, {
|
|
156
|
-
nonInteractive,
|
|
157
|
-
prompt: {
|
|
158
|
-
message: 'What is the destination folder id? (leave empty for the root folder)',
|
|
159
|
-
options: { type: 'input' },
|
|
160
|
-
},
|
|
161
|
-
}, {
|
|
162
|
-
validate: validation_service_1.ValidationService.instance.validateUUIDv4,
|
|
163
|
-
error: new command_types_1.NotValidFolderUuidError(),
|
|
164
|
-
canBeEmpty: true,
|
|
165
|
-
}, this.log.bind(this));
|
|
166
|
-
return destinationFolderUuid;
|
|
167
|
-
};
|
|
168
149
|
getFilePath = async (fileFlag, nonInteractive) => {
|
|
169
150
|
const filePath = await cli_utils_1.CLIUtils.getValueFromFlag({
|
|
170
151
|
value: fileFlag,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class UploadFolder extends Command {
|
|
3
|
+
static readonly args: {};
|
|
4
|
+
static readonly description = "Upload a folder to Internxt Drive";
|
|
5
|
+
static readonly aliases: string[];
|
|
6
|
+
static readonly examples: string[];
|
|
7
|
+
static readonly flags: {
|
|
8
|
+
folder: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
destination: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
'non-interactive': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
};
|
|
12
|
+
static readonly enableJsonFlag = true;
|
|
13
|
+
run: () => Promise<void>;
|
|
14
|
+
catch: (error: Error) => Promise<never>;
|
|
15
|
+
private getFolderPath;
|
|
16
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const cli_utils_1 = require("../utils/cli.utils");
|
|
5
|
+
const auth_service_1 = require("../services/auth.service");
|
|
6
|
+
const validation_service_1 = require("../services/validation.service");
|
|
7
|
+
const config_service_1 = require("../services/config.service");
|
|
8
|
+
const upload_facade_service_1 = require("../services/network/upload/upload-facade.service");
|
|
9
|
+
const command_types_1 = require("../types/command.types");
|
|
10
|
+
class UploadFolder extends core_1.Command {
|
|
11
|
+
static args = {};
|
|
12
|
+
static description = 'Upload a folder to Internxt Drive';
|
|
13
|
+
static aliases = ['upload:folder'];
|
|
14
|
+
static examples = ['<%= config.bin %> <%= command.id %>'];
|
|
15
|
+
static flags = {
|
|
16
|
+
...cli_utils_1.CLIUtils.CommonFlags,
|
|
17
|
+
folder: core_1.Flags.string({
|
|
18
|
+
char: 'f',
|
|
19
|
+
description: 'The path to the folder on your system.',
|
|
20
|
+
required: false,
|
|
21
|
+
}),
|
|
22
|
+
destination: core_1.Flags.string({
|
|
23
|
+
char: 'i',
|
|
24
|
+
description: 'The folder id where the folder is going to be uploaded to. Leave empty for the root folder.',
|
|
25
|
+
required: false,
|
|
26
|
+
parse: cli_utils_1.CLIUtils.parseEmpty,
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
static enableJsonFlag = true;
|
|
30
|
+
run = async () => {
|
|
31
|
+
const { user } = await auth_service_1.AuthService.instance.getAuthDetails();
|
|
32
|
+
const { flags } = await this.parse(UploadFolder);
|
|
33
|
+
const localPath = await this.getFolderPath(flags['folder'], flags['non-interactive']);
|
|
34
|
+
const destinationFolderUuid = (await cli_utils_1.CLIUtils.getDestinationFolderUuid({
|
|
35
|
+
destinationFolderUuidFlag: flags['destination'],
|
|
36
|
+
destinationFlagName: UploadFolder.flags['destination'].name,
|
|
37
|
+
nonInteractive: flags['non-interactive'],
|
|
38
|
+
reporter: this.log.bind(this),
|
|
39
|
+
})) ?? user.rootFolderId;
|
|
40
|
+
const progressBar = cli_utils_1.CLIUtils.progress({
|
|
41
|
+
format: 'Uploading folder [{bar}] {percentage}%',
|
|
42
|
+
linewrap: true,
|
|
43
|
+
}, flags['json']);
|
|
44
|
+
progressBar?.start(100, 0);
|
|
45
|
+
const data = await upload_facade_service_1.UploadFacade.instance.uploadFolder({
|
|
46
|
+
localPath,
|
|
47
|
+
destinationFolderUuid,
|
|
48
|
+
loginUserDetails: user,
|
|
49
|
+
jsonFlag: flags['json'],
|
|
50
|
+
onProgress: (progress) => {
|
|
51
|
+
progressBar?.update(progress.percentage);
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
progressBar?.update(100);
|
|
55
|
+
progressBar?.stop();
|
|
56
|
+
const driveUrl = config_service_1.ConfigService.instance.get('DRIVE_WEB_URL');
|
|
57
|
+
const folderUrl = `${driveUrl}/folder/${data.rootFolderId}`;
|
|
58
|
+
const message = `Folder uploaded in ${data.uploadTimeMs}ms, view it at ${folderUrl} (${data.totalBytes} bytes)`;
|
|
59
|
+
cli_utils_1.CLIUtils.success(this.log.bind(this), message);
|
|
60
|
+
};
|
|
61
|
+
catch = async (error) => {
|
|
62
|
+
const { flags } = await this.parse(UploadFolder);
|
|
63
|
+
cli_utils_1.CLIUtils.catchError({
|
|
64
|
+
error,
|
|
65
|
+
command: this.id,
|
|
66
|
+
logReporter: this.log.bind(this),
|
|
67
|
+
jsonFlag: flags['json'],
|
|
68
|
+
});
|
|
69
|
+
this.exit(1);
|
|
70
|
+
};
|
|
71
|
+
getFolderPath = async (folderFlag, nonInteractive) => {
|
|
72
|
+
return await cli_utils_1.CLIUtils.getValueFromFlag({
|
|
73
|
+
value: folderFlag,
|
|
74
|
+
name: UploadFolder.flags['folder'].name,
|
|
75
|
+
}, {
|
|
76
|
+
nonInteractive,
|
|
77
|
+
prompt: {
|
|
78
|
+
message: 'What is the path to the folder on your computer?',
|
|
79
|
+
options: { type: 'input' },
|
|
80
|
+
},
|
|
81
|
+
}, {
|
|
82
|
+
validate: validation_service_1.ValidationService.instance.validateDirectoryExists,
|
|
83
|
+
error: new command_types_1.NotValidDirectoryError(),
|
|
84
|
+
}, this.log.bind(this));
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
exports.default = UploadFolder;
|
|
@@ -5,12 +5,12 @@ export default class WebDAVConfig extends Command {
|
|
|
5
5
|
static readonly aliases: never[];
|
|
6
6
|
static readonly examples: string[];
|
|
7
7
|
static readonly flags: {
|
|
8
|
-
host: import("@oclif/core/
|
|
9
|
-
port: import("@oclif/core/
|
|
10
|
-
https: import("@oclif/core/
|
|
11
|
-
http: import("@oclif/core/
|
|
12
|
-
timeout: import("@oclif/core/
|
|
13
|
-
createFullPath: import("@oclif/core/
|
|
8
|
+
host: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
port: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
https: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
http: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
timeout: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
createFullPath: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
14
|
};
|
|
15
15
|
static readonly enableJsonFlag = true;
|
|
16
16
|
run: () => Promise<{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
2
|
export default class Webdav extends Command {
|
|
3
3
|
static readonly args: {
|
|
4
|
-
action: import("@oclif/core/
|
|
4
|
+
action: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
5
|
};
|
|
6
6
|
static readonly description = "Enable, disable, restart or get the status of the Internxt CLI WebDav server";
|
|
7
7
|
static readonly aliases: never[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const INTERNXT_CLI_DATA_DIR: string;
|
|
2
|
+
export declare const INTERNXT_CLI_LOGS_DIR: string;
|
|
3
|
+
export declare const INTERNXT_TMP_DIR: string;
|
|
4
|
+
export declare const CREDENTIALS_FILE: string;
|
|
5
|
+
export declare const DRIVE_SQLITE_FILE: string;
|
|
6
|
+
export declare const WEBDAV_SSL_CERTS_DIR: string;
|
|
7
|
+
export declare const WEBDAV_CONFIGS_FILE: string;
|
|
8
|
+
export declare const WEBDAV_DEFAULT_HOST = "127.0.0.1";
|
|
9
|
+
export declare const WEBDAV_DEFAULT_PORT = "3005";
|
|
10
|
+
export declare const WEBDAV_DEFAULT_PROTOCOL = "https";
|
|
11
|
+
export declare const WEBDAV_DEFAULT_TIMEOUT = 0;
|
|
12
|
+
export declare const WEBDAV_DEFAULT_CREATE_FULL_PATH = true;
|
|
@@ -0,0 +1,20 @@
|
|
|
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.WEBDAV_DEFAULT_CREATE_FULL_PATH = exports.WEBDAV_DEFAULT_TIMEOUT = exports.WEBDAV_DEFAULT_PROTOCOL = exports.WEBDAV_DEFAULT_PORT = exports.WEBDAV_DEFAULT_HOST = exports.WEBDAV_CONFIGS_FILE = exports.WEBDAV_SSL_CERTS_DIR = exports.DRIVE_SQLITE_FILE = exports.CREDENTIALS_FILE = exports.INTERNXT_TMP_DIR = exports.INTERNXT_CLI_LOGS_DIR = exports.INTERNXT_CLI_DATA_DIR = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
9
|
+
exports.INTERNXT_CLI_DATA_DIR = node_path_1.default.join(node_os_1.default.homedir(), '.internxt-cli');
|
|
10
|
+
exports.INTERNXT_CLI_LOGS_DIR = node_path_1.default.join(exports.INTERNXT_CLI_DATA_DIR, 'logs');
|
|
11
|
+
exports.INTERNXT_TMP_DIR = node_os_1.default.tmpdir();
|
|
12
|
+
exports.CREDENTIALS_FILE = node_path_1.default.join(exports.INTERNXT_CLI_DATA_DIR, '.inxtcli');
|
|
13
|
+
exports.DRIVE_SQLITE_FILE = node_path_1.default.join(exports.INTERNXT_CLI_DATA_DIR, 'internxt-cli-drive.sqlite');
|
|
14
|
+
exports.WEBDAV_SSL_CERTS_DIR = node_path_1.default.join(exports.INTERNXT_CLI_DATA_DIR, 'certs');
|
|
15
|
+
exports.WEBDAV_CONFIGS_FILE = node_path_1.default.join(exports.INTERNXT_CLI_DATA_DIR, 'config.webdav.inxt');
|
|
16
|
+
exports.WEBDAV_DEFAULT_HOST = '127.0.0.1';
|
|
17
|
+
exports.WEBDAV_DEFAULT_PORT = '3005';
|
|
18
|
+
exports.WEBDAV_DEFAULT_PROTOCOL = 'https';
|
|
19
|
+
exports.WEBDAV_DEFAULT_TIMEOUT = 0;
|
|
20
|
+
exports.WEBDAV_DEFAULT_CREATE_FULL_PATH = true;
|
|
@@ -35,7 +35,7 @@ class AuthService {
|
|
|
35
35
|
return securityDetails.tfaEnabled;
|
|
36
36
|
};
|
|
37
37
|
getAuthDetails = async () => {
|
|
38
|
-
|
|
38
|
+
const loginCreds = await config_service_1.ConfigService.instance.readUser();
|
|
39
39
|
if (!loginCreds?.token || !loginCreds?.user?.mnemonic) {
|
|
40
40
|
throw new command_types_1.MissingCredentialsError();
|
|
41
41
|
}
|
|
@@ -47,11 +47,16 @@ class AuthService {
|
|
|
47
47
|
if (tokenDetails.expiration.expired) {
|
|
48
48
|
throw new command_types_1.ExpiredCredentialsError();
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
if (!tokenDetails.expiration.refreshRequired) {
|
|
51
|
+
return loginCreds;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
return await this.refreshUserToken(loginCreds.token, loginCreds.user.mnemonic);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
await config_service_1.ConfigService.instance.clearUser();
|
|
58
|
+
throw error;
|
|
53
59
|
}
|
|
54
|
-
return loginCreds;
|
|
55
60
|
};
|
|
56
61
|
refreshUserToken = async (oldToken, mnemonic) => {
|
|
57
62
|
sdk_manager_service_1.SdkManager.init({ token: oldToken });
|
|
@@ -75,7 +80,7 @@ class AuthService {
|
|
|
75
80
|
logout = async () => {
|
|
76
81
|
try {
|
|
77
82
|
const user = await config_service_1.ConfigService.instance.readUser();
|
|
78
|
-
if (!user
|
|
83
|
+
if (!user?.token) {
|
|
79
84
|
return;
|
|
80
85
|
}
|
|
81
86
|
const authClient = sdk_manager_service_1.SdkManager.instance.getAuth();
|
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
import { ConfigKeys } from '../types/config.types';
|
|
2
2
|
import { LoginCredentials, WebdavConfig } from '../types/command.types';
|
|
3
3
|
export declare class ConfigService {
|
|
4
|
-
static readonly INTERNXT_CLI_DATA_DIR: string;
|
|
5
|
-
static readonly INTERNXT_CLI_LOGS_DIR: string;
|
|
6
|
-
static readonly INTERNXT_TMP_DIR: string;
|
|
7
|
-
static readonly CREDENTIALS_FILE: string;
|
|
8
|
-
static readonly DRIVE_SQLITE_FILE: string;
|
|
9
|
-
static readonly WEBDAV_SSL_CERTS_DIR: string;
|
|
10
|
-
static readonly WEBDAV_CONFIGS_FILE: string;
|
|
11
|
-
static readonly WEBDAV_DEFAULT_HOST = "127.0.0.1";
|
|
12
|
-
static readonly WEBDAV_DEFAULT_PORT = "3005";
|
|
13
|
-
static readonly WEBDAV_DEFAULT_PROTOCOL = "https";
|
|
14
|
-
static readonly WEBDAV_DEFAULT_TIMEOUT = 0;
|
|
15
|
-
static readonly WEBDAV_DEFAULT_CREATE_FULL_PATH = true;
|
|
16
4
|
static readonly instance: ConfigService;
|
|
17
5
|
get: (key: keyof ConfigKeys) => string;
|
|
18
6
|
saveUser: (loginCredentials: LoginCredentials) => Promise<void>;
|