diff --git a/src/commands/download-file.ts b/src/commands/download-file.ts index 2b58330c..cd9ffcd3 100644 --- a/src/commands/download-file.ts +++ b/src/commands/download-file.ts @@ -1,21 +1,14 @@ import { Command, Flags } from '@oclif/core'; import { DriveFileService } from '../services/drive/drive-file.service'; import { CLIUtils } from '../utils/cli.utils'; -import { NetworkFacade } from '../services/network/network-facade.service'; import { AuthService } from '../services/auth.service'; -import { CryptoService } from '../services/crypto.service'; -import { DownloadService } from '../services/network/download.service'; -import { SdkManager } from '../services/sdk-manager.service'; import { createWriteStream } from 'node:fs'; import { DriveFileItem } from '../types/drive.types'; import fs from 'node:fs/promises'; import path from 'node:path'; import { StreamUtils } from '../utils/stream.utils'; -import { LoginUserDetails, NotValidDirectoryError, NotValidFileUuidError } from '../types/command.types'; +import { NotValidDirectoryError, NotValidFileUuidError } from '../types/command.types'; import { ValidationService } from '../services/validation.service'; -import { Environment } from '@internxt/inxt-js'; -import { ConfigService } from '../services/config.service'; - export default class DownloadFile extends Command { static readonly args = {}; static readonly description = @@ -64,7 +57,7 @@ export default class DownloadFile extends Command { // 2. Prepare the network const { user } = await AuthService.instance.getAuthDetails(); - const networkFacade = await this.prepareNetwork(user, flags['json']); + const networkFacade = await CLIUtils.prepareNetwork({ loginUserDetails: user, jsonFlag: flags['json'] }); // 3. Download the file const fileWriteStream = createWriteStream(downloadPath); @@ -203,29 +196,4 @@ export default class DownloadFile extends Command { return downloadPath; }; - - private prepareNetwork = async (user: LoginUserDetails, jsonFlag?: boolean) => { - CLIUtils.doing('Preparing Network', jsonFlag); - - const networkModule = SdkManager.instance.getNetwork({ - user: user.bridgeUser, - pass: user.userId, - }); - const environment = new Environment({ - bridgeUser: user.bridgeUser, - bridgePass: user.userId, - bridgeUrl: ConfigService.instance.get('NETWORK_URL'), - encryptionKey: user.mnemonic, - appDetails: SdkManager.getAppDetails(), - }); - const networkFacade = new NetworkFacade( - networkModule, - environment, - DownloadService.instance, - CryptoService.instance, - ); - CLIUtils.done(jsonFlag); - - return networkFacade; - }; } diff --git a/src/commands/upload-file.ts b/src/commands/upload-file.ts index 995e6402..1ed07569 100644 --- a/src/commands/upload-file.ts +++ b/src/commands/upload-file.ts @@ -1,15 +1,11 @@ import { Command, Flags } from '@oclif/core'; import { stat } from 'node:fs/promises'; import { createReadStream } from 'node:fs'; -import { NetworkFacade } from '../services/network/network-facade.service'; -import { SdkManager } from '../services/sdk-manager.service'; import { AuthService } from '../services/auth.service'; import { CLIUtils } from '../utils/cli.utils'; import { ConfigService } from '../services/config.service'; import path from 'node:path'; import { DriveFileService } from '../services/drive/drive-file.service'; -import { CryptoService } from '../services/crypto.service'; -import { DownloadService } from '../services/network/download.service'; import { ErrorUtils } from '../utils/errors.utils'; import { NotValidDirectoryError } from '../types/command.types'; import { ValidationService } from '../services/validation.service'; @@ -18,7 +14,6 @@ import { ThumbnailService } from '../services/thumbnail.service'; import { BufferStream } from '../utils/stream.utils'; import { isFileThumbnailable } from '../utils/thumbnail.utils'; import { Readable } from 'node:stream'; -import { Environment } from '@internxt/inxt-js'; export default class UploadFile extends Command { static readonly args = {}; @@ -68,26 +63,7 @@ export default class UploadFile extends Command { })) ?? user.rootFolderId; // 1. Prepare the network - CLIUtils.doing('Preparing Network', flags['json']); - const networkModule = SdkManager.instance.getNetwork({ - user: user.bridgeUser, - pass: user.userId, - }); - const environment = new Environment({ - bridgeUser: user.bridgeUser, - bridgePass: user.userId, - bridgeUrl: ConfigService.instance.get('NETWORK_URL'), - encryptionKey: user.mnemonic, - appDetails: SdkManager.getAppDetails(), - }); - const networkFacade = new NetworkFacade( - networkModule, - environment, - DownloadService.instance, - CryptoService.instance, - ); - - CLIUtils.done(flags['json']); + const networkFacade = await CLIUtils.prepareNetwork({ loginUserDetails: user, jsonFlag: flags['json'] }); // 2. Upload file to the Network const readStream = createReadStream(filePath); diff --git a/src/utils/cli.utils.ts b/src/utils/cli.utils.ts index cc18d9d4..c61a1f21 100644 --- a/src/utils/cli.utils.ts +++ b/src/utils/cli.utils.ts @@ -1,10 +1,16 @@ import { ux, Flags } from '@oclif/core'; import cliProgress from 'cli-progress'; import Table, { Header } from 'tty-table'; -import { NotValidFolderUuidError, PromptOptions } from '../types/command.types'; +import { LoginUserDetails, NotValidFolderUuidError, PromptOptions } from '../types/command.types'; import { InquirerUtils } from './inquirer.utils'; import { ErrorUtils } from './errors.utils'; import { ValidationService } from '../services/validation.service'; +import { SdkManager } from '../services/sdk-manager.service'; +import { Environment } from '@internxt/inxt-js'; +import { ConfigService } from '../services/config.service'; +import { NetworkFacade } from '../services/network/network-facade.service'; +import { DownloadService } from '../services/network/download.service'; +import { CryptoService } from '../services/crypto.service'; export class CLIUtils { static readonly clearPreviousLine = (jsonFlag?: boolean) => { @@ -238,6 +244,35 @@ export class CLIUtils { }; static readonly parseEmpty = async (input: string) => (input.trim().length === 0 ? ' ' : input); + static readonly prepareNetwork = ({ + jsonFlag, + loginUserDetails, + }: { + jsonFlag?: boolean; + loginUserDetails: LoginUserDetails; + }) => { + CLIUtils.doing('Preparing Network', jsonFlag); + const networkModule = SdkManager.instance.getNetwork({ + user: loginUserDetails.bridgeUser, + pass: loginUserDetails.userId, + }); + const environment = new Environment({ + bridgeUser: loginUserDetails.bridgeUser, + bridgePass: loginUserDetails.userId, + bridgeUrl: ConfigService.instance.get('NETWORK_URL'), + encryptionKey: loginUserDetails.mnemonic, + appDetails: SdkManager.getAppDetails(), + }); + const networkFacade = new NetworkFacade( + networkModule, + environment, + DownloadService.instance, + CryptoService.instance, + ); + + CLIUtils.done(jsonFlag); + return networkFacade; + }; } export class NoFlagProvidedError extends Error { diff --git a/test/utils/cli.utils.test.ts b/test/utils/cli.utils.test.ts index 6f73d2da..99bb590d 100644 --- a/test/utils/cli.utils.test.ts +++ b/test/utils/cli.utils.test.ts @@ -3,6 +3,11 @@ import { ux } from '@oclif/core'; import { CLIUtils } from '../../src/utils/cli.utils'; import { Direction } from 'node:readline'; import { Options } from '@oclif/core/lib/ux/action/types'; +import { LoginUserDetails } from '../../src/types/command.types'; +import { SdkManager } from '../../src/services/sdk-manager.service'; +import { ConfigService } from '../../src/services/config.service'; +import { NetworkFacade } from '../../src/services/network/network-facade.service'; +import { Environment } from '@internxt/inxt-js'; vi.mock('ux', () => { return { @@ -15,6 +20,31 @@ vi.mock('ux', () => { }; }); +vi.mock('../../src/services/sdk-manager.service', () => ({ + SdkManager: { + instance: { + getNetwork: vi.fn(), + }, + getAppDetails: vi.fn(), + }, +})); + +vi.mock('../../src/services/config.service', () => ({ + ConfigService: { + instance: { + get: vi.fn(), + }, + }, +})); + +vi.mock('@internxt/inxt-js', () => ({ + Environment: vi.fn(), +})); + +vi.mock('../../src/services/network/network-facade.service', () => ({ + NetworkFacade: vi.fn(), +})); + describe('CliUtils', () => { let stdoutWrite: MockInstance<{ (buffer: Uint8Array | string, cb?: (err?: Error) => void): boolean; @@ -23,6 +53,17 @@ describe('CliUtils', () => { let stdoutClear: MockInstance<(dir: Direction, callback?: () => void) => boolean>; let reporter: (message: string) => void; + const BRIDGE_URL = 'https://test.com'; + let mockNetworkFacade: NetworkFacade; + const mockLoginUserDetails = { + bridgeUser: 'test-bridge-user', + userId: 'test-user-id', + mnemonic: 'test-mnemonic', + } as LoginUserDetails; + + const mockNetworkModule = {} as ReturnType; + const mockAppDetails = {} as ReturnType; + beforeEach(() => { vi.clearAllMocks(); process.stdout.write = vi.fn(); @@ -31,6 +72,17 @@ describe('CliUtils', () => { stdoutClear = vi.spyOn(process.stdout, 'clearLine').mockImplementation(() => true); reporter = vi.fn(); + + mockNetworkFacade = {} as NetworkFacade; + vi.mocked(NetworkFacade).mockImplementation(function (this: NetworkFacade) { + return mockNetworkFacade; + }); + vi.mocked(Environment).mockImplementation(function (this: Environment) { + return {} as Environment; + }); + vi.mocked(SdkManager.instance.getNetwork).mockReturnValue(mockNetworkModule); + vi.mocked(SdkManager.getAppDetails).mockReturnValue(mockAppDetails); + vi.mocked(ConfigService.instance.get).mockReturnValue(BRIDGE_URL); }); afterEach(() => { @@ -145,4 +197,34 @@ describe('CliUtils', () => { expect(ux.action.stop).not.toHaveBeenCalled(); }); }); + describe('prepareNetwork', () => { + it('should properly create a networkFacade instance and return it', () => { + const result = CLIUtils.prepareNetwork({ loginUserDetails: mockLoginUserDetails }); + + expect(result).toBe(mockNetworkFacade); + expect(SdkManager.instance.getNetwork).toHaveBeenCalledWith({ + user: mockLoginUserDetails.bridgeUser, + pass: mockLoginUserDetails.userId, + }); + expect(Environment).toHaveBeenCalledWith({ + bridgeUser: mockLoginUserDetails.bridgeUser, + bridgePass: mockLoginUserDetails.userId, + bridgeUrl: BRIDGE_URL, + encryptionKey: mockLoginUserDetails.mnemonic, + appDetails: mockAppDetails, + }); + expect(NetworkFacade).toHaveBeenCalledTimes(1); + }); + + it('should properly output to the terminal the prepare network step', () => { + const jsonFlag = true; + const doingSpy = vi.spyOn(CLIUtils, 'doing'); + const doneSpy = vi.spyOn(CLIUtils, 'done'); + + CLIUtils.prepareNetwork({ jsonFlag, loginUserDetails: mockLoginUserDetails }); + + expect(doingSpy).toHaveBeenCalledWith('Preparing Network', jsonFlag); + expect(doneSpy).toHaveBeenCalledWith(jsonFlag); + }); + }); });