UNPKG

serverless-exports-plugin

Version:

Serverless Framework plugin to export Environment variables and CloudFormation outputs to a file

115 lines (114 loc) 4.87 kB
"use strict"; 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;