Source: electron/upgrader.js

// import local dependencies
import {checkForUpdates} from '../utils';
import {download} from '../utils/files'
import {Modules} from '../constants';
import {fs, path} from '../utils/contextuals'

const browserCheck = () => {
  if (typeof window !== undefined) {
    throw new Error('Forbidden reference of Upgrader in browser environment')
  }
}

/**
 * The Upgrader class controls the update process using the info passed down from the
 * parent application. It ensures that all the fs interactions occur that are necessary
 * to treat a local directory as an update stream for nuget packages.
 */
class Upgrader {
  constructor ({appDataPath, downloadPath}) {
    browserCheck()
    this._appData = path.resolve(appDataPath);
    this._dir = path.join(downloadPath || this._appData, 'upgrade');
    this._initialized = false;
    this._updateCache = {};
  }

  /**
   * Initialize the upgrader and ensure the appropriate file directories are accessible.
   * @private
   */
  _init () {
    if (!this._initialized) {
      try {
        // dynamic reference for browser compatibility
        fs.ensureDirSync(this._dir)
        this._initialized = true;
      } catch (err) {
        throw new Error(`Error initializing electron upgrader: ${err.message}`)
      }
    }
  }

  /**
   * Retrieve and cache the updates available for electron based on the
   * specified current version and environment.
   * @param currentVersion
   * @param environment
   * @returns {Promise<Object>}
   */
  async _getLatestUpdate ({currentVersion, environment}) {
    if (!this._updateCache[environment]) {
      this._updateCache[environment] = await checkForUpdates({
        module: Modules.ELECTRON,
        currentVersion,
        environment,
      });
    }
    return this._updateCache[environment];
  }

  /**
   * Returns true if the next electron update is a major version upgrade.
   * @param latestUpdate
   * @param currentVersion
   * @param environment
   * @returns {Promise<boolean>}
   */
  async shouldUpgrade ({latestUpdate, currentVersion, environment}) {
    this._init();
    const electronUpdate = latestUpdate || await this._getLatestUpdate({currentVersion, environment});
    return !!electronUpdate?.updateAvailable &&
      !!electronUpdate?.attributes?.isDependency &&
      electronUpdate?.latest?.nupkgUrl && electronUpdate?.latest?.releasesFile;
  }

  /**
   * Download the electron upgrade to the file system and prepare it for installation.
   * @param electronUpdate
   * @param onDownloadProgress
   * @returns {Promise<void>}
   */
  async prepareElectronUpgrade ({latestUpdate, currentVersion, environment, onDownloadProgress}) {
    this._init();
    // get the latest update (presumably cached at this point)
    const electronUpdate = latestUpdate || await this._getLatestUpdate({currentVersion, environment});

    if (!electronUpdate?.latest?.nupkgUrl || !electronUpdate?.latest.nupkgReleasesFileUrl) {
      throw new Error('Missing nupkgUrl or nupkgReleasesFileUrl properties on latest version entry');
    }

    // download the nuget package
    await download(electronUpdate.latest.nupkgUrl, path.join(this._dir, electronUpdate.latest.nupkgUrl.split('/').pop()), onDownloadProgress);

    // download the releases file
    await download(electronUpdate.latest.nupkgReleasesFileUrl, path.join(this._dir, electronUpdate.latest.nupkgReleasesFileUrl.split('/').pop()), onDownloadProgress);
  }

  /**
   * Get the path to use as the feed url for the electron autoUpdater module.
   * @returns {string}
   */
  getFeedURL () {
    return this._dir;
  }
}

export default Upgrader;