@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.
Files changed (72) hide show
  1. package/README.md +89 -27
  2. package/dist/commands/add-cert.js +2 -2
  3. package/dist/commands/create-folder.d.ts +3 -3
  4. package/dist/commands/delete-permanently-file.d.ts +2 -2
  5. package/dist/commands/delete-permanently-folder.d.ts +2 -2
  6. package/dist/commands/download-file.d.ts +4 -5
  7. package/dist/commands/download-file.js +22 -37
  8. package/dist/commands/list.d.ts +4 -4
  9. package/dist/commands/login-legacy.d.ts +5 -5
  10. package/dist/commands/login.d.ts +2 -2
  11. package/dist/commands/logs.js +3 -3
  12. package/dist/commands/move-file.d.ts +4 -4
  13. package/dist/commands/move-folder.d.ts +3 -3
  14. package/dist/commands/rename-file.d.ts +3 -3
  15. package/dist/commands/rename-folder.d.ts +3 -3
  16. package/dist/commands/trash-clear.d.ts +2 -2
  17. package/dist/commands/trash-file.d.ts +2 -2
  18. package/dist/commands/trash-folder.d.ts +2 -2
  19. package/dist/commands/trash-list.d.ts +2 -2
  20. package/dist/commands/trash-restore-file.d.ts +4 -4
  21. package/dist/commands/trash-restore-folder.d.ts +3 -3
  22. package/dist/commands/upload-file.d.ts +6 -7
  23. package/dist/commands/upload-file.js +61 -80
  24. package/dist/commands/upload-folder.d.ts +16 -0
  25. package/dist/commands/upload-folder.js +87 -0
  26. package/dist/commands/webdav-config.d.ts +6 -6
  27. package/dist/commands/webdav.d.ts +1 -1
  28. package/dist/constants/configs.d.ts +12 -0
  29. package/dist/constants/configs.js +20 -0
  30. package/dist/services/auth.service.js +11 -6
  31. package/dist/services/config.service.d.ts +0 -12
  32. package/dist/services/config.service.js +33 -38
  33. package/dist/services/drive/drive-folder.service.d.ts +1 -1
  34. package/dist/services/drive/trash.service.d.ts +1 -1
  35. package/dist/services/local-filesystem/local-filesystem.service.d.ts +6 -0
  36. package/dist/services/local-filesystem/local-filesystem.service.js +57 -0
  37. package/dist/services/local-filesystem/local-filesystem.types.d.ts +13 -0
  38. package/dist/services/local-filesystem/local-filesystem.types.js +2 -0
  39. package/dist/services/network/upload/upload-facade.service.d.ts +9 -0
  40. package/dist/services/network/upload/upload-facade.service.js +53 -0
  41. package/dist/services/network/upload/upload-file.service.d.ts +8 -0
  42. package/dist/services/network/upload/upload-file.service.js +134 -0
  43. package/dist/services/network/upload/upload-folder.service.d.ts +6 -0
  44. package/dist/services/network/upload/upload-folder.service.js +62 -0
  45. package/dist/services/network/upload/upload.types.d.ts +53 -0
  46. package/dist/services/network/upload/upload.types.js +6 -0
  47. package/dist/services/sdk-manager.service.d.ts +2 -2
  48. package/dist/services/sdk-manager.service.js +2 -2
  49. package/dist/services/thumbnail.service.js +1 -34
  50. package/dist/services/validation.service.d.ts +5 -0
  51. package/dist/services/validation.service.js +22 -18
  52. package/dist/types/command.types.d.ts +3 -0
  53. package/dist/types/command.types.js +8 -1
  54. package/dist/types/fast-xml-parser.types.d.ts +59 -0
  55. package/dist/types/fast-xml-parser.types.js +2 -0
  56. package/dist/utils/cli.utils.d.ts +16 -2
  57. package/dist/utils/cli.utils.js +84 -3
  58. package/dist/utils/errors.utils.d.ts +2 -0
  59. package/dist/utils/errors.utils.js +13 -2
  60. package/dist/utils/logger.utils.js +5 -5
  61. package/dist/utils/network.utils.d.ts +2 -2
  62. package/dist/utils/network.utils.js +24 -23
  63. package/dist/utils/thumbnail.utils.d.ts +17 -0
  64. package/dist/utils/thumbnail.utils.js +36 -8
  65. package/dist/utils/xml.utils.d.ts +2 -2
  66. package/dist/utils/xml.utils.js +1 -1
  67. package/dist/webdav/handlers/GET.handler.js +37 -26
  68. package/dist/webdav/handlers/PUT.handler.js +56 -41
  69. package/dist/webdav/middewares/errors.middleware.js +1 -1
  70. package/dist/webdav/webdav-server.js +4 -4
  71. package/oclif.manifest.json +62 -1
  72. package/package.json +24 -24
