UNPKG

@zowe/imperative

Version:
160 lines 8.15 kB
"use strict"; /* * This program and the accompanying materials are made available under the terms of the * Eclipse Public License v2.0 which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-v20.html * * SPDX-License-Identifier: EPL-2.0 * * Copyright Contributors to the Zowe Project. * */ Object.defineProperty(exports, "__esModule", { value: true }); exports.updateAndGetRemovedTypes = void 0; exports.uninstall = uninstall; const fs = require("fs"); const path = require("path"); const PMFConstants_1 = require("../PMFConstants"); const jsonfile_1 = require("jsonfile"); const logger_1 = require("../../../../../logger"); const error_1 = require("../../../../../error"); const utilities_1 = require("../../../../../utilities"); const NpmFunctions_1 = require("../NpmFunctions"); const config_1 = require("../../../../../config"); const npmCmd = (0, NpmFunctions_1.findNpmOnPath)(); /** * Updates `extenders.json` and returns a list of types to remove from the schema, if applicable. * @param npmPackage The package name for the plug-in that's being uninstalled * @returns A list of types to remove from the schema */ const updateAndGetRemovedTypes = (npmPackage) => { const extendersJson = config_1.ConfigUtils.readExtendersJson(); const pluginTypes = Object.keys(extendersJson.profileTypes) .filter((type) => extendersJson.profileTypes[type].from.includes(npmPackage)); const typesToRemove = []; if (pluginTypes.length > 0) { // Only remove a profile type contributed by this plugin if its the single source for that type. for (const profileType of pluginTypes) { const typeInfo = extendersJson.profileTypes[profileType]; if (typeInfo.from.length > 1) { // If there are other sources, remove the version for that type if this plugin provides the // latest version. This will allow the next source to contribute a different schema version. if (typeInfo.latestFrom === npmPackage) { extendersJson.profileTypes[profileType] = Object.assign(Object.assign({}, typeInfo), { from: typeInfo.from.filter((v) => v !== npmPackage), latestFrom: undefined, version: undefined }); } else { extendersJson.profileTypes[profileType] = Object.assign(Object.assign({}, typeInfo), { from: typeInfo.from.filter((v) => v !== npmPackage) }); } } else { delete extendersJson.profileTypes[profileType]; typesToRemove.push(profileType); } } config_1.ConfigUtils.writeExtendersJson(extendersJson); } return typesToRemove; }; exports.updateAndGetRemovedTypes = updateAndGetRemovedTypes; /** * @TODO - allow multiple packages to be uninstalled? * Common function that abstracts the uninstall process. * * @param {string} packageName A package name. This value is a valid npm package name. * */ function uninstall(packageName) { var _a; const iConsole = logger_1.Logger.getImperativeLogger(); const chalk = utilities_1.TextUtils.chalk; const npmPackage = packageName; iConsole.debug(`Uninstalling package: ${packageName}`); iConsole.debug("Reading in the current configuration."); const installedPlugins = (0, jsonfile_1.readFileSync)(PMFConstants_1.PMFConstants.instance.PLUGIN_JSON); const updatedInstalledPlugins = {}; if (Object.prototype.hasOwnProperty.call(installedPlugins, packageName)) { // Loop through the plugins and remove the uninstalled package for (const pluginName in installedPlugins) { // Only retain the plugins that aren't being uninstalled if (packageName.toString() !== pluginName.toString()) { updatedInstalledPlugins[pluginName] = installedPlugins[pluginName]; } } } else { throw new error_1.ImperativeError({ msg: `${chalk.yellow.bold("Plugin name")} '${chalk.red.bold(packageName)}' is not installed.` }); } try { // We need to capture stdout but apparently stderr also gives us a progress // bar from the npm install. const daemonStream = (_a = utilities_1.ImperativeConfig.instance.daemonContext) === null || _a === void 0 ? void 0 : _a.stream; const stderrBuffer = []; const pipe = ["pipe", "pipe", "pipe"]; // Perform the npm uninstall, somehow piping stdout and inheriting stderr gives // some form of a half-assed progress bar. This progress bar doesn't have any // formatting or colors but at least I can get the output of stdout right. (comment from install handler) iConsole.info("Uninstalling package...this may take some time."); const output = utilities_1.ExecUtils.spawnAndGetOutput(npmCmd, [ "uninstall", npmPackage, "--prefix", PMFConstants_1.PMFConstants.instance.PLUGIN_INSTALL_LOCATION, "-g" ], { cwd: PMFConstants_1.PMFConstants.instance.PMF_ROOT, // We need to capture stdout but apparently stderr also gives us a progress // bar from the npm install. stdio: pipe }); if (output) { stderrBuffer.push(output.toString()); } const installFolder = path.join(PMFConstants_1.PMFConstants.instance.PLUGIN_HOME_LOCATION, npmPackage); if (fs.existsSync(installFolder)) { throw new Error("Failed to uninstall plugin, install folder still exists:\n " + installFolder); } if (PMFConstants_1.PMFConstants.instance.PLUGIN_USING_CONFIG) { // Update the Imperative Configuration to add the profiles introduced by the recently installed plugin // This might be needed outside of PLUGIN_USING_CONFIG scenarios, but we haven't had issues with other APIs before const globalLayer = PMFConstants_1.PMFConstants.instance.PLUGIN_CONFIG.layers.find((layer) => layer.global && layer.exists); if (globalLayer) { const schemaInfo = PMFConstants_1.PMFConstants.instance.PLUGIN_CONFIG.getSchemaInfo(); if (schemaInfo.local && fs.existsSync(schemaInfo.resolved)) { let loadedSchema; try { // load schema from disk to prevent removal of profile types from other applications loadedSchema = config_1.ConfigSchema.loadSchema((0, jsonfile_1.readFileSync)(schemaInfo.resolved)); } catch (err) { iConsole.error("Error when removing profile type for plugin %s: failed to parse schema", npmPackage); } // update extenders.json with any removed types - function returns the list of types to remove const typesToRemove = (0, exports.updateAndGetRemovedTypes)(npmPackage); // Only update global schema if there are types to remove and accessible from disk if (loadedSchema != null && typesToRemove.length > 0) { loadedSchema = loadedSchema.filter((typeCfg) => !typesToRemove.includes(typeCfg.type)); const schema = config_1.ConfigSchema.buildSchema(loadedSchema); config_1.ConfigSchema.updateSchema({ layer: "global", schema }); } } } } iConsole.info("Uninstall complete"); (0, jsonfile_1.writeFileSync)(PMFConstants_1.PMFConstants.instance.PLUGIN_JSON, updatedInstalledPlugins, { spaces: 2 }); iConsole.info("Plugin successfully uninstalled."); if (stderrBuffer.length > 0 && daemonStream) { daemonStream.write(utilities_1.DaemonRequest.create({ stderr: stderrBuffer.toString() })); } } catch (e) { throw new error_1.ImperativeError({ msg: e.message, causeErrors: [e] }); } } //# sourceMappingURL=uninstall.js.map