Skip to content

Commit

Permalink
fix: only one cli print at the same time
Browse files Browse the repository at this point in the history
  • Loading branch information
ido-pluto committed Mar 13, 2024
1 parent 2c606e8 commit 0371537
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 90 deletions.
2 changes: 2 additions & 0 deletions src/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import FetchStreamError from "./download/download-engine/streams/download-engine
import IpullError from "./errors/ipull-error.js";
import EngineError from "./download/download-engine/engine/error/engine-error.js";
import {FormattedStatus} from "./download/transfer-visualize/format-transfer-status.js";
import DownloadEngineMultiDownload from "./download/download-engine/engine/download-engine-multi-download.js";

export {
downloadFileBrowser,
Expand All @@ -25,6 +26,7 @@ export {
export type {
DownloadFileBrowserOptions,
DownloadEngineBrowser,
DownloadEngineMultiDownload,
FormattedStatus,
SaveProgressInfo
};
5 changes: 2 additions & 3 deletions src/download/browser-download.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DownloadEngineBrowser, {DownloadEngineOptionsBrowser} from "./download-engine/engine/download-engine-browser.js";
import DownloadEngineMultiDownload from "./download-engine/engine/download-engine-multi-download.js";

export const DEFAULT_PARALLEL_STREAMS_FOR_BROWSER = 3;
const DEFAULT_PARALLEL_STREAMS_FOR_BROWSER = 3;

export type DownloadFileBrowserOptions = DownloadEngineOptionsBrowser;

Expand All @@ -17,6 +17,5 @@ export async function downloadFileBrowser(options: DownloadFileBrowserOptions) {
* Download multiple files in the browser environment.
*/
export async function downloadSequenceBrowser(...downloads: (DownloadEngineBrowser | Promise<DownloadEngineBrowser>)[]) {
const allDownloads = await Promise.all(downloads);
return new DownloadEngineMultiDownload(allDownloads);
return await DownloadEngineMultiDownload.fromEngines(downloads);
}
4 changes: 4 additions & 0 deletions src/download/download-engine/engine/base-download-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export default class BaseDownloadEngine extends EventEmitter<BaseDownloadEngineE
return this._latestStatus ?? createFormattedStatus(this._engine.status);
}

public get downloadStatues() {
return [this.status];
}

/**
* @internal
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default class DownloadEngineMultiDownload<Engine extends DownloadEngineMu
protected _closeFiles: (() => Promise<void>)[] = [];


public constructor(engines: (DownloadEngineMultiAllowedEngines | DownloadEngineMultiDownload)[]) {
protected constructor(engines: (DownloadEngineMultiAllowedEngines | DownloadEngineMultiDownload)[]) {
super();
this._engines = DownloadEngineMultiDownload._extractEngines(engines);
this._init();
Expand Down Expand Up @@ -114,4 +114,8 @@ export default class DownloadEngineMultiDownload<Engine extends DownloadEngineMu
})
.flat();
}

public static async fromEngines<Engine extends DownloadEngineMultiAllowedEngines>(engines: (Engine | Promise<Engine>)[]) {
return new DownloadEngineMultiDownload(await Promise.all(engines));
}
}
90 changes: 12 additions & 78 deletions src/download/node-download.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,23 @@
import DownloadEngineNodejs, {DownloadEngineOptionsNodejs} from "./download-engine/engine/download-engine-nodejs.js";
import BaseDownloadEngine from "./download-engine/engine/base-download-engine.js";
import DownloadEngineMultiDownload from "./download-engine/engine/download-engine-multi-download.js";
import TransferCli, {TransferCliOptions} from "./transfer-visualize/transfer-cli/transfer-cli.js";
import switchCliProgressStyle, {AvailableCLIProgressStyle} from "./transfer-visualize/transfer-cli/progress-bars/switch-cli-progress-style.js";
import {CliFormattedStatus} from "./transfer-visualize/transfer-cli/progress-bars/base-transfer-cli-progress-bar.js";

export const DEFAULT_PARALLEL_STREAMS_FOR_NODEJS = 3;
export const DEFAULT_CLI_STYLE: AvailableCLIProgressStyle = "fancy";

export type CliProgressDownloadEngineOptions = {
truncateName?: boolean | number;
cliProgress?: boolean;
cliStyle?: AvailableCLIProgressStyle | ((status: CliFormattedStatus) => string)
cliName?: string;
cliAction?: string;
};
import CliAnimationWrapper, {CliProgressDownloadEngineOptions} from "./transfer-visualize/transfer-cli/cli-animation-wrapper.js";
import {CLI_LEVEL} from "./transfer-visualize/transfer-cli/transfer-cli.js";

const DEFAULT_PARALLEL_STREAMS_FOR_NODEJS = 3;
export type DownloadFileOptions = DownloadEngineOptionsNodejs & CliProgressDownloadEngineOptions;

function createCliProgressForDownloadEngine(options: CliProgressDownloadEngineOptions) {
const cliOptions: Partial<TransferCliOptions> = {...options};

if (options.cliAction) {
cliOptions.action = options.cliAction;
}
if (options.cliName) {
cliOptions.name = options.cliName;
}

cliOptions.createProgressBar = typeof options.cliStyle === "function" ?
options.cliStyle :
switchCliProgressStyle(options.cliStyle ?? DEFAULT_CLI_STYLE, {truncateName: options.truncateName});

return new TransferCli(cliOptions);
}

/**
* Download one file with CLI progress
*/
export async function downloadFile(options: DownloadFileOptions) {
let cli: TransferCli | undefined;
if (options.cliProgress) {
options.cliAction ??= options.fetchStrategy === "localFile" ? "Copying" : "Downloading";

cli = createCliProgressForDownloadEngine(options);
cli.startLoading();
}
options.parallelStreams ??= DEFAULT_PARALLEL_STREAMS_FOR_NODEJS;

const downloader = DownloadEngineNodejs.createFromOptions(options);
const wrapper = new CliAnimationWrapper(downloader, options);

const downloader = await DownloadEngineNodejs.createFromOptions(options);

if (cli) {
cli.start();
downloader.on("progress", () => {
cli?.updateStatues([downloader.status]);
});

downloader.on("closed", () => {
cli?.stop();
});
}


return downloader;
await wrapper.attachAnimation();
return await downloader;
}

export type DownloadSequenceOptions = CliProgressDownloadEngineOptions & {
Expand All @@ -81,30 +35,10 @@ export async function downloadSequence(options: DownloadSequenceOptions | Downlo
downloadOptions = options;
}

let cli: TransferCli | undefined;
if (downloadOptions.cliProgress) {
if (downloadOptions.fetchStrategy) {
downloadOptions.cliAction ??= downloadOptions.fetchStrategy === "localFile" ? "Copying" : "Downloading";
}

cli = createCliProgressForDownloadEngine(downloadOptions);
cli.startLoading();

}

const allDownloads = await Promise.all(downloads);
const oneDownloader = new DownloadEngineMultiDownload(allDownloads);

if (cli) {
cli.start();
oneDownloader.on("progress", () => {
cli?.updateStatues(oneDownloader.downloadStatues);
});

oneDownloader.on("closed", () => {
cli?.stop();
});
}
downloadOptions.cliLevel = CLI_LEVEL.HIGH;
const downloader = DownloadEngineMultiDownload.fromEngines(downloads);
const wrapper = new CliAnimationWrapper(downloader, downloadOptions);

return oneDownloader;
await wrapper.attachAnimation();
return await downloader;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import DownloadEngineNodejs from "../../download-engine/engine/download-engine-nodejs.js";
import DownloadEngineMultiDownload from "../../download-engine/engine/download-engine-multi-download.js";
import switchCliProgressStyle, {AvailableCLIProgressStyle} from "./progress-bars/switch-cli-progress-style.js";
import {CliFormattedStatus} from "./progress-bars/base-transfer-cli-progress-bar.js";
import TransferCli, {CLI_LEVEL, TransferCliOptions} from "./transfer-cli.js";

const DEFAULT_CLI_STYLE: AvailableCLIProgressStyle = "fancy";
type AllowedDownloadEngines = DownloadEngineNodejs | DownloadEngineMultiDownload;

export type CliProgressDownloadEngineOptions = {
truncateName?: boolean | number;
cliProgress?: boolean;
cliStyle?: AvailableCLIProgressStyle | ((status: CliFormattedStatus) => string)
cliName?: string;
cliAction?: string;
fetchStrategy?: "localFile" | "fetch";
/** @internal */
cliLevel?: CLI_LEVEL;
};

export default class CliAnimationWrapper {
private readonly _downloadEngine: Promise<AllowedDownloadEngines>;
private readonly _options: CliProgressDownloadEngineOptions;
private _activeCLI?: TransferCli;

public constructor(downloadEngine: Promise<AllowedDownloadEngines>, _options: CliProgressDownloadEngineOptions) {
this._options = _options;
this._downloadEngine = downloadEngine;
this._init();
}

private _init() {
if (!this._options.cliProgress) {
return;
}
this._options.cliAction ??= this._options.fetchStrategy === "localFile" ? "Copying" : "Downloading";

const cliOptions: Partial<TransferCliOptions> = {...this._options};
if (this._options.cliAction) {
cliOptions.action = this._options.cliAction;
}
if (this._options.cliName) {
cliOptions.name = this._options.cliName;
}

cliOptions.createProgressBar = typeof this._options.cliStyle === "function" ?
this._options.cliStyle :
switchCliProgressStyle(this._options.cliStyle ?? DEFAULT_CLI_STYLE, {truncateName: this._options.truncateName});

this._activeCLI = new TransferCli(cliOptions, this._options.cliLevel);
}

public async attachAnimation() {
if (!this._activeCLI) {
return;
}
this._activeCLI.loadingAnimation.start();
const engine = await this._downloadEngine;
this._activeCLI.loadingAnimation.stop();

engine.once("start", () => {
this._activeCLI?.start();

engine.on("progress", () => {
this._activeCLI?.updateStatues(engine.downloadStatues);
});

engine.on("closed", () => {
this._activeCLI?.stop();
});
});
}
}
22 changes: 14 additions & 8 deletions src/download/transfer-visualize/transfer-cli/transfer-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,21 @@ export const DEFAULT_TRANSFER_CLI_OPTIONS: TransferCliOptions = {
loadingText: "Gathering information"
};

export enum CLI_LEVEL {
LOW = 0,
HIGH = 2
}


export default class TransferCli {
protected readonly loadingAnimation: CliSpinnersLoadingAnimation;
public static activeCLILevel = CLI_LEVEL.LOW;
public readonly loadingAnimation: CliSpinnersLoadingAnimation;
protected options: TransferCliOptions;
protected stdoutManager = UpdateManager.getInstance();
protected myCLILevel: number;

public constructor(options: Partial<TransferCliOptions>) {
public constructor(options: Partial<TransferCliOptions>, myCLILevel = CLI_LEVEL.LOW) {
TransferCli.activeCLILevel = this.myCLILevel = myCLILevel;
this.options = {...DEFAULT_TRANSFER_CLI_OPTIONS, ...options};

this.updateStatues = debounce(this.updateStatues.bind(this), this.options.debounceWait, {
Expand All @@ -45,23 +53,21 @@ export default class TransferCli {
this.stop = this.stop.bind(this);
}

startLoading() {
this.loadingAnimation.start();
}

start() {
this.loadingAnimation.stop();
this.stdoutManager.hook();
process.on("exit", this.stop);
}

stop() {
this.stdoutManager.erase();
this.stdoutManager.unhook(false);
process.off("exit", this.stop);
}

public updateStatues(statues: FormattedStatus[]) {
if (this.myCLILevel !== TransferCli.activeCLILevel) {
return; // Do not update if there is a higher level CLI, meaning that this CLI is sub-CLI
}

const newLog = statues.map((status) => {
status.transferAction = this.options.action ?? status.transferAction;
return this.options.createProgressBar(status);
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import FetchStreamError from "./download/download-engine/streams/download-engine
import IpullError from "./errors/ipull-error.js";
import EngineError from "./download/download-engine/engine/error/engine-error.js";
import {FormattedStatus} from "./download/transfer-visualize/format-transfer-status.js";
import DownloadEngineMultiDownload from "./download/download-engine/engine/download-engine-multi-download.js";

export {
downloadFile,
Expand All @@ -28,6 +29,7 @@ export type {
DownloadFileOptions,
DownloadSequenceOptions,
DownloadEngineNodejs,
DownloadEngineMultiDownload,
SaveProgressInfo,
FormattedStatus
};
Expand Down

0 comments on commit 0371537

Please sign in to comment.