@internxt/cli 1.6.0 → 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 +89 -27
- 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/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 +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/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/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 +13 -2
- package/dist/utils/cli.utils.js +47 -0
- package/dist/utils/errors.utils.d.ts +1 -0
- package/dist/utils/errors.utils.js +5 -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/xml.utils.d.ts +1 -1
- package/dist/webdav/handlers/GET.handler.js +37 -24
- package/oclif.manifest.json +62 -1
- package/package.json +24 -24
|
@@ -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;
|
|
@@ -49,6 +49,9 @@ export declare class NotValidFolderUuidError extends Error {
|
|
|
49
49
|
export declare class NotValidFileUuidError extends Error {
|
|
50
50
|
constructor();
|
|
51
51
|
}
|
|
52
|
+
export declare class NotValidFileIdError extends Error {
|
|
53
|
+
constructor();
|
|
54
|
+
}
|
|
52
55
|
export declare class NoRootFolderIdFoundError extends Error {
|
|
53
56
|
constructor();
|
|
54
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');
|
|
@@ -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);
|
package/dist/utils/cli.utils.js
CHANGED
|
@@ -7,8 +7,16 @@ exports.NoFlagProvidedError = exports.CLIUtils = void 0;
|
|
|
7
7
|
const core_1 = require("@oclif/core");
|
|
8
8
|
const cli_progress_1 = __importDefault(require("cli-progress"));
|
|
9
9
|
const tty_table_1 = __importDefault(require("tty-table"));
|
|
10
|
+
const command_types_1 = require("../types/command.types");
|
|
10
11
|
const inquirer_utils_1 = require("./inquirer.utils");
|
|
11
12
|
const errors_utils_1 = require("./errors.utils");
|
|
13
|
+
const validation_service_1 = require("../services/validation.service");
|
|
14
|
+
const sdk_manager_service_1 = require("../services/sdk-manager.service");
|
|
15
|
+
const inxt_js_1 = require("@internxt/inxt-js");
|
|
16
|
+
const config_service_1 = require("../services/config.service");
|
|
17
|
+
const network_facade_service_1 = require("../services/network/network-facade.service");
|
|
18
|
+
const download_service_1 = require("../services/network/download.service");
|
|
19
|
+
const crypto_service_1 = require("../services/crypto.service");
|
|
12
20
|
class CLIUtils {
|
|
13
21
|
static clearPreviousLine = (jsonFlag) => {
|
|
14
22
|
if (!jsonFlag) {
|
|
@@ -94,6 +102,28 @@ class CLIUtils {
|
|
|
94
102
|
return await CLIUtils.promptWithAttempts(command.prompt, maxAttempts, validation, reporter);
|
|
95
103
|
}
|
|
96
104
|
};
|
|
105
|
+
static getDestinationFolderUuid = async ({ destinationFolderUuidFlag, destinationFlagName, nonInteractive, reporter, }) => {
|
|
106
|
+
const destinationFolderUuid = await this.getValueFromFlag({
|
|
107
|
+
value: destinationFolderUuidFlag,
|
|
108
|
+
name: destinationFlagName,
|
|
109
|
+
}, {
|
|
110
|
+
nonInteractive,
|
|
111
|
+
prompt: {
|
|
112
|
+
message: 'What is the destination folder id? (leave empty for the root folder)',
|
|
113
|
+
options: { type: 'input' },
|
|
114
|
+
},
|
|
115
|
+
}, {
|
|
116
|
+
validate: validation_service_1.ValidationService.instance.validateUUIDv4,
|
|
117
|
+
error: new command_types_1.NotValidFolderUuidError(),
|
|
118
|
+
canBeEmpty: true,
|
|
119
|
+
}, reporter);
|
|
120
|
+
if (destinationFolderUuid.trim().length === 0) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
return destinationFolderUuid;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
97
127
|
static promptWithAttempts = async (prompt, maxAttempts, validation, reporter) => {
|
|
98
128
|
let isValid = false;
|
|
99
129
|
let currentAttempts = 0;
|
|
@@ -148,6 +178,23 @@ class CLIUtils {
|
|
|
148
178
|
}
|
|
149
179
|
};
|
|
150
180
|
static parseEmpty = async (input) => (input.trim().length === 0 ? ' ' : input);
|
|
181
|
+
static prepareNetwork = ({ jsonFlag, loginUserDetails, }) => {
|
|
182
|
+
CLIUtils.doing('Preparing Network', jsonFlag);
|
|
183
|
+
const networkModule = sdk_manager_service_1.SdkManager.instance.getNetwork({
|
|
184
|
+
user: loginUserDetails.bridgeUser,
|
|
185
|
+
pass: loginUserDetails.userId,
|
|
186
|
+
});
|
|
187
|
+
const environment = new inxt_js_1.Environment({
|
|
188
|
+
bridgeUser: loginUserDetails.bridgeUser,
|
|
189
|
+
bridgePass: loginUserDetails.userId,
|
|
190
|
+
bridgeUrl: config_service_1.ConfigService.instance.get('NETWORK_URL'),
|
|
191
|
+
encryptionKey: loginUserDetails.mnemonic,
|
|
192
|
+
appDetails: sdk_manager_service_1.SdkManager.getAppDetails(),
|
|
193
|
+
});
|
|
194
|
+
const networkFacade = new network_facade_service_1.NetworkFacade(networkModule, environment, download_service_1.DownloadService.instance, crypto_service_1.CryptoService.instance);
|
|
195
|
+
CLIUtils.done(jsonFlag);
|
|
196
|
+
return networkFacade;
|
|
197
|
+
};
|
|
151
198
|
}
|
|
152
199
|
exports.CLIUtils = CLIUtils;
|
|
153
200
|
class NoFlagProvidedError extends Error {
|
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.NotImplementedError = exports.MethodNotAllowed = exports.UnsupportedMediaTypeError = exports.BadRequestError = exports.NotFoundError = exports.ConflictError = exports.ErrorUtils = void 0;
|
|
4
4
|
exports.isError = isError;
|
|
5
|
+
exports.isAlreadyExistsError = isAlreadyExistsError;
|
|
5
6
|
const logger_utils_1 = require("./logger.utils");
|
|
6
7
|
const node_util_1 = require("node:util");
|
|
7
8
|
function isError(error) {
|
|
8
9
|
return node_util_1.types.isNativeError(error);
|
|
9
10
|
}
|
|
11
|
+
function isAlreadyExistsError(error) {
|
|
12
|
+
return ((isError(error) && error.message.includes('already exists')) ||
|
|
13
|
+
(typeof error === 'object' && error !== null && 'status' in error && error.status === 409));
|
|
14
|
+
}
|
|
10
15
|
class ErrorUtils {
|
|
11
16
|
static report(error, props = {}) {
|
|
12
17
|
if (isError(error)) {
|
|
@@ -11,10 +11,10 @@ export declare class NetworkUtils {
|
|
|
11
11
|
cert: string;
|
|
12
12
|
privateKey: string;
|
|
13
13
|
};
|
|
14
|
-
static generateNewSelfsignedCerts(configs: WebdavConfig): SelfsignedCert
|
|
14
|
+
static generateNewSelfsignedCerts(configs: WebdavConfig): Promise<SelfsignedCert>;
|
|
15
15
|
static getWebdavSSLCerts(configs: WebdavConfig): Promise<SelfsignedCert>;
|
|
16
16
|
static saveWebdavSSLCerts(pems: selfsigned.GenerateResult): Promise<void>;
|
|
17
|
-
static generateSelfSignedSSLCerts(configs: WebdavConfig): selfsigned.GenerateResult
|
|
17
|
+
static generateSelfSignedSSLCerts(configs: WebdavConfig): Promise<selfsigned.GenerateResult>;
|
|
18
18
|
static parseRangeHeader(rangeOptions: {
|
|
19
19
|
range?: string;
|
|
20
20
|
totalFileSize: number;
|
|
@@ -21,8 +21,8 @@ class NetworkUtils {
|
|
|
21
21
|
cert: node_path_1.default.join(config_service_1.ConfigService.WEBDAV_SSL_CERTS_DIR, 'cert.crt'),
|
|
22
22
|
privateKey: node_path_1.default.join(config_service_1.ConfigService.WEBDAV_SSL_CERTS_DIR, 'priv.key'),
|
|
23
23
|
};
|
|
24
|
-
static generateNewSelfsignedCerts(configs) {
|
|
25
|
-
const newCerts = this.generateSelfSignedSSLCerts(configs);
|
|
24
|
+
static async generateNewSelfsignedCerts(configs) {
|
|
25
|
+
const newCerts = await this.generateSelfSignedSSLCerts(configs);
|
|
26
26
|
this.saveWebdavSSLCerts(newCerts);
|
|
27
27
|
return {
|
|
28
28
|
cert: newCerts.cert,
|
|
@@ -44,7 +44,7 @@ class NetworkUtils {
|
|
|
44
44
|
const dateToday = new Date();
|
|
45
45
|
const dateValid = new Date(validTo);
|
|
46
46
|
if (dateToday > dateValid) {
|
|
47
|
-
const newCerts = this.generateNewSelfsignedCerts(configs);
|
|
47
|
+
const newCerts = await this.generateNewSelfsignedCerts(configs);
|
|
48
48
|
selfsignedCert = {
|
|
49
49
|
cert: newCerts.cert,
|
|
50
50
|
key: newCerts.key,
|
|
@@ -57,7 +57,7 @@ class NetworkUtils {
|
|
|
57
57
|
await (0, promises_1.writeFile)(this.WEBDAV_SSL_CERTS_PATH.cert, pems.cert, 'utf8');
|
|
58
58
|
await (0, promises_1.writeFile)(this.WEBDAV_SSL_CERTS_PATH.privateKey, pems.private, 'utf8');
|
|
59
59
|
}
|
|
60
|
-
static generateSelfSignedSSLCerts(configs) {
|
|
60
|
+
static async generateSelfSignedSSLCerts(configs) {
|
|
61
61
|
const attrs = [{ name: 'commonName', value: configs.host }];
|
|
62
62
|
const extensions = [
|
|
63
63
|
{
|
|
@@ -70,7 +70,9 @@ class NetworkUtils {
|
|
|
70
70
|
],
|
|
71
71
|
},
|
|
72
72
|
];
|
|
73
|
-
const
|
|
73
|
+
const notAfterDate = new Date();
|
|
74
|
+
notAfterDate.setDate(notAfterDate.getDate() + 365);
|
|
75
|
+
const pems = await selfsigned_1.default.generate(attrs, { notAfterDate, algorithm: 'sha256', keySize: 2048, extensions });
|
|
74
76
|
return pems;
|
|
75
77
|
}
|
|
76
78
|
static parseRangeHeader(rangeOptions) {
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { Readable } from 'node:stream';
|
|
2
|
+
import { NetworkFacade } from '../services/network/network-facade.service';
|
|
3
|
+
import { BufferStream } from './stream.utils';
|
|
1
4
|
export declare const ThumbnailConfig: {
|
|
2
5
|
readonly MaxWidth: 300;
|
|
3
6
|
readonly MaxHeight: 300;
|
|
@@ -7,3 +10,17 @@ export declare const ThumbnailConfig: {
|
|
|
7
10
|
export declare const isFileThumbnailable: (fileType: string) => boolean;
|
|
8
11
|
export declare const isPDFThumbnailable: (fileType: string) => boolean;
|
|
9
12
|
export declare const isImageThumbnailable: (fileType: string) => boolean;
|
|
13
|
+
export declare const tryUploadThumbnail: ({ bufferStream, fileType, userBucket, fileUuid, networkFacade, }: {
|
|
14
|
+
bufferStream: BufferStream;
|
|
15
|
+
fileType: string;
|
|
16
|
+
userBucket: string;
|
|
17
|
+
fileUuid: string;
|
|
18
|
+
networkFacade: NetworkFacade;
|
|
19
|
+
}) => Promise<void>;
|
|
20
|
+
export declare const createFileStreamWithBuffer: ({ path, fileType, }: {
|
|
21
|
+
path: string;
|
|
22
|
+
fileType: string;
|
|
23
|
+
}) => {
|
|
24
|
+
bufferStream?: BufferStream;
|
|
25
|
+
fileStream: Readable;
|
|
26
|
+
};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isImageThumbnailable = exports.isPDFThumbnailable = exports.isFileThumbnailable = exports.ThumbnailConfig = void 0;
|
|
3
|
+
exports.createFileStreamWithBuffer = exports.tryUploadThumbnail = exports.isImageThumbnailable = exports.isPDFThumbnailable = exports.isFileThumbnailable = exports.ThumbnailConfig = void 0;
|
|
4
|
+
const thumbnail_service_1 = require("../services/thumbnail.service");
|
|
5
|
+
const errors_utils_1 = require("./errors.utils");
|
|
6
|
+
const stream_utils_1 = require("./stream.utils");
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
4
8
|
exports.ThumbnailConfig = {
|
|
5
9
|
MaxWidth: 300,
|
|
6
10
|
MaxHeight: 300,
|
|
@@ -42,3 +46,27 @@ const isImageThumbnailable = (fileType) => {
|
|
|
42
46
|
return fileType.trim().length > 0 && thumbnailableImageExtension.includes(fileType.trim().toLowerCase());
|
|
43
47
|
};
|
|
44
48
|
exports.isImageThumbnailable = isImageThumbnailable;
|
|
49
|
+
const tryUploadThumbnail = async ({ bufferStream, fileType, userBucket, fileUuid, networkFacade, }) => {
|
|
50
|
+
try {
|
|
51
|
+
const thumbnailBuffer = bufferStream.getBuffer();
|
|
52
|
+
if (thumbnailBuffer) {
|
|
53
|
+
await thumbnail_service_1.ThumbnailService.instance.uploadThumbnail(thumbnailBuffer, fileType, userBucket, fileUuid, networkFacade);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
errors_utils_1.ErrorUtils.report(error);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.tryUploadThumbnail = tryUploadThumbnail;
|
|
61
|
+
const createFileStreamWithBuffer = ({ path, fileType, }) => {
|
|
62
|
+
const readable = (0, node_fs_1.createReadStream)(path);
|
|
63
|
+
if ((0, exports.isFileThumbnailable)(fileType)) {
|
|
64
|
+
const bufferStream = new stream_utils_1.BufferStream();
|
|
65
|
+
return {
|
|
66
|
+
bufferStream,
|
|
67
|
+
fileStream: readable.pipe(bufferStream),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return { fileStream: readable };
|
|
71
|
+
};
|
|
72
|
+
exports.createFileStreamWithBuffer = createFileStreamWithBuffer;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { X2jOptions, XmlBuilderOptions } from 'fast-xml-parser';
|
|
1
|
+
import { X2jOptions, XmlBuilderOptions } from '../types/fast-xml-parser.types';
|
|
2
2
|
export declare class XMLUtils {
|
|
3
3
|
static readonly DEFAULT_NAMESPACE_LETTER = "D";
|
|
4
4
|
static toJSON(xml: string, options?: X2jOptions): any;
|
|
@@ -5,6 +5,7 @@ const webdav_utils_1 = require("../../utils/webdav.utils");
|
|
|
5
5
|
const errors_utils_1 = require("../../utils/errors.utils");
|
|
6
6
|
const logger_utils_1 = require("../../utils/logger.utils");
|
|
7
7
|
const network_utils_1 = require("../../utils/network.utils");
|
|
8
|
+
const command_types_1 = require("../../types/command.types");
|
|
8
9
|
class GETRequestHandler {
|
|
9
10
|
dependencies;
|
|
10
11
|
constructor(dependencies) {
|
|
@@ -26,31 +27,43 @@ class GETRequestHandler {
|
|
|
26
27
|
logger_utils_1.webdavLogger.info(`[GET] [${driveFile.uuid}] Found Drive File`);
|
|
27
28
|
const { user } = await authService.getAuthDetails();
|
|
28
29
|
logger_utils_1.webdavLogger.info(`[GET] [${driveFile.uuid}] Network ready for download`);
|
|
29
|
-
const range = req.headers['range'];
|
|
30
|
-
const rangeOptions = network_utils_1.NetworkUtils.parseRangeHeader({
|
|
31
|
-
range,
|
|
32
|
-
totalFileSize: driveFile.size,
|
|
33
|
-
});
|
|
34
|
-
let contentLength = driveFile.size;
|
|
35
|
-
if (rangeOptions) {
|
|
36
|
-
logger_utils_1.webdavLogger.info(`[GET] [${driveFile.uuid}] Range request received:`, { rangeOptions });
|
|
37
|
-
contentLength = rangeOptions.rangeSize;
|
|
38
|
-
}
|
|
39
30
|
res.header('Content-Type', 'application/octet-stream');
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
31
|
+
const fileSize = driveFile.size ?? 0;
|
|
32
|
+
if (fileSize > 0) {
|
|
33
|
+
const range = req.headers['range'];
|
|
34
|
+
const rangeOptions = network_utils_1.NetworkUtils.parseRangeHeader({
|
|
35
|
+
range,
|
|
36
|
+
totalFileSize: fileSize,
|
|
37
|
+
});
|
|
38
|
+
let contentLength = fileSize;
|
|
39
|
+
if (rangeOptions) {
|
|
40
|
+
logger_utils_1.webdavLogger.info(`[GET] [${driveFile.uuid}] Range request received:`, { rangeOptions });
|
|
41
|
+
contentLength = rangeOptions.rangeSize;
|
|
42
|
+
}
|
|
43
|
+
res.header('Content-length', contentLength.toString());
|
|
44
|
+
const writable = new WritableStream({
|
|
45
|
+
write(chunk) {
|
|
46
|
+
res.write(chunk);
|
|
47
|
+
},
|
|
48
|
+
close() {
|
|
49
|
+
res.end();
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
if (!driveFile.fileId) {
|
|
53
|
+
throw new command_types_1.NotValidFileIdError();
|
|
54
|
+
}
|
|
55
|
+
const [executeDownload] = await networkFacade.downloadToStream(driveFile.bucket, user.mnemonic, driveFile.fileId, contentLength, writable, rangeOptions);
|
|
56
|
+
logger_utils_1.webdavLogger.info(`[GET] [${driveFile.uuid}] Download prepared, executing...`);
|
|
57
|
+
res.status(200);
|
|
58
|
+
await executeDownload;
|
|
59
|
+
logger_utils_1.webdavLogger.info(`[GET] [${driveFile.uuid}] ✅ Download ready, replying to client`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
logger_utils_1.webdavLogger.info(`[GET] [${driveFile.uuid}] File is empty, replying to client with no content`);
|
|
63
|
+
res.header('Content-length', '0');
|
|
64
|
+
res.status(200);
|
|
65
|
+
res.end();
|
|
66
|
+
}
|
|
54
67
|
};
|
|
55
68
|
}
|
|
56
69
|
exports.GETRequestHandler = GETRequestHandler;
|
package/oclif.manifest.json
CHANGED
|
@@ -1190,6 +1190,67 @@
|
|
|
1190
1190
|
"upload-file.js"
|
|
1191
1191
|
]
|
|
1192
1192
|
},
|
|
1193
|
+
"upload-folder": {
|
|
1194
|
+
"aliases": [
|
|
1195
|
+
"upload:folder"
|
|
1196
|
+
],
|
|
1197
|
+
"args": {},
|
|
1198
|
+
"description": "Upload a folder to Internxt Drive",
|
|
1199
|
+
"examples": [
|
|
1200
|
+
"<%= config.bin %> <%= command.id %>"
|
|
1201
|
+
],
|
|
1202
|
+
"flags": {
|
|
1203
|
+
"json": {
|
|
1204
|
+
"description": "Format output as json.",
|
|
1205
|
+
"helpGroup": "GLOBAL",
|
|
1206
|
+
"name": "json",
|
|
1207
|
+
"allowNo": false,
|
|
1208
|
+
"type": "boolean"
|
|
1209
|
+
},
|
|
1210
|
+
"non-interactive": {
|
|
1211
|
+
"char": "x",
|
|
1212
|
+
"description": "Prevents the CLI from being interactive. When enabled, the CLI will not request input through the console and will throw errors directly.",
|
|
1213
|
+
"env": "INXT_NONINTERACTIVE",
|
|
1214
|
+
"helpGroup": "helper",
|
|
1215
|
+
"name": "non-interactive",
|
|
1216
|
+
"required": false,
|
|
1217
|
+
"allowNo": false,
|
|
1218
|
+
"type": "boolean"
|
|
1219
|
+
},
|
|
1220
|
+
"folder": {
|
|
1221
|
+
"char": "f",
|
|
1222
|
+
"description": "The path to the folder on your system.",
|
|
1223
|
+
"name": "folder",
|
|
1224
|
+
"required": false,
|
|
1225
|
+
"hasDynamicHelp": false,
|
|
1226
|
+
"multiple": false,
|
|
1227
|
+
"type": "option"
|
|
1228
|
+
},
|
|
1229
|
+
"destination": {
|
|
1230
|
+
"char": "i",
|
|
1231
|
+
"description": "The folder id where the folder is going to be uploaded to. Leave empty for the root folder.",
|
|
1232
|
+
"name": "destination",
|
|
1233
|
+
"required": false,
|
|
1234
|
+
"hasDynamicHelp": false,
|
|
1235
|
+
"multiple": false,
|
|
1236
|
+
"type": "option"
|
|
1237
|
+
}
|
|
1238
|
+
},
|
|
1239
|
+
"hasDynamicHelp": false,
|
|
1240
|
+
"hiddenAliases": [],
|
|
1241
|
+
"id": "upload-folder",
|
|
1242
|
+
"pluginAlias": "@internxt/cli",
|
|
1243
|
+
"pluginName": "@internxt/cli",
|
|
1244
|
+
"pluginType": "core",
|
|
1245
|
+
"strict": true,
|
|
1246
|
+
"enableJsonFlag": true,
|
|
1247
|
+
"isESM": false,
|
|
1248
|
+
"relativePath": [
|
|
1249
|
+
"dist",
|
|
1250
|
+
"commands",
|
|
1251
|
+
"upload-folder.js"
|
|
1252
|
+
]
|
|
1253
|
+
},
|
|
1193
1254
|
"webdav-config": {
|
|
1194
1255
|
"aliases": [],
|
|
1195
1256
|
"args": {},
|
|
@@ -1355,5 +1416,5 @@
|
|
|
1355
1416
|
]
|
|
1356
1417
|
}
|
|
1357
1418
|
},
|
|
1358
|
-
"version": "1.6.
|
|
1419
|
+
"version": "1.6.1"
|
|
1359
1420
|
}
|