electron-dl-manager
Version:
A library for implementing file downloads in Electron with 'save as' dialog and id support.
521 lines (519 loc) • 16.2 kB
text/typescript
import { BrowserWindow, DownloadItem, Event, SaveDialogOptions, WebContents } from "electron";
//#region src/DownloadData.d.ts
interface RestoreDownloadData {
/**
* Download id
*/
id: string;
url: string;
/**
* The path and filename where the download will be saved.
*/
fileSaveAsPath: string;
urlChain: string[];
mimeType: string;
/**
* The ETag of the download, if available.
* This is used to resume downloads.
*/
eTag: string;
receivedBytes: number;
totalBytes: number;
startTime: number;
percentCompleted: number;
/**
* If persistOnAppClose is true, this is the path where the download
* is persisted to. This is used to restore the download later.
*/
persistedFilePath?: string;
}
interface DownloadDataConfig {
/**
* Download id
*/
id?: string;
}
/**
* Contains the data for a download.
*/
declare class DownloadData {
/**
* Generated id for the download
*/
id: string;
/**
* The Electron.DownloadItem. Use this to grab the filename, path, etc.
* @see https://www.electronjs.org/docs/latest/api/download-item
*/
item: DownloadItem;
/**
* The Electron.WebContents
* @see https://www.electronjs.org/docs/latest/api/web-contents
*/
webContents: WebContents;
/**
* The Electron.Event
* @see https://www.electronjs.org/docs/latest/api/event
*/
event: Event;
/**
* The name of the file that is being saved to the user's computer.
* Recommended over Item.getFilename() as it may be inaccurate when using the save as dialog.
*/
resolvedFilename: string;
/**
* If true, the download was cancelled from the save as dialog. This flag
* will also be true if the download was cancelled by the application when
* using the save as dialog.
*/
cancelledFromSaveAsDialog?: boolean;
/**
* The percentage of the download that has been completed
*/
percentCompleted: number;
/**
* The download rate in bytes per second.
*/
downloadRateBytesPerSecond: number;
/**
* The estimated time remaining in seconds.
*/
estimatedTimeRemainingSeconds: number;
/**
* If the download was interrupted, the state in which it was interrupted from
*/
interruptedVia?: "in-progress" | "completed";
/**
* If defined, this is the path where the download is persisted to.
*/
persistedFilePath?: string;
constructor(config?: DownloadDataConfig);
/**
* Returns data necessary for restoring a download
*/
getRestoreDownloadData(): RestoreDownloadData;
isDownloadInProgress(): boolean;
isDownloadCompleted(): boolean;
isDownloadCancelled(): boolean;
isDownloadInterrupted(): boolean;
isDownloadResumable(): boolean;
isDownloadPaused(): boolean;
}
//#endregion
//#region src/types.d.ts
/**
* The download has started
*/
type DownloadStartedFn = (data: DownloadData) => Promise<void> | void;
/**
* There is progress on the download
*/
type DownloadProgressFn = (data: DownloadData) => Promise<void> | void;
/**
* The download has been cancelled
*/
type DownloadCancelledFn = (data: DownloadData) => Promise<void> | void;
/**
* The download has completed
*/
type DownloadCompletedFn = (data: DownloadData) => Promise<void> | void;
/**
* The download was interrupted
*/
type DownloadInterruptedFn = (data: DownloadData) => Promise<void> | void;
/**
* The download has been persisted for later restoration
*/
type DownloadPersistedFn = (data: DownloadData, restoreDownloadData: RestoreDownloadData) => Promise<void> | void;
/**
* The download has failed
*/
type ErrorFn = (error: Error, data?: DownloadData) => Promise<void> | void;
/**
* Function for logging internal debug messages
*/
type DebugLoggerFn = (message: string) => void;
interface DownloadManagerConstructorParams {
/**
* If defined, will log out internal debug messages. Useful for
* troubleshooting downloads. Does not log out progress due to
* how frequent it can be.
*/
debugLogger?: DebugLoggerFn;
}
interface DownloadManagerCallbacks {
/**
* When the download has started. When using a "save as" dialog,
* this will be called after the user has selected a location.
*
* This will always be called first before the progress and completed events.
*/
onDownloadStarted?: DownloadStartedFn;
/**
* When there is a progress update on a download. Note: This
* may be skipped entirely in some cases, where the download
* completes immediately. In that case, onDownloadCompleted
* will be called instead.
*/
onDownloadProgress?: DownloadProgressFn;
/**
* When the download has completed
*/
onDownloadCompleted?: DownloadCompletedFn;
/**
* When the download has been cancelled. Also called if the user cancels
* from the save as dialog.
*/
onDownloadCancelled?: DownloadCancelledFn;
/**
* When the download has been interrupted. This could be due to a bad
* connection, the server going down, etc.
*/
onDownloadInterrupted?: DownloadInterruptedFn;
/**
* When the download has been persisted for later restoration.
*/
onDownloadPersisted?: DownloadPersistedFn;
/**
* When an error has been encountered.
* Note: The signature is (error, <maybe some data>).
*/
onError?: ErrorFn;
}
interface RestoreDownloadConfig {
/**
* The Electron.App instance
*/
app: Electron.App;
/**
* The Electron.BrowserWindow instance
*/
window: BrowserWindow;
/**
* Data required for resuming the download
*/
restoreData: RestoreDownloadData;
/**
* The callbacks to define to listen for download events
*/
callbacks: DownloadManagerCallbacks;
/**
* Electron.DownloadURLOptions to pass to the downloadURL method
*
* @see https://www.electronjs.org/docs/latest/api/session#sesdownloadurlurl-options
*/
downloadURLOptions?: Electron.DownloadURLOptions;
}
interface DownloadConfig {
/**
* The Electron.App instance. Required if persistOnAppClose is enabled.
*/
app?: Electron.App;
/**
* The Electron.BrowserWindow instance
*/
window: BrowserWindow;
/**
* The URL to download
*/
url: string;
/**
* The callbacks to define to listen for download events
*/
callbacks: DownloadManagerCallbacks;
/**
* Electron.DownloadURLOptions to pass to the downloadURL method
*
* @see https://www.electronjs.org/docs/latest/api/session#sesdownloadurlurl-options
*/
downloadURLOptions?: Electron.DownloadURLOptions;
/**
* If defined, will show a save dialog when the user
* downloads a file.
*
* @see https://www.electronjs.org/docs/latest/api/dialog#dialogshowsavedialogbrowserwindow-options
*/
saveDialogOptions?: SaveDialogOptions;
/**
* The filename to save the file as. If not defined, the filename
* from the server will be used.
*
* Only applies if saveDialogOptions is not defined.
*/
saveAsFilename?: string;
/**
* The directory to save the file to. Must be an absolute path.
* @default The user's downloads directory
*/
directory?: string;
/**
* If true, will overwrite the file if it already exists
* @default false
*/
overwrite?: boolean;
/**
* Options for persisting a partial download when the application closes for use with restoring it later.
*/
persistOnAppClose?: boolean;
}
interface IElectronDownloadManager {
/**
* Starts a download. If saveDialogOptions has been defined in the config,
* the saveAs dialog will show up first.
*
* Returns the id of the download.
*
* This *must* be called with `await` or unintended behavior may occur.
*/
download(params: DownloadConfig): Promise<string>;
/**
* Cancels a download
*/
cancelDownload(id: string): void;
/**
* Pauses a download and returns the data necessary to restore it later
*/
pauseDownload(id: string): RestoreDownloadData | undefined;
/**
* Resumes a download
*/
resumeDownload(id: string): void;
/**
* Returns the number of active downloads
*/
getActiveDownloadCount(): number;
/**
* Returns the data for a download
*/
getDownloadData(id: string): DownloadData | undefined;
/**
* Restores a download that is not registered in the download manager.
* If it is already registered, calls resumeDownload() instead.
*
* Returns the id of the restored download.
*/
restoreDownload(params: RestoreDownloadConfig): Promise<string>;
}
//#endregion
//#region src/CallbackDispatcher.d.ts
/**
* Wraps around the callbacks to handle errors and logging
*/
declare class CallbackDispatcher {
protected logger: DebugLoggerFn;
callbacks: DownloadManagerCallbacks;
downloadDataId: string;
constructor(downloadDataId: string, callbacks: DownloadManagerCallbacks, logger: (message: string) => void);
protected log(message: string): void;
onDownloadStarted(downloadData: DownloadData): Promise<void>;
onDownloadCompleted(downloadData: DownloadData): Promise<void>;
onDownloadProgress(downloadData: DownloadData): Promise<void>;
onDownloadCancelled(downloadData: DownloadData): Promise<void>;
onDownloadInterrupted(downloadData: DownloadData): Promise<void>;
onDownloadPersisted(downloadData: DownloadData): Promise<void>;
handleError(error: Error, downloadData?: DownloadData): void;
}
//#endregion
//#region src/DownloadInitiator.d.ts
interface DownloadInitiatorConstructorParams {
/**
* The id for the download. If not provided, a random id will be generated.
*/
id?: string;
/**
* A debug logger function to log messages.
* If not provided, no logging will occur.
*/
debugLogger?: (message: string) => void;
/**
* Called when the download is cleaned up.
* This is called after the download has completed or been cancelled.
* @param id The download data
*/
onCleanup?: (id: DownloadData) => void;
/**
* Called when the download is initialized.
* This is called before any download events are fired.
* @param id The download data
*/
onDownloadInit?: (id: DownloadData) => void;
/**
* The user callbacks to define to listen for download events
*/
callbacks: DownloadManagerCallbacks;
}
interface WillOnDownloadParams {
/**
* If defined, will show a save dialog when the user
* downloads a file.
*
* @see https://www.electronjs.org/docs/latest/api/dialog#dialogshowsavedialogbrowserwindow-options
*/
saveDialogOptions?: SaveDialogOptions;
/**
* The filename to save the file as. If not defined, the filename
* from the server will be used.
*
* Only applies if saveDialogOptions is not defined.
*/
saveAsFilename?: string;
/**
* The directory to save the file to. Must be an absolute path.
* @default The user's downloads directory
*/
directory?: string;
/**
* If true, will overwrite the file if it already exists
* @default false
*/
overwrite?: boolean;
/**
* Data for restoring a download.
*/
restoreData?: RestoreDownloadData;
}
declare class DownloadInitiator {
protected logger: (message: string) => void;
/**
* When the download is initiated
*/
private onDownloadInit;
/**
* When cleanup is called
*/
private onCleanup;
/**
* The callback dispatcher for handling download events back to the user
*/
private callbackDispatcher;
/**
* The data for the download.
*/
private downloadData;
private config;
/**
* The handler for the DownloadItem's `updated` event.
*/
private onUpdateHandler?;
/**
* The handler for the DownloadItem's `done` event.
*/
private onDoneHandler?;
constructor(config: DownloadInitiatorConstructorParams);
protected log(message: string): void;
/**
* Returns the download id
*/
getDownloadId(): string;
/**
* Returns the current download data
*/
getDownloadData(): DownloadData;
/**
* Generates the handler that attaches to the session `will-download` event,
* which will execute the workflows for handling a download.
*/
generateOnWillDownload(downloadParams: WillOnDownloadParams): (event: Event, item: DownloadItem, webContents: WebContents) => Promise<void>;
/**
* Flow for handling a download that requires user interaction via a "Save as" dialog.
*/
protected initSaveAsInteractiveDownload(): void;
private augmentDownloadItem;
/**
* Flow for handling a download that doesn't require user interaction.
*/
protected initNonInteractiveDownload(isRestoring?: boolean): Promise<void>;
protected updateProgress(): void;
/**
* Generates the handler for hooking into the DownloadItem's `updated` event.
*/
protected generateItemOnUpdated(): (_event: Event, state: "progressing" | "interrupted") => Promise<void>;
/**
* Generates the handler for hooking into the DownloadItem's `done` event.
*/
protected generateItemOnDone(): (_event: Event, state: "completed" | "cancelled" | "interrupted") => Promise<void>;
protected cleanup(): void;
private getPersistDownloadFilename;
/**
* Persists the download to an alternative location.
* This is useful for saving the download state when the app is about to close.
* It copies the current download file to a new location with a `.download` extension.
* If the download is already completed or cancelled, it does nothing.
*/
persistDownload(): void;
/**
* Restores a download from a persisted state.
*/
restorePersistedDownload(restoreData: RestoreDownloadData): void;
}
//#endregion
//#region src/ElectronDownloadManager.d.ts
/**
* Enables handling downloads in Electron.
*/
declare class ElectronDownloadManager implements IElectronDownloadManager {
protected downloadData: Record<string, DownloadData>;
protected logger: DebugLoggerFn;
private downloadQueue;
constructor(params?: DownloadManagerConstructorParams);
protected log(message: string): void;
/**
* Returns the current download data
*/
getDownloadData(id: string): DownloadData;
/**
* Cancels a download
*/
cancelDownload(id: string): void;
/**
* Pauses a download and returns the data necessary
* to restore it later via restoreDownload() if the download exists.
*/
pauseDownload(id: string): RestoreDownloadData | undefined;
/**
* Resumes a download
*/
resumeDownload(id: string): void;
/**
* Returns the number of active downloads
*/
getActiveDownloadCount(): number;
/**
* Restores a download that is not registered in the download manager.
* If it is already registered, calls resumeDownload() instead.
*/
restoreDownload(params: RestoreDownloadConfig): Promise<string>;
/**
* Starts a download. If saveDialogOptions has been defined in the config,
* the saveAs dialog will show up first.
*
* Returns the id of the download.
*/
download(params: DownloadConfig): Promise<string>;
protected cleanup(data: DownloadData): void;
}
//#endregion
//#region src/ElectronDownloadManagerMock.d.ts
/**
* Mock version of ElectronDownloadManager
* that can be used for testing purposes
*/
declare class ElectronDownloadManagerMock implements IElectronDownloadManager {
download(_params: DownloadConfig): Promise<string>;
cancelDownload(_id: string): void;
pauseDownload(_id: string): RestoreDownloadData | undefined;
resumeDownload(_id: string): void;
getActiveDownloadCount(): number;
getDownloadData(id: string): DownloadData;
restoreDownload(_params: RestoreDownloadConfig): Promise<string>;
}
//#endregion
//#region src/utils.d.ts
declare function truncateUrl(url: string): string;
declare function generateRandomId(): string;
declare function getFilenameFromMime(name: string, mime: string): string;
/**
* Determines the initial file path for the download.
*/
//#endregion
export { CallbackDispatcher, DebugLoggerFn, DownloadCancelledFn, DownloadCompletedFn, DownloadConfig, DownloadData, DownloadDataConfig, DownloadInitiator, DownloadInterruptedFn, DownloadManagerCallbacks, DownloadManagerConstructorParams, DownloadPersistedFn, DownloadProgressFn, DownloadStartedFn, ElectronDownloadManager, ElectronDownloadManagerMock, ErrorFn, IElectronDownloadManager, RestoreDownloadConfig, RestoreDownloadData, generateRandomId, getFilenameFromMime, truncateUrl };