mirror of
https://github.com/serverless/serverless.git
synced 2026-01-18 14:58:43 +00:00
122 lines
3.8 KiB
JavaScript
122 lines
3.8 KiB
JavaScript
import spawn from 'child-process-ext/spawn.js';
|
|
import fsp from 'fs/promises';
|
|
import fse from 'fs-extra';
|
|
import path from 'path';
|
|
import _ from 'lodash';
|
|
import isPlainObject from 'type/plain-object/is.js';
|
|
import yaml from 'js-yaml';
|
|
import cloudformationSchema from '@serverless/utils/cloudformation-schema.js';
|
|
import { utils } from '@serverlessinc/sf-core';
|
|
import yamlAstParser from '../lib/utils/yaml-ast-parser.js';
|
|
import npmCommandDeferred from '../lib/utils/npm-command-deferred.js';
|
|
import {
|
|
getPluginInfo,
|
|
getServerlessFilePath,
|
|
validate,
|
|
} from '../lib/commands/plugin-management.js';
|
|
|
|
const { log, progress, style } = utils;
|
|
|
|
const mainProgress = progress.get('main');
|
|
|
|
export default async ({ configuration, serviceDir, configurationFilename, options }) => {
|
|
const commandRunStartTime = Date.now();
|
|
validate({ serviceDir });
|
|
|
|
const pluginInfo = getPluginInfo(options.name);
|
|
const pluginName = pluginInfo.name;
|
|
const configurationFilePath = getServerlessFilePath({ serviceDir, configurationFilename });
|
|
|
|
const context = { configuration, serviceDir, configurationFilePath, pluginName };
|
|
mainProgress.notice(`Uninstalling plugin "${pluginName}"`, { isMainEvent: true });
|
|
await uninstallPlugin(context);
|
|
await removePluginFromServerlessFile(context);
|
|
|
|
log.notice();
|
|
log.notice.success(
|
|
`Plugin "${pluginName}" uninstalled ${style.aside(
|
|
`(${Math.floor((Date.now() - commandRunStartTime) / 1000)}s)`
|
|
)}`
|
|
);
|
|
};
|
|
|
|
const uninstallPlugin = async ({ serviceDir, pluginName }) => {
|
|
await npmUninstall(pluginName, { serviceDir });
|
|
};
|
|
|
|
const removePluginFromServerlessFile = async ({ configurationFilePath, pluginName }) => {
|
|
const fileExtension = path.extname(configurationFilePath);
|
|
if (fileExtension === '.js' || fileExtension === '.ts') {
|
|
requestManualUpdate(configurationFilePath);
|
|
return;
|
|
}
|
|
|
|
if (fileExtension === '.json') {
|
|
const serverlessFileObj = await fse.readJson(configurationFilePath);
|
|
const isArrayPluginsObject = Array.isArray(serverlessFileObj.plugins);
|
|
const plugins = isArrayPluginsObject
|
|
? serverlessFileObj.plugins
|
|
: serverlessFileObj.plugins && serverlessFileObj.plugins.modules;
|
|
|
|
if (plugins) {
|
|
_.pull(plugins, pluginName);
|
|
if (!plugins.length) {
|
|
if (isArrayPluginsObject) {
|
|
delete serverlessFileObj.plugins;
|
|
} else {
|
|
delete serverlessFileObj.plugins.modules;
|
|
}
|
|
}
|
|
await fse.writeJson(configurationFilePath, serverlessFileObj);
|
|
}
|
|
return;
|
|
}
|
|
|
|
const serverlessFileObj = yaml.load(await fsp.readFile(configurationFilePath, 'utf8'), {
|
|
filename: configurationFilePath,
|
|
schema: cloudformationSchema,
|
|
});
|
|
if (serverlessFileObj.plugins != null) {
|
|
// Plugins section can be behind variables, opt-out in such case
|
|
if (isPlainObject(serverlessFileObj.plugins)) {
|
|
if (
|
|
serverlessFileObj.plugins.modules != null &&
|
|
!Array.isArray(serverlessFileObj.plugins.modules)
|
|
) {
|
|
requestManualUpdate(configurationFilePath);
|
|
return;
|
|
}
|
|
} else if (!Array.isArray(serverlessFileObj.plugins)) {
|
|
requestManualUpdate(configurationFilePath);
|
|
return;
|
|
}
|
|
}
|
|
await yamlAstParser.removeExistingArrayItem(
|
|
configurationFilePath,
|
|
Array.isArray(serverlessFileObj.plugins) ? 'plugins' : 'plugins.modules',
|
|
pluginName
|
|
);
|
|
};
|
|
|
|
const npmUninstall = async (name, { serviceDir }) => {
|
|
const { command, args } = await npmCommandDeferred;
|
|
try {
|
|
await spawn(command, [...args, 'uninstall', '--save-dev', name], {
|
|
cwd: serviceDir,
|
|
stdio: 'pipe',
|
|
});
|
|
} catch (error) {
|
|
log.error(String(error.stderrBuffer));
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
const requestManualUpdate = (configurationFilePath) => {
|
|
log.notice();
|
|
log.notice.skip(
|
|
`Can't automatically remove plugin from "${path.basename(
|
|
configurationFilePath
|
|
)}" file. Please make it manually.`
|
|
);
|
|
};
|