serverless-exports-plugin
Version:
Serverless Framework plugin to export Environment variables and CloudFormation outputs to a file
115 lines (114 loc) • 4.87 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const chalk_1 = __importDefault(require("chalk"));
const config_1 = require("./config");
// https://www.serverless.com/framework/docs/guides/plugins/creating-plugins
class ServerlessOutputPlugin {
constructor(serverless, cliOptions, logging) {
this.serverless = serverless;
this.cliOptions = cliOptions || {};
this.logging = logging;
this.config = { exports: {} };
this.hooks = {
initialize: () => this.init(),
// https://www.serverless.com/framework/docs/providers/aws/cli-reference/info
'info:info': async () => this.exportEnvironment(),
'package:finalize': async () => this.exportEnvironment(),
'deploy:finalize': async () => this.exportStack(),
};
serverless.configSchemaHandler.defineCustomProperties(config_1.configSchema);
}
init() {
this.config = this.serverless.service.custom;
}
async exportEnvironment() {
if (!this.config.exports.environment) {
this.logging.log.notice('Config for environment not found. Skipping export for environment variables.');
return;
}
this.logging.log.verbose('\nExporting enviroment...');
const exports = await this.getEnvironmentVariables();
this.write(exports, this.config.exports.environment);
this.logging.log.success(`Exported environment variables to ${this.prettifyFile(this.config.exports.environment.file)}`);
this.logging.log.notice(`${this.prettifyExports(exports)}\n`);
}
async exportStack() {
if (!this.config.exports.stack) {
this.logging.log.notice('Config for stack not found. Skipping export for stack outputs.');
return;
}
this.logging.log.verbose('\nExporting stack...');
const exports = await this.getStackOutputs();
this.write(exports, this.config.exports.stack);
this.logging.log.success(`Exported stack outputs to ${this.prettifyFile(this.config.exports.stack.file)}`);
this.logging.log.notice(this.prettifyExports(exports));
}
async getEnvironmentVariables() {
const providerVariables = 'environment' in this.serverless.service.provider
? this.serverless.service.provider.environment
: {};
// TODO collect variables from functions
const functionVariables = {};
return {
...providerVariables,
...functionVariables,
};
}
async getStackOutputs() {
const aws = this.serverless.getProvider('aws');
const stackName = aws.naming.getStackName();
const response = await aws.request('CloudFormation', 'describeStacks', {
StackName: stackName,
});
if (!response.Stacks)
throw new Error(`Stack ${stackName} not found`);
const [stack] = response.Stacks;
const outputs = stack.Outputs || [];
return outputs.reduce((acc, { OutputKey, OutputValue }) => {
if (!OutputKey)
return acc;
acc[OutputKey] = OutputValue || '';
return acc;
}, {});
}
format(exports, format) {
switch (format.toLowerCase()) {
case 'toml':
throw new Error('Not implemented yet');
case 'yaml':
case 'yml':
return Object.entries(exports)
.map(([key, value]) => `${key}: ${value}`)
.join('\n');
case 'json':
throw new Error('Not implemented yet');
case 'env':
return Object.entries(exports)
.map(([key, value]) => `${key}=${value}`)
.join('\n');
default:
throw new Error(`Format ${format} is not supported`);
}
}
write(exports, config) {
if (node_fs_1.default.existsSync(config.file) && !config.overwrite)
throw new Error(`File ${config.file} already exists and overwrite is disabled`);
const { format, file } = config;
const content = this.format(exports, format);
//TODO create directory if it doesn't exist
node_fs_1.default.writeFileSync(file, content);
}
prettifyExports(exports) {
return Object.entries(exports)
.map(([key, value]) => chalk_1.default.gray(` ${key}: ${value}`))
.join('\n');
}
prettifyFile(file) {
return chalk_1.default.gray(node_path_1.default.relative(process.cwd(), file));
}
}
module.exports = ServerlessOutputPlugin;