@@ -38,29 +38,33 @@ class ValidationService {
38
38
  const fileStat = await promises_1.default.stat(path);
39
39
  return fileStat.isFile();
40
40
  };
41
- validateTokenAndCheckExpiration = (token) => {
42
- if (!token || typeof token !== 'string') {
43
- return { isValid: false, expiration: { expired: true, refreshRequired: false } };
44
- }
45
- const parts = token.split('.');
46
- if (parts.length !== 3) {
47
- return { isValid: false, expiration: { expired: true, refreshRequired: false } };
41
+ validateJwtAndCheckExpiration = (token) => {
42
+ if (!token || typeof token !== 'string' || token.split('.').length !== 3) {
43
+ return null;
48
44
  }
49
45
  try {
50
- const payload = JSON.parse(atob(parts[1]));
51
- if (typeof payload.exp !== 'number') {
52
- return { isValid: false, expiration: { expired: true, refreshRequired: false } };
53
- }
54
- const currentTime = Math.floor(Date.now() / 1000);
55
- const twoDaysInSeconds = 2 * 24 * 60 * 60;
56
- const remainingSeconds = payload.exp - currentTime;
57
- const expired = remainingSeconds <= 0;
58
- const refreshRequired = remainingSeconds > 0 && remainingSeconds <= twoDaysInSeconds;
59
- return { isValid: true, expiration: { expired, refreshRequired } };
46
+ const payload = JSON.parse(atob(token.split('.')[1]));
47
+ return typeof payload.exp === 'number' ? payload.exp : null;
60
48
  }
61
49
  catch {
62
- return { isValid: false, expiration: { expired: true, refreshRequired: false } };
50
+ return null;
63
51
  }
64
52
  };
53
+ checkTokenExpiration = (expirationTimestamp) => {
54
+ const TWO_DAYS_IN_SECONDS = 2 * 24 * 60 * 60;
55
+ const currentTime = Math.floor(Date.now() / 1000);
56
+ const remainingSeconds = expirationTimestamp - currentTime;
57
+ return {
58
+ expired: remainingSeconds <= 0,
59
+ refreshRequired: remainingSeconds > 0 && remainingSeconds <= TWO_DAYS_IN_SECONDS,
60
+ };
61
+ };
62
+ validateTokenAndCheckExpiration = (token) => {
63
+ const expiration = this.validateJwtAndCheckExpiration(token);
64
+ return {
65
+ isValid: expiration !== null,
66
+ expiration: expiration ? this.checkTokenExpiration(expiration) : { expired: true, refreshRequired: false },
67
+ };
68
+ };
65
69
  }
66
70
  exports.ValidationService = ValidationService;
@@ -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 {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -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/lib/interfaces").BooleanFlag<boolean>;
19
+ 'non-interactive': import("@oclif/core/interfaces").BooleanFlag<boolean>;
19
20
  };
20
21
  static readonly getValueFromFlag: (flag: {
21
22
  value?: string;
@@ -32,10 +33,19 @@ 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;
38
45
  };
46
+ static readonly formatDuration: (milliseconds: number) => string;
47
+ static readonly formatBytesToString: (bytes: number) => string;
48
+ static readonly calculateThroughputMBps: (bytes: number, milliseconds: number) => number;
39
49
  static readonly catchError: ({ error, logReporter, command, jsonFlag, }: {
40
50
  error: Error;
41
51
  command?: string;
@@ -43,6 +53,10 @@ export declare class CLIUtils {
43
53
  jsonFlag?: boolean;
44
54
  }) => void;
45
55
  static readonly parseEmpty: (input: string) => Promise<string>;
56
+ static readonly prepareNetwork: ({ jsonFlag, loginUserDetails, }: {
57
+ jsonFlag?: boolean;
58
+ loginUserDetails: LoginUserDetails;
59
+ }) => NetworkFacade;
46
60
  }
47
61
  export declare class NoFlagProvidedError extends Error {
48
62
  constructor(flag: string);
@@ -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;
@@ -113,11 +143,11 @@ class CLIUtils {
113
143
  }
114
144
  }
115
145
  } while (!isValid && currentAttempts < maxAttempts);
116
- if (!isValid) {
117
- throw validation.error;
146
+ if (isValid) {
147
+ return promptValue;
118
148
  }
119
149
  else {
120
- return promptValue;
150
+ throw validation.error;
121
151
  }
122
152
  };
123
153
  static timer = () => {
@@ -130,6 +160,40 @@ class CLIUtils {
130
160
  },
131
161
  };
132
162
  };
