'use strict';
/**
* ### GTFS Data Update Checker
*
* This module runs the agency update checks. The agencies to check are set
* in the build options and are returned from the {@link module:helpers/options|options}
* module. Depending on the Agency settings, this will either run the default
* update function or the agency-specific update function.
*
* If the agency has a post-update script defined, this will be run after the
* agency update script is complete, regardless if an update is requested.
* @module update
*/
const fs = require('fs');
const path = require('path');
const config = require('../../config.json');
const errors = require('../helpers/errors.js');
const log = require('../helpers/log.js');
const options = require('../helpers/options.js');
const defaultUpdate = require('./default.js');
/**
* Final callback to return to the run script
* @type {runCallback}
* @private
*/
let FINAL_CALLBACK = function() {};
// Agency counter
let AGENCY = 0;
/**
* Start the database update check process. This will check for a GTFS data
* update for all agencies specified in the Database Build Options ({@link Options}).
* If an update is present, the new data will be downloaded and unpacked into
* the agency's GTFS directory.
* @param {runCallback} callback Final callback when the update process is complete.
*/
function update(callback) {
log.info("RUNNING AGENCY UPDATE CHECKS");
log("------------------------------------------------");
// Set final callback
FINAL_CALLBACK = callback;
// Start the first agency
_startNextAgency();
}
/**
* Function to call when starting the next agency in the list. It will
* start with an update check and then continue as necessary.
* @private
*/
function _startNextAgency() {
let agencyOptions = options.agency(AGENCY);
// Get the agency options
log.raw([
{
"text": "AGENCY:"
},
{
"text": " " + agencyOptions.agency.id + " ",
"chalk": "bgYellow.black"
}
]);
// Path to agency-specific update script
let agencyUpdateScript = path.normalize(agencyOptions.agency.moduleDirectory + '/' + config.locations.scripts.update);
// If agency-specific update script exists, use that to update...
if ( fs.existsSync(agencyUpdateScript) ) {
log("--> Using custom update script...");
// Try to load the agency update script
try {
let update = require(agencyUpdateScript);
update(agencyOptions, log, errors, _agencyUpdateComplete);
}
catch(err) {
let msg = "Could not run agency update script";
log.error("ERROR: " + msg);
errors.error(msg, err.message, agencyOptions.agency.id);
_agencyUpdateComplete(false, false);
}
}
// Use default update script
else {
log("--> Using default update script...");
defaultUpdate(agencyOptions, _agencyUpdateComplete);
}
}
/**
* Function to call when an agency is finished with the update check
* @param {boolean} requested Update requested flag
* @param {boolean} successful Update successful flag
* @param {string} [published] GTFS Published Date/Time (if not provided, use
* value in the default the published file)
* @param {string} [notes] Agency update notes (does not override notes
* provided as a command line option)
* @type {updateCallback}
* @private
*/
function _agencyUpdateComplete(requested, successful, published, notes) {
// Set agency option properties
options.agency(AGENCY).update = requested;
options.agency(AGENCY).updateComplete = successful;
options.agency(AGENCY).published = published !== undefined ? published :
new Date(
fs.readFileSync(
path.normalize(
options.agency(AGENCY).agency.moduleDirectory + '/' + config.locations.files.published
)
).toString()
);
// Set notes, if not provided
if ( !options.agency(AGENCY).notes && notes ) {
options.agency(AGENCY).notes = notes;
}
else if ( !options.agency(AGENCY).notes ) {
let d = new Date().toLocaleString();
options.agency(AGENCY).notes = "This schedule database was automatically compiled on " + d + " due to a schedule data update from " + options.agency(AGENCY).agency.name + ".";
}
let details = {};
if ( requested && successful ) {
options.agency(AGENCY).compile = true;
details = {
"text": " YES ",
"chalk": "bgGreen.black.bold"
};
}
else if ( requested && !successful ) {
details = {
"text": " UNSUCCESSFUL ",
"chalk": "bgRed.white.bold"
};
errors.error("Agency Update Check Unsuccessful", undefined, options.agency(AGENCY).agency.id);
}
else {
details = {
"text": " No Update ",
"chalk": "bgWhite.black.bold"
};
}
// Log update status
log.raw([
{
"text": "--> GTFS Data Update:"
},
details
]);
// Check for a post-update script
_agencyPostUpdate();
}
/**
* Run the agency post-update script, if present
* @private
*/
function _agencyPostUpdate() {
let postUpdateScript = path.normalize(options.agency(AGENCY).agency.moduleDirectory + '/' + config.locations.scripts.postUpdate);
// post update script exists
if ( fs.existsSync(postUpdateScript) ) {
log("--> Running agency post-update script...");
let postUpdate = require(postUpdateScript);
postUpdate(options.agency(AGENCY), log, errors, _agencyComplete);
}
// no post update script
else {
_agencyComplete();
}
}
/**
* Function to call when an agency is completely finished
* with the update check and database compilation, if necessary
* @private
*/
function _agencyComplete() {
AGENCY++;
// Continue with the next agency if there are more
if ( AGENCY < options.agencyCount() ) {
log("------------------------------------------------");
_startNextAgency();
}
// All agencies are complete
else {
_finish();
}
}
/**
* Callback function for when all agencies have run update checks
* @private
*/
function _finish() {
FINAL_CALLBACK();
}
module.exports = update;