UNPKG

profoundjs

Version:

Profound.js Framework and Server

201 lines (183 loc) 6.05 kB
"use strict"; /* Discovers and removes additional components that exist outside of the package installation directory. It's used by Profound Installer Any changes to the behavior may require changes to the "install_info.json" file or Profound Installer. */ const child_process = require("child_process"); const minimist = require("minimist"); const iutils = require("./install_utils.js"); const readline = require("readline"); const IBMi = iutils.isIBMi(); (async() => { try { // Parse arguments. const argDefs = { alias: { "h": "help", "d": "dry-run", "s": "silent" }, boolean: [ "h", "d", "s" ], unknown: function(arg) { console.error("removeExtraComponents.js: Unknown argument:", arg); process.exit(1); } }; const args = minimist(process.argv.slice(2), argDefs); // Show help and quit, if requested. if (args["help"] === true) { const HELP = `Usage: node removeExtraComponents.js [OPTION] -h, --help Print this help and exit. -d, --dry-run Report what items would be removed, without removing them. -s, --silent Bypass confirmation prompt. Removes components that exist outside of the package installation directory: * IBM i Connector library, based on config setting: "connectorLibrary" * IBM i STRTCPSVR instance configuration. This script does not uninstall the package itself. It is intended to be used before uninstalling the package via NPM. `; console.log(HELP); process.exit(0); } // Get config. const deployDir = iutils.getDeployDir(); if (!deployDir) { console.error("removeExtraComponents.js: Can't find deployment directory."); process.exit(1); } const configPath = iutils.getConfigPath(); let config; try { config = require(configPath); } catch (error) { console.error("removeExtraComponents.js: Unable to read configuration file: " + configPath); console.error("removeExtraComponents.js:", error.message); process.exit(1); } let connectorLibrary, connectorIASP; let instances = []; const messages = []; if (IBMi) { // Get STRTCPSVR instance configs, if any. instances = iutils.getIBMiInstances(deployDir); for (const instance of instances) { messages.push("IBM i STRTCPSVR instance configuration " + instance.name); } // Get Connector library details, if any. connectorLibrary = config.connectorLibrary; connectorIASP = config.connectorIASP; if (connectorIASP === undefined) { connectorIASP = "*SYSBAS"; } if (connectorLibrary !== undefined) { let exists = false; try { // Determine if library exists. // This is a weird way to do it... // This allows us to check for the library even if the IASP is not mounted to the IFS and not in the job current ASP group. execCL(`qsys/dsplib lib(${connectorLibrary}) aspdev(${connectorIASP}) output(*)`, true); exists = true; } catch (error) { let handle = false; if (error.stderr) { const match = error.stderr.toString().match(/^(CPF.{4}): /); if (match) { const msgid = match[1]; handle = (msgid === "CPF2110"); // Library not found. } } if (!handle) { throw error; } } if (exists) { messages.push("IBM i Connector library " + connectorLibrary + " in ASP device " + connectorIASP); } else { connectorLibrary = connectorIASP = undefined; } } } // Report and quit, if requested. if (args["dry-run"] === true) { for (const message of messages) { console.log(message); } process.exit(0); } if (messages.length === 0) { console.log("No additional components to remove."); process.exit(0); } if (args["silent"] !== true) { // Confirm removal. console.log("The following items will be removed:\n"); for (const message of messages) { console.log(message); } let answer = await new Promise(resolve => { const readlineInterface = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false }); readlineInterface.question("\nAre you sure you want to proceed (y/n)? ", function(answer) { readlineInterface.close(); resolve(answer); }); }); answer = answer.trim().toLowerCase(); if (answer === "") { answer = "n"; } if (answer !== "y") { console.log("Removal of extra components canceled."); process.exit(0); } } for (const instance of instances) { execCL(`QSYS/ENDTCPSVR SERVER(*PJS) INSTANCE(${instance.name})`); // This should generally work as shutdown is relatively fast. await new Promise(resolve => setTimeout(resolve, 10000)); exec(`/usr/bin/rm -rf '/profoundjs-base/instances/${instance.name}'`); } if (connectorLibrary !== undefined) { execCL(`qsys/dltlib lib(${connectorLibrary}) aspdev(${connectorIASP})`); } console.log("Removal of extra components complete."); process.stdin.destroy(); } catch (error) { process.stdin.destroy(); console.error(error); process.exit(1); } })(); function execCL(command, quiet) { command = `/usr/bin/system '${escapeQuotes(command)}'`; return exec(command, quiet); function escapeQuotes(input) { return input.replace(/'/g, "'\\''"); } } function exec(command, quiet = false) { if (quiet !== true) { console.log("Executing command:", command); } const opts = { env: { QIBM_USE_DESCRIPTOR_STDIO: "Y", QIBM_MULTI_THREADED: "N" }, stdio: "pipe", windowsHide: true }; return child_process.execSync(command, opts).toString(); }