163
+ static formatDuration = (milliseconds) => {
164
+ if (milliseconds <= 0) {
165
+ return '00:00:00.000';
166
+ }
167
+ const totalSeconds = Math.floor(milliseconds / 1000);
168
+ const hours = Math.floor(totalSeconds / 3600);
169
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
170
+ const seconds = totalSeconds % 60;
171
+ const ms = Math.floor(milliseconds % 1000);
172
+ const hoursFormated = hours.toString().padStart(2, '0');
173
+ const minutesFormated = minutes.toString().padStart(2, '0');
174
+ const secondsFormated = seconds.toString().padStart(2, '0');
175
+ const msFormated = ms.toString().padStart(3, '0');
176
+ return `${hoursFormated}:${minutesFormated}:${secondsFormated}.${msFormated}`;
177
+ };
178
+ static formatBytesToString = (bytes) => {
179
+ if (bytes <= 0) {
180
+ return '0.00 KB';
181
+ }
182
+ const kb = bytes / 1024;
183
+ if (kb < 1024) {
184
+ return `${kb.toFixed(2)} KB`;
185
+ }
186
+ const mb = kb / 1024;
187
+ return `${mb.toFixed(2)} MB`;
188
+ };
189
+ static calculateThroughputMBps = (bytes, milliseconds) => {
190
+ if (bytes <= 0 || milliseconds <= 0) {
191
+ return 0;
192
+ }
193
+ const megabytes = bytes / 1024 / 1024;
194
+ const seconds = milliseconds / 1000;
195
+ return megabytes / seconds;
196
+ };
133
197
  static catchError = ({ error, logReporter, command, jsonFlag, }) => {
134
198
  let message;
135
199
  if ('message' in error && error.message.trim().length > 0) {
@@ -148,6 +212,23 @@ class CLIUtils {
148
212
  }
149
213
  };
150
214
  static parseEmpty = async (input) => (input.trim().length === 0 ? ' ' : input);
215
+ static prepareNetwork = ({ jsonFlag, loginUserDetails, }) => {
216
+ CLIUtils.doing('Preparing Network', jsonFlag);
217
+ const networkModule = sdk_manager_service_1.SdkManager.instance.getNetwork({
218
+ user: loginUserDetails.bridgeUser,
219
+ pass: loginUserDetails.userId,
220
+ });
221
+ const environment = new inxt_js_1.Environment({
222
+ bridgeUser: loginUserDetails.bridgeUser,
223
+ bridgePass: loginUserDetails.userId,
224
+ bridgeUrl: config_service_1.ConfigService.instance.get('NETWORK_URL'),
225
+ encryptionKey: loginUserDetails.mnemonic,
226
+ appDetails: sdk_manager_service_1.SdkManager.getAppDetails(),
227
+ });
228
+ const networkFacade = new network_facade_service_1.NetworkFacade(networkModule, environment, download_service_1.DownloadService.instance, crypto_service_1.CryptoService.instance);
229
+ CLIUtils.done(jsonFlag);
230
+ return networkFacade;
231
+ };
151
232
  }
152
233
  exports.CLIUtils = CLIUtils;
