Source: index.js

/*
 * Automatically update nodejs program from npm/github
 */
const shell = require('shelljs')
const etc = require("etc")()
const path = require("path");
// const conf = require('node-etc');
const conf = require('../node-etc');

/**
 * Automatic Updates
 */

class automaticUpdates {
    /**
     * Update Interval
     */
    interval = 3600;

    /**
     * Source from which to update
     */
    source = 'npm'

    constructor() { }

    /**
     * Initialize automatic updates
     * @param {object} options - Options
     * @param {number} [options.interval = 3600] - Interval over which to check for updates.
     * @param {string} [options.source = npm] - The source from which to check for updates.
     */
    init(options) {
        options = Object.assign({ interval: 3600, source: 'npm' }, options);
        this.interval = options.interval
        this.source = options.source

        if (typeof this.interval !== 'number') throw Error(`Invalid interval type for ${this.interval}`)
        if (this.interval <= 0) throw Error(`Interval should be greater than 0`)
        if (!['github', 'npm'].includes(this.source)) {
            throw Error(`Invalid source ${this.source}`)
        }
        switch (this.source) {
            case 'npm':
                this.updateFromnpm();
                break;
            case 'github':
                this.updateFromGithub();
                break;
            default:
                throw Error(`Unrecognized source ${this.source}`)
        }
    }

    /** 
     * Update using git pull from github repo
     */
    async updateFromGithub() {
        let packageJsonDir = conf.packageJsonDir();
        let remoteExists = shell.exec(`cd ${packageJsonDir} && git remote -v`, { silent: true })
        if (remoteExists.stdout.length === 0 && remoteExists.stderr.length === 0) {
            remoteExists = false
        }
        if (!remoteExists) {
            throw Error(`${packageJsonDir} is not a github repo`)
        }

        const updateFromGithub = async () => {
            let key = await conf.parseYAML('system');
            key = key.sshKey
            if (!key) {
                throw Error(`ssh key is missing`)
            }
            let update = shell.exec(`cd ${packageJsonDir}  && GIT_SSH_COMMAND='ssh -i ${key} -o IdentitiesOnly=yes' git pull origin master`)
            update = update.stdout + update.stderr;
            if (!update.includes('Already up-to-date')) {
                shell.exec(`cd ${packageJsonDir}  && yarn install`);
            }
        }


        updateFromGithub();
        setInterval(() => {
            updateFromGithub();
            this.updateModules()
        }, this.interval * 1000)
    }

    /**
     * update from npm
     */
    async updateFromnpm() {

        const updateFromnpm = async () => {
            let packageJson = conf.packageJson();
            let installedVersion = conf.packageJson().version
            let installedVersionDotted = installedVersion
            installedVersion = installedVersion.replace(/\./g, '')
            try {
                let latestVersion = await shell.exec(`npm show ${packageJson.name} version`, { silent: true }).stdout.replace(/\n/, '')
                let latestVersionDotted = latestVersion
                latestVersion = latestVersion.replace(/\./g, '');

                while (installedVersion.length < latestVersion.length) {
                    installedVersion = `${installedVersion}0`
                }
                while (latestVersion.length < installedVersion.length) {
                    latestVersion = `${latestVersion}0`
                }
                if (parseInt(latestVersion) > parseInt(installedVersion)) {
                    console.log(`Updating from install v${installedVersionDotted} to latest v${latestVersionDotted}`)
                    shell.exec(`npm install -g ${packageJson.name}`)
                } else {
                    console.log(`Installed v${installedVersionDotted} is the latest.`)
                }

            } catch (error) {
                console.log(error)
            }
        }
        updateFromnpm();
        setInterval(() => {
            console.log(this.interval)
            updateFromnpm();
            this.updateModules()
        }, this.interval * 1000)
    }

    /**
     * update node modules for current project
     */
    updateModules(){
        let packageJsonDir = conf.packageJsonDir();
        shell.exec(`cd ${packageJsonDir} && yarn install || npm install`, { silent: true })
    }
}

new automaticUpdates();
module.exports = new automaticUpdates();