UNPKG

n-bootstart

Version:

A script to start node js projects when the system boots up

288 lines (261 loc) 10.1 kB
'use strict'; /** * This source code is licensed under MIT. */ const os = require('os'); const fs = require('fs'); const path = require('path'); const username = os.userInfo().username; const { spawnSync } = require('child_process'); const config = require('./configs'); const BASE_PATH = config.BASE_PATH; const utils = require('./utils'); if (!fs.existsSync(BASE_PATH)) { fs.mkdirSync(BASE_PATH); } class scripts extends utils { constructor() { super(); } /** * Get enabled status of a project * @param {String} projectName * @returns {Object} status */ status(projectName) { const isLinux = os.type().indexOf('Windows') < 0 ? true : false; let bootScriptPath = this.getBootScriptPath(isLinux, projectName); if (isLinux) { let existingCron = spawnSync('crontab', ['-u', username, '-l'], { detached: true }); let cronContent = existingCron.stdout.toString(); let cronErr = existingCron.stderr.toString(); if (this.isValidCronErr(cronErr)) { return { err: this.formatError(cronErr), status: false }; } else if (cronContent.indexOf(`${this.getProjectTag(projectName)}_`) > -1) { return { status: true }; } } else if (fs.existsSync(bootScriptPath)) { return { status: true }; } return { status: false }; }; /** * Enable boot-start for a project * @param {String} projectName * @param {String} projectPath * @param {String} envVariables - Format : key1=value1,key2=value2 * @returns {Object} err, status */ _enable(projectName, projectPath, envVariables) { const isLinux = os.type().indexOf('Windows') < 0 ? true : false; let scriptStatus = this.status(projectName); if (scriptStatus.status) { const err = `A script already exists with the same name.`; return { status: false, err }; } if (!fs.existsSync(projectPath)) { return { status: false, err: `Incorrect project path - '${projectPath}'.` }; } let bootScriptPath = this.getBootScriptPath(isLinux, projectName); let envVars = this.getEnvVariables(isLinux, envVariables); let executionCmd = this.getExecutionCmd(envVariables); let projectInfo = this.getProjectInfo(isLinux, projectPath); if (projectInfo && projectInfo.err) { return { status: false, err: projectInfo.err }; } if (isLinux) { let existingCron = spawnSync('crontab', ['-u', username, '-l'], { detached: true }); let cronContent = existingCron.stdout.toString(); let cronListErr = existingCron.stderr.toString(); if (this.isValidCronErr(cronListErr)) { return { err: this.formatError(cronListErr), status: false }; } if (!cronContent || cronContent.toString().length < 1) { cronContent = ''; } let scriptContent = this.getCronContent(projectInfo, envVars, executionCmd); if (cronContent.indexOf(`${this.getProjectTag(projectName)}_`) < 0) { cronContent += `\n${this.getProjectTag(projectName)}_${envVars} ${projectPath}${scriptContent}`; } fs.writeFileSync(path.resolve(bootScriptPath), cronContent); let addCron = spawnSync('crontab', ['-u', username, path.resolve(bootScriptPath)], { detached: true }); let cronErr = addCron.stderr.toString(); if (this.isValidCronErr(cronErr)) { return { err: this.formatError(cronErr), status: false }; } } else { fs.writeFileSync(bootScriptPath, `Set ObjShell = CreateObject("Wscript.Shell")\nSet processVar = ObjShell.Environment("process")\n${envVars}path = "${projectInfo.directory}"\nstartfile = "${projectInfo.startFile}"\nObjShell.Run "cmd.exe /S /C cd """ & path & """ & ${executionCmd} ${projectInfo.startFile}""", 0`); } this.updateProjectList(projectName, true); return { status: true }; }; /** * Disable boot-start for a project * @param {String} projectName * @returns {Object} err, status */ _disable(projectName) { const isLinux = os.type().indexOf('Windows') < 0 ? true : false; let scriptStatus = this.status(projectName); if (!scriptStatus.status) { const err = `No script found for the mentioned project.`; return { status: false, err }; } let bootScriptPath = this.getBootScriptPath(isLinux, projectName); if (isLinux) { let existingCron = spawnSync('crontab', ['-u', username, '-l'], { detached: true }); let cronContent = existingCron.stdout.toString(); let cronListErr = existingCron.stderr.toString(); if (this.isValidCronErr(cronListErr)) { return { err: this.formatError(cronListErr), status: false }; } if (cronContent && cronContent.length > 0) { cronContent = cronContent.split('\n'); let scriptTag = this.getProjectTag(projectName); let scriptIndex = this.getStringIndex(`${scriptTag}_`, cronContent); let updatedCronContent = ''; if (scriptIndex > -1) { cronContent.splice(scriptIndex, 2); } for (let i = 0; i < cronContent.length; i++) { if (updatedCronContent.length > 0) { updatedCronContent += '\n'; } if (cronContent[i].trim().length > 0) { updatedCronContent += cronContent[i]; } } fs.writeFileSync(path.resolve(bootScriptPath), updatedCronContent); let addCron = spawnSync('crontab', ['-u', username, path.resolve(bootScriptPath)], { detached: true }); let cronErr = addCron.stderr.toString(); if (this.isValidCronErr(cronErr)) { return { err: this.formatError(cronErr), status: false }; } } } else { fs.unlinkSync(bootScriptPath) } this.updateProjectList(projectName); return { status: true }; }; /** * View the configured information for a project * @param {String} projectName * @returns {Object} err, status, path, envVars, startfile */ _view(projectName) { const isLinux = os.type().indexOf('Windows') < 0 ? true : false; const err = `No content found for the mentioned project.`; let scriptStatus = this.status(projectName); if (!scriptStatus.status) { return { status: false, err }; } let path = '', envVars = '', startfile = ''; let bootScriptPath = this.getBootScriptPath(isLinux, projectName); if (isLinux) { let existingCron = spawnSync('crontab', ['-u', username, '-l'], { detached: true }); let cronContent = existingCron.stdout.toString(); let cronListErr = existingCron.stderr.toString(); if (this.isValidCronErr(cronListErr)) { return { err: this.formatError(cronListErr), status: false }; } cronContent = cronContent.split('\n'); let scriptTag = this.getProjectTag(projectName); let scriptIndex = this.getStringIndex(`${scriptTag}_`, cronContent); if (scriptIndex > -1) { path = cronContent[scriptIndex].split(' ')[1]; let projectTag = `${this.getProjectTag(projectName)}_`; envVars = cronContent[scriptIndex].split(projectTag); if (envVars && envVars[1]) { envVars = envVars[1].split(' ')[0]; } else { envVars = ''; } return { status: true, path, envVars }; } } else { let scriptContent = fs.readFileSync(bootScriptPath).toString().split('\n'); for (let i = 0; i < scriptContent.length; i++) { if (scriptContent[i].indexOf('processVar(') > -1) { scriptContent[i] = scriptContent[i].split('"').join(''); let key = scriptContent[i].split('=')[0]; key = key.split('(')[1]; key = key.split(')')[0]; let value = scriptContent[i].split('=')[1] ? scriptContent[i].split('=')[1].trim() : ''; if (envVars.length > 0) { envVars += ',' } envVars += `${key}=${value}`; } if (scriptContent[i].indexOf('path = ') > -1) { path = scriptContent[i].split('path = ')[1].trim().split('"').join(''); } if (scriptContent[i].indexOf('startfile = ') > -1) { startfile = scriptContent[i].split('startfile = ')[1].trim().split('"').join(''); } if (path === '' && scriptContent[i].indexOf('ObjShell.Run') > -1) { let content = scriptContent[i].split('node'); content = content && content.length > 0 ? content[content.length - 1] : ''; path = content && content.indexOf('"') > -1 ? content.split('"')[0].trim() : ''; } } return { status: true, path, startfile, envVars } } return { status: false, err }; }; /** * List all the configured projects * @returns {Object} list, err */ _list() { let result = this.getProjects(); if (result && result.list) { let projects = result.list.split('\n'); projects = projects.filter(function (project) { return project.toString().trim().length > 0; }); for (let i = 0; i < projects.length; i++) { let index = parseInt(i) + 1; projects[i] = `${index}. ${projects[i]}`; } result.list = projects.toString().split(',').join('\n'); } return result; }; /** * Remove all the configured projects * @returns {Object} list, err */ _removeAll() { let result = this.getProjects(); if (result && result.list) { let projects = result.list.split('\n'); if (projects.length > 0) { let disabled = { count: 0 }; projects.map((name) => { let response = this._disable(name); if (response && response.status) { disabled.count++; } }); return disabled; } } return null; }; }; module.exports = scripts;