153
234
  class NoFlagProvidedError extends Error {
@@ -1,4 +1,6 @@
1
1
  export declare function isError(error: unknown): error is Error;
2
+ export declare function isAlreadyExistsError(error: unknown): error is Error;
3
+ export declare function isFileNotFoundError(error: unknown): error is NodeJS.ErrnoException;
2
4
  export declare class ErrorUtils {
3
5
  static report(error: unknown, props?: Record<string, unknown>): void;
4
6
  }
@@ -2,10 +2,21 @@
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;
6
+ exports.isFileNotFoundError = isFileNotFoundError;
5
7
  const logger_utils_1 = require("./logger.utils");
6
- const node_util_1 = require("node:util");
7
8
  function isError(error) {
8
- return node_util_1.types.isNativeError(error);
9
+ return typeof Error.isError === 'function'
10
+ ? Error.isError(error)
11
+ : error instanceof Error ||
12
+ (typeof error === 'object' && error !== null && 'message' in error && ('stack' in error || 'name' in error));
13
+ }
14
+ function isAlreadyExistsError(error) {
15
+ return ((isError(error) && error.message.includes('already exists')) ||
16
+ (typeof error === 'object' && error !== null && 'status' in error && error.status === 409));
17
+ }
18
+ function isFileNotFoundError(error) {
19
+ return isError(error) && 'code' in error && error.code === 'ENOENT';
9
20
  }
10
21
  class ErrorUtils {
11
22
  static report(error, props = {}) {
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.webdavLogger = exports.logger = void 0;
7
7
  const winston_1 = __importDefault(require("winston"));
8
- const config_service_1 = require("../services/config.service");
8
+ const configs_1 = require("../constants/configs");
9
9
  const maxLogSize = 40 * 1024 * 1024;
10
10
  const maxLogsFiles = 5;
11
11
  exports.logger = winston_1.default.createLogger({
@@ -16,14 +16,14 @@ exports.logger = winston_1.default.createLogger({
16
16
  new winston_1.default.transports.File({
17
17
  filename: 'internxt-cli-error.log',
18
18
  level: 'error',
19
- dirname: config_service_1.ConfigService.INTERNXT_CLI_LOGS_DIR,
19
+ dirname: configs_1.INTERNXT_CLI_LOGS_DIR,
20
20
  maxsize: maxLogSize,
21
21
  maxFiles: maxLogsFiles,
22
22
  tailable: true,
23
23
  }),
24
24
  new winston_1.default.transports.File({
25
25
  filename: 'internxt-cli-combined.log',
26
- dirname: config_service_1.ConfigService.INTERNXT_CLI_LOGS_DIR,
26
+ dirname: configs_1.INTERNXT_CLI_LOGS_DIR,
27
27
  maxsize: maxLogSize,
28
28
  maxFiles: maxLogsFiles,
29
29
  tailable: true,
@@ -38,14 +38,14 @@ exports.webdavLogger = winston_1.default.createLogger({
38
38
  new winston_1.default.transports.File({
39
39
  filename: 'internxt-webdav-error.log',
40
40
  level: 'error',
41
- dirname: config_service_1.ConfigService.INTERNXT_CLI_LOGS_DIR,
41
+ dirname: configs_1.INTERNXT_CLI_LOGS_DIR,
42
42
  maxsize: maxLogSize,
43
43
  maxFiles: maxLogsFiles,
44
44
  tailable: true,
45
45
  }),
46
46
  new winston_1.default.transports.File({
47
47
  filename: 'internxt-webdav-combined.log',
48
- dirname: config_service_1.ConfigService.INTERNXT_CLI_LOGS_DIR,
48
+ dirname: configs_1.INTERNXT_CLI_LOGS_DIR,
49
49
  maxsize: maxLogSize,
50
50
  maxFiles: maxLogsFiles,
51
51
  tailable: true,
@@ -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;
@@ -9,7 +9,7 @@ const promises_1 = require("node:fs/promises");
9
9
  const node_path_1 = __importDefault(require("node:path"));
10
10
  const selfsigned_1 = __importDefault(require("selfsigned"));
11
11
  const range_parser_1 = __importDefault(require("range-parser"));
12
- const config_service_1 = require("../services/config.service");
12
+ const configs_1 = require("../constants/configs");
13
13
  class NetworkUtils {
14
14
  static getAuthFromCredentials(creds) {
15
15
  return {
@@ -18,11 +18,11 @@ class NetworkUtils {
18
18
  };
19
19
  }
20
20
  static WEBDAV_SSL_CERTS_PATH = {
21
- cert: node_path_1.default.join(config_service_1.ConfigService.WEBDAV_SSL_CERTS_DIR, 'cert.crt'),
22
- privateKey: node_path_1.default.join(config_service_1.ConfigService.WEBDAV_SSL_CERTS_DIR, 'priv.key'),
21
+ cert: node_path_1.default.join(configs_1.WEBDAV_SSL_CERTS_DIR, 'cert.crt'),
22
+ privateKey: node_path_1.default.join(configs_1.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,20 +57,21 @@ 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
- const extensions = [
63
- {
64
- name: 'subjectAltName',
65
- altNames: [
66
- {
67
- type: 2,
68
- value: configs.host,
69
- },
70
- ],
71
- },
72
- ];
73
- const pems = selfsigned_1.default.generate(attrs, { days: 365, algorithm: 'sha256', keySize: 2048, extensions });
62
+ const extension = {
63
+ name: 'subjectAltName',
64
+ altNames: [
65
+ {
66
+ type: 2,
67
+ value: configs.host,
68
+ },
69
+ ],
70
+ };
71
+ const extensions = [extension];
72
+ const notAfterDate = new Date();
73
+ notAfterDate.setDate(notAfterDate.getDate() + 365);
74
+ const pems = await selfsigned_1.default.generate(attrs, { notAfterDate, algorithm: 'sha256', keySize: 2048, extensions });
74
75
  return pems;
75
76
  }
76
77
  static parseRangeHeader(rangeOptions) {
@@ -85,10 +86,7 @@ class NetworkUtils {
85
86
  else if (parsed.length <= 0) {
86
87
  throw new Error(`Empty Range-Request. ${JSON.stringify(rangeOptions)}`);
87
88
  }
88
- else if (parsed.type !== 'bytes') {
89
- throw new Error(`Unkwnown Range-Request type "${parsed.type}". ${JSON.stringify(rangeOptions)}`);
90
- }
91
- else {
89
+ if (parsed.type === 'bytes') {
92
90
  const rangeSize = parsed[0].end - parsed[0].start + 1;
93
91
  return {
94
92
  range: rangeOptions.range,
@@ -97,6 +95,9 @@ class NetworkUtils {
97
95
  parsed: parsed[0],
98
96
  };
99
97
  }
98
+ else {
99
+ throw new Error(`Unkwnown Range-Request type "${parsed.type}". ${JSON.stringify(rangeOptions)}`);
100
+ }
100
101
  }
101
102
  else if (parsed === -1) {
102
103
  throw new Error(`Malformed Range-Request. ${JSON.stringify(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,
@@ -21,24 +25,48 @@ const imageExtensions = {
21
25
  const pdfExtensions = {
22
26
  pdf: ['pdf'],
23
27
  };
24
- const thumbnailableImageExtension = [
28
+ const thumbnailableImageExtension = new Set([
25
29
  ...imageExtensions['jpg'],
26
30
  ...imageExtensions['png'],
27
31
  ...imageExtensions['webp'],
28
32
  ...imageExtensions['gif'],
29
33
  ...imageExtensions['tiff'],
30
- ];
31
- const thumbnailablePdfExtension = pdfExtensions['pdf'];
32
- const thumbnailableExtension = [...thumbnailableImageExtension];
34
+ ]);
35
+ const thumbnailablePdfExtension = new Set(pdfExtensions['pdf']);
36
+ const thumbnailableExtension = new Set(thumbnailableImageExtension);
33
37
  const isFileThumbnailable = (fileType) => {
34
- return fileType.trim().length > 0 && thumbnailableExtension.includes(fileType.trim().toLowerCase());
38
+ return fileType.trim().length > 0 && thumbnailableExtension.has(fileType.trim().toLowerCase());
35
39
  };
36
40
  exports.isFileThumbnailable = isFileThumbnailable;
37
41
  const isPDFThumbnailable = (fileType) => {
38
- return fileType.trim().length > 0 && thumbnailablePdfExtension.includes(fileType.trim().toLowerCase());
42
+ return fileType.trim().length > 0 && thumbnailablePdfExtension.has(fileType.trim().toLowerCase());
39
43
  };
40
44
  exports.isPDFThumbnailable = isPDFThumbnailable;
41
45
  const isImageThumbnailable = (fileType) => {
42
- return fileType.trim().length > 0 && thumbnailableImageExtension.includes(fileType.trim().toLowerCase());
46
+ return fileType.trim().length > 0 && thumbnailableImageExtension.has(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,8 +1,8 @@
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
- static toXML(object: object, options?: XmlBuilderOptions): string;
5
+ static toXML(object: object, options: XmlBuilderOptions): string;
6
6
  static toWebDavXML(object: object, options: XmlBuilderOptions, rootObject?: string): string;
7
7
  static addDefaultNamespace(key: string): string;
8
8
  static encodeWebDavUri(uri: string): string;
@@ -8,7 +8,7 @@ class XMLUtils {
8
8
  const parser = new fast_xml_parser_1.XMLParser(options);
9
9
  return parser.parse(xml);
10
10
  }
11
- static toXML(object, options = { format: true }) {
11
+ static toXML(object, options) {
12
12
  const builder = new fast_xml_parser_1.XMLBuilder(options);
13
13
  return builder.build(object);
14
14
  }