@internxt/cli 1.2.1 → 1.3.0

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 (92) hide show
  1. package/.env +2 -1
  2. package/README.md +404 -25
  3. package/bin/dev.js +0 -0
  4. package/bin/run.js +0 -0
  5. package/dist/commands/config.js +1 -1
  6. package/dist/commands/list.js +1 -2
  7. package/dist/commands/{move.d.ts → move-file.d.ts} +5 -4
  8. package/dist/commands/move-file.js +84 -0
  9. package/dist/commands/move-folder.d.ts +19 -0
  10. package/dist/commands/move-folder.js +84 -0
  11. package/dist/commands/rename.d.ts +18 -0
  12. package/dist/commands/{move.js → rename.js} +29 -29
  13. package/dist/commands/trash-clear.d.ts +15 -0
  14. package/dist/commands/trash-clear.js +64 -0
  15. package/dist/commands/trash-list.d.ts +20 -0
  16. package/dist/commands/trash-list.js +95 -0
  17. package/dist/commands/trash-restore-file.d.ts +19 -0
  18. package/dist/commands/trash-restore-file.js +87 -0
  19. package/dist/commands/trash-restore-folder.d.ts +19 -0
  20. package/dist/commands/trash-restore-folder.js +87 -0
  21. package/dist/commands/webdav-config.d.ts +17 -0
  22. package/dist/commands/webdav-config.js +91 -0
  23. package/dist/commands/webdav.d.ts +1 -1
  24. package/dist/commands/webdav.js +5 -2
  25. package/dist/database/migrations/20241018114828-add-parent-column.d.ts +1 -0
  26. package/dist/database/migrations/20241018114828-add-parent-column.js +24 -0
  27. package/dist/hooks/prerun/auth_check.js +2 -1
  28. package/dist/services/analytics.service.d.ts +9 -6
  29. package/dist/services/analytics.service.js +2 -35
  30. package/dist/services/config.service.d.ts +6 -1
  31. package/dist/services/config.service.js +24 -0
  32. package/dist/services/database/drive-database-manager.service.d.ts +10 -7
  33. package/dist/services/database/drive-database-manager.service.js +34 -24
  34. package/dist/services/database/drive-file/drive-file.attributes.d.ts +1 -0
  35. package/dist/services/database/drive-file/drive-file.domain.d.ts +4 -1
  36. package/dist/services/database/drive-file/drive-file.domain.js +21 -1
  37. package/dist/services/database/drive-file/drive-file.model.d.ts +1 -0
  38. package/dist/services/database/drive-file/drive-file.model.js +4 -0
  39. package/dist/services/database/drive-folder/drive-folder.attributes.d.ts +1 -0
  40. package/dist/services/database/drive-folder/drive-folder.domain.d.ts +4 -1
  41. package/dist/services/database/drive-folder/drive-folder.domain.js +18 -1
  42. package/dist/services/database/drive-folder/drive-folder.model.d.ts +1 -0
  43. package/dist/services/database/drive-folder/drive-folder.model.js +5 -0
  44. package/dist/services/drive/drive-file.service.d.ts +5 -0
  45. package/dist/services/drive/drive-file.service.js +10 -0
  46. package/dist/services/drive/drive-folder.service.d.ts +7 -2
  47. package/dist/services/drive/drive-folder.service.js +16 -0
  48. package/dist/services/drive/trash.service.d.ts +7 -0
  49. package/dist/services/drive/trash.service.js +30 -0
  50. package/dist/services/network/upload.service.js +5 -1
  51. package/dist/services/sdk-manager.service.d.ts +1 -2
  52. package/dist/services/sdk-manager.service.js +0 -5
  53. package/dist/services/usage.service.d.ts +2 -1
  54. package/dist/services/usage.service.js +3 -7
  55. package/dist/services/validation.service.d.ts +2 -0
  56. package/dist/services/validation.service.js +6 -0
  57. package/dist/types/command.types.d.ts +16 -0
  58. package/dist/types/command.types.js +29 -1
  59. package/dist/types/config.types.d.ts +0 -1
  60. package/dist/types/drive.types.d.ts +2 -1
  61. package/dist/types/network.types.d.ts +5 -0
  62. package/dist/types/webdav.types.d.ts +1 -0
  63. package/dist/utils/cli.utils.d.ts +1 -1
  64. package/dist/utils/drive.utils.js +3 -1
  65. package/dist/utils/network.utils.d.ts +3 -9
  66. package/dist/utils/network.utils.js +21 -7
  67. package/dist/utils/webdav.utils.d.ts +16 -2
  68. package/dist/utils/webdav.utils.js +71 -20
  69. package/dist/utils/xml.utils.d.ts +1 -0
  70. package/dist/utils/xml.utils.js +3 -0
  71. package/dist/webdav/handlers/DELETE.handler.d.ts +5 -1
  72. package/dist/webdav/handlers/DELETE.handler.js +15 -12
  73. package/dist/webdav/handlers/GET.handler.d.ts +1 -2
  74. package/dist/webdav/handlers/GET.handler.js +10 -13
  75. package/dist/webdav/handlers/HEAD.handler.d.ts +1 -1
  76. package/dist/webdav/handlers/HEAD.handler.js +2 -2
  77. package/dist/webdav/handlers/MKCOL.handler.d.ts +1 -1
  78. package/dist/webdav/handlers/MKCOL.handler.js +14 -15
  79. package/dist/webdav/handlers/MOVE.handler.d.ts +11 -1
  80. package/dist/webdav/handlers/MOVE.handler.js +73 -2
  81. package/dist/webdav/handlers/OPTIONS.handler.d.ts +1 -1
  82. package/dist/webdav/handlers/OPTIONS.handler.js +2 -2
  83. package/dist/webdav/handlers/PROPFIND.handler.d.ts +11 -12
  84. package/dist/webdav/handlers/PROPFIND.handler.js +62 -76
  85. package/dist/webdav/handlers/PUT.handler.d.ts +5 -8
  86. package/dist/webdav/handlers/PUT.handler.js +34 -18
  87. package/dist/webdav/middewares/request-logger.middleware.js +1 -1
  88. package/dist/webdav/webdav-server.d.ts +14 -14
  89. package/dist/webdav/webdav-server.js +31 -14
  90. package/oclif.manifest.json +441 -8
  91. package/package.json +22 -26
  92. package/scripts/add-cert.sh +19 -5
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const config_service_1 = require("../services/config.service");
5
+ const drive_folder_service_1 = require("../services/drive/drive-folder.service");
6
+ const cli_utils_1 = require("../utils/cli.utils");
7
+ const command_types_1 = require("../types/command.types");
8
+ const validation_service_1 = require("../services/validation.service");
9
+ const errors_utils_1 = require("../utils/errors.utils");
10
+ class TrashRestoreFolder extends core_1.Command {
11
+ static args = {};
12
+ static description = 'Restore a trashed folder into a destination folder.';
13
+ static examples = ['<%= config.bin %> <%= command.id %>'];
14
+ static aliases = ['trash:restore:folder'];
15
+ static flags = {
16
+ ...cli_utils_1.CLIUtils.CommonFlags,
17
+ id: core_1.Flags.string({
18
+ char: 'i',
19
+ description: 'The folder id to be restored from the trash.',
20
+ required: false,
21
+ }),
22
+ destination: core_1.Flags.string({
23
+ char: 'd',
24
+ description: 'The folder id where the folder is going to be restored. Leave empty for the root folder.',
25
+ required: false,
26
+ parse: cli_utils_1.CLIUtils.parseEmpty,
27
+ }),
28
+ };
29
+ async run() {
30
+ const { flags } = await this.parse(TrashRestoreFolder);
31
+ const nonInteractive = flags['non-interactive'];
32
+ const userCredentials = await config_service_1.ConfigService.instance.readUser();
33
+ if (!userCredentials)
34
+ throw new command_types_1.MissingCredentialsError();
35
+ const folderUuid = await this.getFolderUuid(flags['id'], nonInteractive);
36
+ let destinationFolderUuid = await this.getDestinationFolderUuid(flags['destination'], nonInteractive);
37
+ if (destinationFolderUuid.trim().length === 0) {
38
+ destinationFolderUuid = userCredentials.root_folder_uuid;
39
+ }
40
+ await drive_folder_service_1.DriveFolderService.instance.moveFolder({ folderUuid, destinationFolderUuid });
41
+ cli_utils_1.CLIUtils.success(`Folder restored successfully to: ${destinationFolderUuid}`);
42
+ }
43
+ async catch(error) {
44
+ errors_utils_1.ErrorUtils.report(error, { command: this.id });
45
+ cli_utils_1.CLIUtils.error(error.message);
46
+ this.exit(1);
47
+ }
48
+ getFolderUuid = async (folderUuidFlag, nonInteractive) => {
49
+ let folderUuid = cli_utils_1.CLIUtils.getValueFromFlag({
50
+ value: folderUuidFlag,
51
+ name: TrashRestoreFolder.flags['id'].name,
52
+ error: new command_types_1.NotValidFolderUuidError(),
53
+ canBeEmpty: true,
54
+ }, nonInteractive, (folderUuid) => validation_service_1.ValidationService.instance.validateUUIDv4(folderUuid));
55
+ if (!folderUuid) {
56
+ folderUuid = (await this.getFolderUuidInteractively()).trim();
57
+ }
58
+ return folderUuid;
59
+ };
60
+ getDestinationFolderUuid = async (destinationFolderUuidFlag, nonInteractive) => {
61
+ let destinationFolderUuid = cli_utils_1.CLIUtils.getValueFromFlag({
62
+ value: destinationFolderUuidFlag,
63
+ name: TrashRestoreFolder.flags['destination'].name,
64
+ error: new command_types_1.NotValidFolderUuidError(),
65
+ canBeEmpty: true,
66
+ }, nonInteractive, (folderUuid) => validation_service_1.ValidationService.instance.validateUUIDv4(folderUuid));
67
+ if (!destinationFolderUuid) {
68
+ destinationFolderUuid = (await this.getDestinationFolderUuidInteractively()).trim();
69
+ }
70
+ return destinationFolderUuid;
71
+ };
72
+ static MAX_ATTEMPTS = 3;
73
+ getFolderUuidInteractively = () => {
74
+ return cli_utils_1.CLIUtils.promptWithAttempts({
75
+ message: 'What is the folder id you want to restore?',
76
+ options: { required: true },
77
+ error: new command_types_1.NotValidFolderUuidError(),
78
+ }, TrashRestoreFolder.MAX_ATTEMPTS, validation_service_1.ValidationService.instance.validateUUIDv4);
79
+ };
80
+ getDestinationFolderUuidInteractively = () => {
81
+ return cli_utils_1.CLIUtils.prompt({
82
+ message: 'What is the destination folder id? (leave empty for the root folder)',
83
+ options: { required: false },
84
+ });
85
+ };
86
+ }
87
+ exports.default = TrashRestoreFolder;
@@ -0,0 +1,17 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class WebDAVConfig extends Command {
3
+ static readonly description = "Edit the configuration of the Internxt CLI WebDav server as the port or the protocol.";
4
+ static readonly args: {
5
+ action: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static readonly examples: string[];
8
+ static readonly flags: {
9
+ port: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
+ 'non-interactive': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<void>;
13
+ catch(error: Error): Promise<void>;
14
+ private static readonly MAX_ATTEMPTS;
15
+ getWebDAVPort: (webdavPortFlag: string | undefined, nonInteractive: boolean) => Promise<string>;
16
+ getNewWebDAVPortInteractively: () => Promise<string>;
17
+ }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const config_service_1 = require("../services/config.service");
5
+ const cli_utils_1 = require("../utils/cli.utils");
6
+ const errors_utils_1 = require("../utils/errors.utils");
7
+ const command_types_1 = require("../types/command.types");
8
+ const validation_service_1 = require("../services/validation.service");
9
+ class WebDAVConfig extends core_1.Command {
10
+ static description = 'Edit the configuration of the Internxt CLI WebDav server as the port or the protocol.';
11
+ static args = {
12
+ action: core_1.Args.string({
13
+ required: true,
14
+ options: ['set-http', 'set-https', 'change-port'],
15
+ }),
16
+ };
17
+ static examples = [
18
+ '<%= config.bin %> <%= command.id %> set-http',
19
+ '<%= config.bin %> <%= command.id %> set-https',
20
+ '<%= config.bin %> <%= command.id %> change-port',
21
+ ];
22
+ static flags = {
23
+ ...cli_utils_1.CLIUtils.CommonFlags,
24
+ port: core_1.Flags.string({
25
+ char: 'p',
26
+ description: 'The new port that the WebDAV server is going to be have.',
27
+ required: false,
28
+ }),
29
+ };
30
+ async run() {
31
+ const { args, flags } = await this.parse(WebDAVConfig);
32
+ const nonInteractive = flags['non-interactive'];
33
+ const webdavConfig = await config_service_1.ConfigService.instance.readWebdavConfig();
34
+ if (args.action !== 'change-port' && flags['port']) {
35
+ cli_utils_1.CLIUtils.warning('The port flag will be ignored; it can only be used with the "change-port" action.');
36
+ }
37
+ switch (args.action) {
38
+ case 'set-http': {
39
+ await config_service_1.ConfigService.instance.saveWebdavConfig({
40
+ ...webdavConfig,
41
+ protocol: 'http',
42
+ });
43
+ cli_utils_1.CLIUtils.success('On the next start, the WebDAV server will use HTTP.');
44
+ break;
45
+ }
46
+ case 'set-https': {
47
+ await config_service_1.ConfigService.instance.saveWebdavConfig({
48
+ ...webdavConfig,
49
+ protocol: 'https',
50
+ });
51
+ cli_utils_1.CLIUtils.success('On the next start, the WebDAV server will use HTTPS.');
52
+ break;
53
+ }
54
+ case 'change-port': {
55
+ const newPort = await this.getWebDAVPort(flags['port'], nonInteractive);
56
+ await config_service_1.ConfigService.instance.saveWebdavConfig({
57
+ ...webdavConfig,
58
+ port: newPort,
59
+ });
60
+ cli_utils_1.CLIUtils.success('For the next start, the Webdav server will be served at the new port: ' + newPort);
61
+ break;
62
+ }
63
+ }
64
+ }
65
+ async catch(error) {
66
+ errors_utils_1.ErrorUtils.report(error, { command: this.id });
67
+ cli_utils_1.CLIUtils.error(error.message);
68
+ this.exit(1);
69
+ }
70
+ static MAX_ATTEMPTS = 3;
71
+ getWebDAVPort = async (webdavPortFlag, nonInteractive) => {
72
+ let port = cli_utils_1.CLIUtils.getValueFromFlag({
73
+ value: webdavPortFlag,
74
+ name: WebDAVConfig.flags['port'].name,
75
+ error: new command_types_1.NotValidPortError(),
76
+ canBeEmpty: true,
77
+ }, nonInteractive, (port) => validation_service_1.ValidationService.instance.validateTCPIntegerPort(port));
78
+ if (!port) {
79
+ port = (await this.getNewWebDAVPortInteractively()).trim();
80
+ }
81
+ return port;
82
+ };
83
+ getNewWebDAVPortInteractively = () => {
84
+ return cli_utils_1.CLIUtils.promptWithAttempts({
85
+ message: 'What is the new WebDAV server port?',
86
+ options: { required: false },
87
+ error: new command_types_1.NotValidPortError(),
88
+ }, WebDAVConfig.MAX_ATTEMPTS, (port) => validation_service_1.ValidationService.instance.validateTCPIntegerPort(port));
89
+ };
90
+ }
91
+ exports.default = WebDAVConfig;
@@ -1,6 +1,6 @@
1
1
  import { Command } from '@oclif/core';
2
2
  export default class Webdav extends Command {
3
- static readonly description = "Enable,disable, restart or get the status of the Internxt CLI WebDav server";
3
+ static readonly description = "Enable, disable, restart or get the status of the Internxt CLI WebDav server";
4
4
  static examples: string[];
5
5
  static flags: {};
6
6
  static args: {
@@ -8,7 +8,7 @@ const analytics_service_1 = require("../services/analytics.service");
8
8
  const auth_service_1 = require("../services/auth.service");
9
9
  const drive_database_manager_service_1 = require("../services/database/drive-database-manager.service");
10
10
  class Webdav extends core_1.Command {
11
- static description = 'Enable,disable, restart or get the status of the Internxt CLI WebDav server';
11
+ static description = 'Enable, disable, restart or get the status of the Internxt CLI WebDav server';
12
12
  static examples = [
13
13
  '<%= config.bin %> <%= command.id %> enable',
14
14
  '<%= config.bin %> <%= command.id %> disable',
@@ -24,14 +24,17 @@ class Webdav extends core_1.Command {
24
24
  };
25
25
  async enableWebDav() {
26
26
  cli_utils_1.CLIUtils.doing('Starting Internxt WebDav server...');
27
+ await drive_database_manager_service_1.DriveDatabaseManager.clean();
27
28
  await pm2_utils_1.PM2Utils.connect();
28
29
  await pm2_utils_1.PM2Utils.killWebDavServer();
29
30
  await pm2_utils_1.PM2Utils.startWebDavServer();
30
31
  cli_utils_1.CLIUtils.done();
31
32
  const { status } = await pm2_utils_1.PM2Utils.webdavServerStatus();
33
+ const webdavConfigs = await config_service_1.ConfigService.instance.readWebdavConfig();
32
34
  if (status === 'online') {
33
35
  core_1.ux.log(`\nWebDav server status: ${core_1.ux.colorize('green', 'online')}\n`);
34
- cli_utils_1.CLIUtils.success(`Internxt WebDav server started successfully on https://${config_service_1.ConfigService.WEBDAV_LOCAL_URL}:${process.env.WEBDAV_SERVER_PORT}`);
36
+ cli_utils_1.CLIUtils.success(`Internxt WebDav server started successfully at ${webdavConfigs.protocol}://${config_service_1.ConfigService.WEBDAV_LOCAL_URL}:${webdavConfigs.port}`);
37
+ core_1.ux.log(`\n[If the above URL is not working, the WebDAV server can be accessed directly via your localhost IP at: ${webdavConfigs.protocol}://127.0.0.1:${webdavConfigs.port} ]\n`);
35
38
  const authDetails = await auth_service_1.AuthService.instance.getAuthDetails();
36
39
  await analytics_service_1.AnalyticsService.instance.track('WebDAVEnabled', { app: 'internxt-cli', userId: authDetails.user.uuid });
37
40
  }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ module.exports = {
4
+ async up(queryInterface, Sequelize) {
5
+ await queryInterface.addColumn('folders', 'parent_uuid', {
6
+ type: Sequelize.UUIDV4,
7
+ references: {
8
+ model: 'folders',
9
+ key: 'uuid',
10
+ },
11
+ });
12
+ await queryInterface.addColumn('files', 'folder_uuid', {
13
+ type: Sequelize.UUIDV4,
14
+ references: {
15
+ model: 'files',
16
+ key: 'uuid',
17
+ },
18
+ });
19
+ },
20
+ async down(queryInterface) {
21
+ await queryInterface.removeColumn('folders', 'parent_uuid');
22
+ await queryInterface.removeColumn('files', 'folder_uuid');
23
+ },
24
+ };
@@ -12,7 +12,8 @@ const sdk_manager_service_1 = require("../../services/sdk-manager.service");
12
12
  const auth_service_1 = require("../../services/auth.service");
13
13
  const command_types_1 = require("../../types/command.types");
14
14
  const webdav_1 = __importDefault(require("../../commands/webdav"));
15
- const CommandsToSkip = [whoami_1.default, login_1.default, logout_1.default, logs_1.default, webdav_1.default];
15
+ const webdav_config_1 = __importDefault(require("../../commands/webdav-config"));
16
+ const CommandsToSkip = [whoami_1.default, login_1.default, logout_1.default, logs_1.default, webdav_1.default, webdav_config_1.default];
16
17
  const hook = async function (opts) {
17
18
  if (!CommandsToSkip.map((command) => command.name).includes(opts.Command.name)) {
18
19
  cli_utils_1.CLIUtils.doing('Checking credentials');
@@ -1,4 +1,3 @@
1
- import { apiObject } from '@rudderstack/rudder-sdk-node';
2
1
  import { ConfigService } from './config.service';
3
2
  export declare const AnalyticsEvents: {
4
3
  CLILogin: string;
@@ -6,14 +5,18 @@ export declare const AnalyticsEvents: {
6
5
  WebDAVRequest: string;
7
6
  };
8
7
  export declare class AnalyticsService {
9
- private config;
8
+ private readonly config;
10
9
  static readonly instance: AnalyticsService;
11
10
  constructor(config: ConfigService);
12
- private getRudderstack;
13
- private platformShortName;
14
- private platformFamily;
15
11
  track(eventKey: keyof typeof AnalyticsEvents, options: {
16
12
  app: 'internxt-cli' | 'internxt-webdav';
17
13
  userId: string;
18
- }, params?: apiObject): void;
14
+ }, params?: object): Promise<{
15
+ eventKey: "CLILogin" | "WebDAVEnabled" | "WebDAVRequest";
16
+ options: {
17
+ app: 'internxt-cli' | 'internxt-webdav';
18
+ userId: string;
19
+ };
20
+ params: object;
21
+ }>;
19
22
  }
@@ -1,10 +1,6 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.AnalyticsService = exports.AnalyticsEvents = void 0;
7
- const rudder_sdk_node_1 = __importDefault(require("@rudderstack/rudder-sdk-node"));
8
4
  const config_service_1 = require("./config.service");
9
5
  exports.AnalyticsEvents = {
10
6
  CLILogin: 'CLI Login',
@@ -17,37 +13,8 @@ class AnalyticsService {
17
13
  constructor(config) {
18
14
  this.config = config;
19
15
  }
20
- getRudderstack() {
21
- return new rudder_sdk_node_1.default(this.config.get('RUDDERSTACK_WRITE_KEY'), {
22
- dataPlaneUrl: this.config.get('RUDDERSTACK_DATAPLANE_URL'),
23
- });
24
- }
25
- platformShortName(platform) {
26
- switch (platform) {
27
- case 'darwin':
28
- return 'MAC';
29
- case 'win32':
30
- return 'WIN';
31
- case 'linux':
32
- return 'LINUX';
33
- default:
34
- return '';
35
- }
36
- }
37
- platformFamily(platform) {
38
- switch (platform) {
39
- case 'darwin':
40
- return 'Mac';
41
- case 'win32':
42
- return 'Windows';
43
- case 'linux':
44
- return 'Linux';
45
- default:
46
- return 'Unknown';
47
- }
48
- }
49
- track(eventKey, options, params = {}) {
50
- return;
16
+ async track(eventKey, options, params = {}) {
17
+ return { eventKey, options, params };
51
18
  }
52
19
  }
53
20
  exports.AnalyticsService = AnalyticsService;
@@ -1,5 +1,5 @@
1
1
  import { ConfigKeys } from '../types/config.types';
2
- import { CLICredentials } from '../types/command.types';
2
+ import { CLICredentials, WebdavConfig } from '../types/command.types';
3
3
  export declare class ConfigService {
4
4
  static readonly INTERNXT_CLI_DATA_DIR: string;
5
5
  static readonly INTERNXT_CLI_LOGS_DIR: string;
@@ -7,12 +7,17 @@ export declare class ConfigService {
7
7
  static readonly CREDENTIALS_FILE: string;
8
8
  static readonly DRIVE_SQLITE_FILE: string;
9
9
  static readonly WEBDAV_SSL_CERTS_DIR: string;
10
+ static readonly WEBDAV_CONFIGS_FILE: string;
10
11
  static readonly WEBDAV_LOCAL_URL = "webdav.local.internxt.com";
12
+ static readonly WEBDAV_DEFAULT_PORT = "3005";
13
+ static readonly WEBDAV_DEFAULT_PROTOCOL = "https";
11
14
  static readonly instance: ConfigService;
12
15
  get: (key: keyof ConfigKeys) => string;
13
16
  saveUser: (loginCredentials: CLICredentials) => Promise<void>;
14
17
  clearUser: () => Promise<void>;
15
18
  readUser: () => Promise<CLICredentials | undefined>;
19
+ saveWebdavConfig: (webdavConfig: WebdavConfig) => Promise<void>;
20
+ readWebdavConfig: () => Promise<WebdavConfig>;
16
21
  ensureInternxtCliDataDirExists: () => Promise<void>;
17
22
  ensureWebdavCertsDirExists: () => Promise<void>;
18
23
  ensureInternxtLogsDirExists: () => Promise<void>;
@@ -15,7 +15,10 @@ class ConfigService {
15
15
  static CREDENTIALS_FILE = path_1.default.join(this.INTERNXT_CLI_DATA_DIR, '.inxtcli');
16
16
  static DRIVE_SQLITE_FILE = path_1.default.join(this.INTERNXT_CLI_DATA_DIR, 'internxt-cli-drive.sqlite');
17
17
  static WEBDAV_SSL_CERTS_DIR = path_1.default.join(this.INTERNXT_CLI_DATA_DIR, 'certs');
18
+ static WEBDAV_CONFIGS_FILE = path_1.default.join(this.INTERNXT_CLI_DATA_DIR, 'config.webdav.inxt');
18
19
  static WEBDAV_LOCAL_URL = 'webdav.local.internxt.com';
20
+ static WEBDAV_DEFAULT_PORT = '3005';
21
+ static WEBDAV_DEFAULT_PROTOCOL = 'https';
19
22
  static instance = new ConfigService();
20
23
  get = (key) => {
21
24
  const value = process.env[key];
@@ -51,6 +54,27 @@ class ConfigService {
51
54
  return;
52
55
  }
53
56
  };
57
+ saveWebdavConfig = async (webdavConfig) => {
58
+ await this.ensureInternxtCliDataDirExists();
59
+ const configs = JSON.stringify(webdavConfig);
60
+ await promises_1.default.writeFile(ConfigService.WEBDAV_CONFIGS_FILE, configs, 'utf8');
61
+ };
62
+ readWebdavConfig = async () => {
63
+ try {
64
+ const configsData = await promises_1.default.readFile(ConfigService.WEBDAV_CONFIGS_FILE, 'utf8');
65
+ const configs = JSON.parse(configsData);
66
+ return {
67
+ port: configs?.port ?? ConfigService.WEBDAV_DEFAULT_PORT,
68
+ protocol: configs?.protocol ?? ConfigService.WEBDAV_DEFAULT_PROTOCOL,
69
+ };
70
+ }
71
+ catch {
72
+ return {
73
+ port: ConfigService.WEBDAV_DEFAULT_PORT,
74
+ protocol: ConfigService.WEBDAV_DEFAULT_PROTOCOL,
75
+ };
76
+ }
77
+ };
54
78
  ensureInternxtCliDataDirExists = async () => {
55
79
  try {
56
80
  await promises_1.default.access(ConfigService.INTERNXT_CLI_DATA_DIR);
@@ -4,17 +4,20 @@ import { DriveFolderRepository } from './drive-folder/drive-folder.repository';
4
4
  import { DriveFile } from './drive-file/drive-file.domain';
5
5
  import { DriveFolder } from './drive-folder/drive-folder.domain';
6
6
  export declare class DriveDatabaseManager {
7
- private driveFileRepository;
8
- private driveFolderRepository;
7
+ private readonly driveFileRepository;
8
+ private readonly driveFolderRepository;
9
9
  private static readonly sequelize;
10
10
  constructor(driveFileRepository: DriveFileRepository, driveFolderRepository: DriveFolderRepository);
11
11
  static readonly init: () => Promise<void>;
12
12
  static readonly clean: () => Promise<void>;
13
- findByRelativePath: (relativePath: string) => Promise<DriveFolder | DriveFile | null>;
14
- createFolder: (driveFolder: DriveFolderItem) => Promise<DriveFolder>;
15
- createFile: (driveFile: DriveFileItem) => Promise<DriveFile>;
13
+ findFileByRelativePath: (relativePath: string) => Promise<DriveFile | null>;
14
+ findFolderByRelativePath: (relativePath: string) => Promise<DriveFolder | null>;
15
+ createFolder: (driveFolder: DriveFolderItem, relativePath: string) => Promise<DriveFolder>;
16
+ createFile: (driveFile: DriveFileItem, relativePath: string) => Promise<DriveFile>;
16
17
  buildRelativePathForFile: (fileName: string, parentId: number | null) => Promise<string>;
17
18
  buildRelativePathForFolder: (folderName: string, parentId: number | null) => Promise<string>;
18
- deleteFile: (id: number) => Promise<void>;
19
- deleteFolder: (id: number) => Promise<void>;
19
+ deleteFileById: (id: number) => Promise<void>;
20
+ deleteFolderById: (id: number) => Promise<void>;
21
+ deleteFileByPath: (relativePath: string) => Promise<void>;
22
+ deleteFolderByPath: (relativePath: string) => Promise<void>;
20
23
  }
@@ -25,36 +25,29 @@ class DriveDatabaseManager {
25
25
  this.driveFolderRepository = driveFolderRepository;
26
26
  }
27
27
  static init = async () => {
28
- await DriveDatabaseManager.sequelize.sync();
28
+ await DriveDatabaseManager.sequelize.sync({ force: true });
29
29
  };
30
30
  static clean = async () => {
31
31
  await drive_file_repository_1.DriveFileRepository.clean();
32
32
  await drive_folder_repository_1.DriveFolderRepository.clean();
33
33
  };
34
- findByRelativePath = async (relativePath) => {
34
+ findFileByRelativePath = async (relativePath) => {
35
35
  const driveFile = await this.driveFileRepository.findByRelativePath(relativePath);
36
- if (driveFile)
37
- return driveFile;
38
- let folderRelativePath = relativePath;
39
- if (!relativePath.endsWith('/'))
40
- folderRelativePath = relativePath.concat('/');
36
+ return driveFile ?? null;
37
+ };
38
+ findFolderByRelativePath = async (relativePath) => {
39
+ const folderRelativePath = relativePath.endsWith('/') ? relativePath : relativePath.concat('/');
41
40
  const driveFolder = await this.driveFolderRepository.findByRelativePath(folderRelativePath);
42
- if (driveFolder)
43
- return driveFolder;
44
- return null;
41
+ return driveFolder ?? null;
45
42
  };
46
- createFolder = async (driveFolder) => {
47
- const relativePath = await this.buildRelativePathForFolder(driveFolder.name, driveFolder.parentId ?? null);
48
- const existingObject = await this.driveFolderRepository.findById(driveFolder.id);
49
- if (existingObject)
50
- await this.driveFolderRepository.deleteById(existingObject.id);
43
+ createFolder = async (driveFolder, relativePath) => {
44
+ await this.deleteFolderById(driveFolder.id);
45
+ await this.deleteFolderByPath(relativePath);
51
46
  return await this.driveFolderRepository.createFolder(driveFolder, relativePath);
52
47
  };
53
- createFile = async (driveFile) => {
54
- const relativePath = await this.buildRelativePathForFile(driveFile.type ? `${driveFile.name}.${driveFile.type}` : driveFile.name, driveFile.folderId);
55
- const existingObject = await this.driveFileRepository.findById(driveFile.id);
56
- if (existingObject)
57
- await this.driveFileRepository.deleteById(existingObject.id);
48
+ createFile = async (driveFile, relativePath) => {
49
+ await this.deleteFileById(driveFile.id);
50
+ await this.deleteFileByPath(relativePath);
58
51
  return await this.driveFileRepository.createFile(driveFile, relativePath);
59
52
  };
60
53
  buildRelativePathForFile = async (fileName, parentId) => {
@@ -73,11 +66,28 @@ class DriveDatabaseManager {
73
66
  const parentPath = await this.buildRelativePathForFolder(parentFolder.name, parentFolder.parentId);
74
67
  return webdav_utils_1.WebDavUtils.joinURL(parentPath, folderName, '/');
75
68
  };
76
- deleteFile = (id) => {
77
- return this.driveFileRepository.deleteById(id);
69
+ deleteFileById = async (id) => {
70
+ const existingObject = await this.driveFileRepository.findById(id);
71
+ if (existingObject) {
72
+ await this.driveFileRepository.deleteById(existingObject.id);
73
+ }
74
+ };
75
+ deleteFolderById = async (id) => {
76
+ const existingObject = await this.driveFolderRepository.findById(id);
77
+ if (existingObject) {
78
+ await this.driveFolderRepository.deleteById(existingObject.id);
79
+ }
78
80
  };
79
- deleteFolder = (id) => {
80
- return this.driveFolderRepository.deleteById(id);
81
+ deleteFileByPath = async (relativePath) => {
82
+ const existingPath = await this.driveFileRepository.findByRelativePath(relativePath);
83
+ if (existingPath)
84
+ await this.driveFileRepository.deleteById(existingPath.id);
85
+ };
86
+ deleteFolderByPath = async (relativePath) => {
87
+ const existingPath = await this.driveFolderRepository.findByRelativePath(relativePath);
88
+ if (existingPath) {
89
+ await this.driveFolderRepository.deleteById(existingPath.id);
90
+ }
81
91
  };
82
92
  }
83
93
  exports.DriveDatabaseManager = DriveDatabaseManager;
@@ -5,6 +5,7 @@ export interface DriveFileAttributes {
5
5
  uuid: string;
6
6
  fileId: string;
7
7
  folderId: number;
8
+ folderUuid: string;
8
9
  bucket: string;
9
10
  relativePath: string;
10
11
  createdAt: Date;
@@ -1,3 +1,4 @@
1
+ import { DriveFileItem } from '../../../types/drive.types';
1
2
  import { DriveFileAttributes } from './drive-file.attributes';
2
3
  export declare class DriveFile implements DriveFileAttributes {
3
4
  id: number;
@@ -6,13 +7,15 @@ export declare class DriveFile implements DriveFileAttributes {
6
7
  uuid: string;
7
8
  fileId: string;
8
9
  folderId: number;
10
+ folderUuid: string;
9
11
  bucket: string;
10
12
  relativePath: string;
11
13
  createdAt: Date;
12
14
  updatedAt: Date;
13
15
  size: number;
14
16
  status: string;
15
- constructor({ id, name, type, uuid, fileId, folderId, bucket, relativePath, createdAt, updatedAt, size, status, }: DriveFileAttributes);
17
+ constructor({ id, name, type, uuid, fileId, folderId, folderUuid, bucket, relativePath, createdAt, updatedAt, size, status, }: DriveFileAttributes);
16
18
  static build(file: DriveFileAttributes): DriveFile;
17
19
  toJSON(): DriveFileAttributes;
20
+ toItem(): DriveFileItem;
18
21
  }
@@ -8,19 +8,21 @@ class DriveFile {
8
8
  uuid;
9
9
  fileId;
10
10
  folderId;
11
+ folderUuid;
11
12
  bucket;
12
13
  relativePath;
13
14
  createdAt;
14
15
  updatedAt;
15
16
  size;
16
17
  status;
17
- constructor({ id, name, type, uuid, fileId, folderId, bucket, relativePath, createdAt, updatedAt, size, status, }) {
18
+ constructor({ id, name, type, uuid, fileId, folderId, folderUuid, bucket, relativePath, createdAt, updatedAt, size, status, }) {
18
19
  this.id = id;
19
20
  this.name = name;
20
21
  this.type = type;
21
22
  this.uuid = uuid;
22
23
  this.fileId = fileId;
23
24
  this.folderId = folderId;
25
+ this.folderUuid = folderUuid;
24
26
  this.bucket = bucket;
25
27
  this.relativePath = relativePath;
26
28
  this.createdAt = createdAt;
@@ -39,6 +41,7 @@ class DriveFile {
39
41
  uuid: this.uuid,
40
42
  fileId: this.fileId,
41
43
  folderId: this.folderId,
44
+ folderUuid: this.folderUuid,
42
45
  bucket: this.bucket,
43
46
  relativePath: this.relativePath,
44
47
  createdAt: this.createdAt,
@@ -47,5 +50,22 @@ class DriveFile {
47
50
  status: this.status,
48
51
  };
49
52
  }
53
+ toItem() {
54
+ return {
55
+ id: this.id,
56
+ name: this.name,
57
+ type: this.type,
58
+ uuid: this.uuid,
59
+ fileId: this.fileId,
60
+ folderId: this.folderId,
61
+ folderUuid: this.folderUuid,
62
+ bucket: this.bucket,
63
+ createdAt: this.createdAt,
64
+ updatedAt: this.updatedAt,
65
+ size: this.size,
66
+ status: this.status,
67
+ encryptedName: '',
68
+ };
69
+ }
50
70
  }
51
71
  exports.DriveFile = DriveFile;
@@ -7,6 +7,7 @@ export declare class DriveFileModel extends Model implements DriveFileAttributes
7
7
  uuid: string;
8
8
  fileId: string;
9
9
  folderId: number;
10
+ folderUuid: string;
10
11
  bucket: string;
11
12
  relativePath: string;
12
13
  size: number;
@@ -43,6 +43,10 @@ __decorate([
43
43
  (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.INTEGER),
44
44
  __metadata("design:type", Number)
45
45
  ], DriveFileModel.prototype, "folderId", void 0);
46
+ __decorate([
47
+ (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.UUIDV4),
48
+ __metadata("design:type", String)
49
+ ], DriveFileModel.prototype, "folderUuid", void 0);
46
50
  __decorate([
47
51
  (0, sequelize_typescript_1.Column)(sequelize_typescript_1.DataType.STRING(24)),
48
52
  __metadata("design:type", String)
@@ -5,6 +5,7 @@ export interface DriveFolderAttributes {
5
5
  status: 'EXISTS' | 'TRASHED';
6
6
  relativePath: string;
7
7
  parentId: number | null;
8
+ parentUuid: string | null;
8
9
  createdAt: Date;
9
10
  updatedAt: Date;
10
11
  }