kiwix-js-pwa/www/js/lib/updater.js
2023-09-01 08:56:51 +01:00

112 lines
4.5 KiB
JavaScript

/**
* updater.js : Functions for checking and initiating app updates
*
* Copyright 2013-2023 Jaifroid and contributors
* License GPL v3:
*
* This file is part of Kiwix.
*
* Kiwix is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Kiwix is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
*/
'use strict';
/* global params */
import uiUtil from './uiUtil.js';
/**
* The update server configuration
*/
params.updateServer = {
url: 'https://api.github.com/repos/kiwix/kiwix-js-windows/',
releases: 'releases'
};
// A RegExp prototype string to match the current app's releases
const baseApp = (params.packagedFile && /wikivoyage/.test(params.packagedFile)) ? 'wikivoyage'
: (params.packagedFile && /wikmed|mdwiki/.test(params.packagedFile)) ? 'wikimed'
: 'windows|electron|kiwixwebapp_'; // Default value
// A RegExp to match download URLs of releases
const regexpMatchGitHubReleases = RegExp('"browser_download_url[":\\s]+"(https:.*download\\/([^\\/]+).*(?:' + baseApp + ')[^"]+)"', 'ig');
/**
* Get and return the JSON list of releases from the update server's REST API
*
* @param {Function} callback The function to call with the data
* @returns {String} A JSON string containing hierarchical release data
*/
function getReleasesObject (callback) {
uiUtil.XHR(params.updateServer.url + params.updateServer.releases, 'text',
function (response, mimetype, status) {
if (status === 200) {
callback(response);
} else callback('');
}
);
}
/**
* A function to get the latest updates from a GitHub releases source
* Only updates that are greater than the current update are returned
* Attempts to match by channel, but also matches non-channel releases
*
* @param {Function} callback A function to call back with the results
* @returns {Object} Calls back with update tag, update URL, and array of releases
*/
function getLatestUpdates (callback) {
var updatedReleases = [];
var currentRelease = params.appVersion.replace(/^v?([\d.]+)/, '$1');
var currentReleaseChannel = params.appVersion.replace(/^[v\d.]+/, '');
var updateTag;
var channelMatchedTag;
var updateUrl;
var channelMatchedUpdateUrl;
getReleasesObject(function (releases) {
var releaseFile;
var releaseVersion;
var releaseChannel;
// Loop through every line in releases
var matchedRelease = regexpMatchGitHubReleases.exec(releases);
while (matchedRelease != null) {
releaseFile = matchedRelease[1];
releaseVersion = matchedRelease[2].replace(/^v?([\d.]+).*/, '$1');
releaseChannel = matchedRelease[2].replace(/^[v\d.]+/, '');
// Compare the releases using a version-type comparison
if (releaseVersion.localeCompare(currentRelease, { numeric: true, sensitivity: 'base' }) === 1) {
if (!channelMatchedTag && currentReleaseChannel === releaseChannel) {
channelMatchedTag = matchedRelease[2];
channelMatchedUpdateUrl = releaseFile.replace(/\/download\//, '/tag/').replace(/[^/]+$/, '');
}
if (!updateTag) updateTag = matchedRelease[2];
if (!updateUrl) updateUrl = releaseFile.replace(/\/download\//, '/tag/').replace(/[^/]+$/, '');
updatedReleases.push(releaseFile)
}
matchedRelease = regexpMatchGitHubReleases.exec(releases);
}
// We should now have a list of all candidate updates, and candidate channel update
// Compare the channel-matched update wiht the update, and if they are same underlying version number, choose channel match
if (updateTag && updateTag.replace(/^v?([\d.]+).*/, '$1') === channelMatchedTag.replace(/^v?([\d.]+).*/, '$1')) {
updateTag = channelMatchedTag;
updateUrl = channelMatchedUpdateUrl;
}
callback(updateTag, updateUrl, updatedReleases);
});
}
export default {
getLatestUpdates: getLatestUpdates
};