Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
coverage
node_modules
dist
node_modules
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ custom:
file: .build/stack.toml # toml, yaml, yml, and json format is available
```

Optionally, you can provide a format explicitly which will allow you to choose
any output filename. This format will override the implicit one from the file
extension.

```yaml
custom:
output:
format: toml
file: .env
```

### Handler

Based on the configuration above the plugin will search for a file `scripts/output.js` with the following content:
Expand Down
36 changes: 36 additions & 0 deletions dist/file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("fs");
var StackOutputFile = /** @class */ (function () {
function StackOutputFile(path, format) {
this.path = path;
this.format = format;
}
StackOutputFile.prototype.formatData = function (data) {
var ext = this.path.split('.').pop() || '';
var format = this.format || ext;
switch (format.toUpperCase()) {
case 'JSON':
return JSON.stringify(data, null, 2);
case 'TOML':
return require('tomlify-j0.4')(data, null, 0).replace(/ /g, "");
case 'YAML':
case 'YML':
return require('yamljs').stringify(data);
default:
throw new Error('No formatter found for `' + format + '` extension');
}
};
StackOutputFile.prototype.save = function (data) {
var content = this.formatData(data);
try {
fs.writeFileSync(this.path, content);
}
catch (e) {
throw new Error('Cannot write to file: ' + this.path);
}
return Promise.resolve();
};
return StackOutputFile;
}());
exports.default = StackOutputFile;
4 changes: 4 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var plugin_1 = require("./plugin");
module.exports = plugin_1.default;
99 changes: 99 additions & 0 deletions dist/plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var assert = require("assert");
var util = require("util");
var file_1 = require("./file");
var StackOutputPlugin = /** @class */ (function () {
function StackOutputPlugin(serverless, options) {
this.serverless = serverless;
this.options = options;
this.hooks = {
'after:deploy:deploy': this.process.bind(this)
};
this.output = this.serverless.service.custom.output;
}
Object.defineProperty(StackOutputPlugin.prototype, "file", {
get: function () {
return this.getConfig('file');
},
enumerable: true,
configurable: true
});
Object.defineProperty(StackOutputPlugin.prototype, "handler", {
get: function () {
return this.getConfig('handler');
},
enumerable: true,
configurable: true
});
Object.defineProperty(StackOutputPlugin.prototype, "stackName", {
get: function () {
return util.format('%s-%s', this.serverless.service.getServiceName(), this.serverless.getProvider('aws').getStage());
},
enumerable: true,
configurable: true
});
StackOutputPlugin.prototype.hasConfig = function (key) {
return !!this.output && !!this.output[key];
};
StackOutputPlugin.prototype.hasHandler = function () {
return this.hasConfig('handler');
};
StackOutputPlugin.prototype.hasFile = function () {
return this.hasConfig('file');
};
StackOutputPlugin.prototype.getConfig = function (key) {
return util.format('%s/%s', this.serverless.config.servicePath, this.output[key]);
};
StackOutputPlugin.prototype.callHandler = function (data) {
var splits = this.handler.split('.');
var func = splits.pop() || '';
var file = splits.join('.');
require(file)[func](data, this.serverless, this.options);
return Promise.resolve();
};
StackOutputPlugin.prototype.saveFile = function (data) {
var f = new file_1.default(this.file, this.output.format);
return f.save(data);
};
StackOutputPlugin.prototype.fetch = function () {
return this.serverless.getProvider('aws').request('CloudFormation', 'describeStacks', { StackName: this.stackName }, this.serverless.getProvider('aws').getStage(), this.serverless.getProvider('aws').getRegion());
};
StackOutputPlugin.prototype.beautify = function (data) {
var stack = data.Stacks.pop() || { Outputs: [] };
var output = stack.Outputs || [];
return output.reduce(function (obj, item) {
return (Object.assign(obj, (_a = {}, _a[item.OutputKey] = item.OutputValue, _a)));
var _a;
}, {});
};
StackOutputPlugin.prototype.handle = function (data) {
return Promise.all([
this.handleHandler(data),
this.handleFile(data)
]);
};
StackOutputPlugin.prototype.handleHandler = function (data) {
var _this = this;
return this.hasHandler() ? (this.callHandler(data).then(function () { return _this.serverless.cli.log(util.format('Stack Output processed with handler: %s', _this.output.handler)); })) : Promise.resolve();
};
StackOutputPlugin.prototype.handleFile = function (data) {
var _this = this;
return this.hasFile() ? (this.saveFile(data).then(function () { return _this.serverless.cli.log(util.format('Stack Output saved to file: %s', _this.output.file)); })) : Promise.resolve();
};
StackOutputPlugin.prototype.validate = function () {
assert(this.serverless, 'Invalid serverless configuration');
assert(this.serverless.service, 'Invalid serverless configuration');
assert(this.serverless.service.provider, 'Invalid serverless configuration');
assert(this.serverless.service.provider.name, 'Invalid serverless configuration');
assert(this.serverless.service.provider.name === 'aws', 'Only supported for AWS provider');
assert(this.options && !this.options.noDeploy, 'Skipping deployment with --noDeploy flag');
};
StackOutputPlugin.prototype.process = function () {
var _this = this;
Promise.resolve()
.then(function () { return _this.validate(); }).then(function () { return _this.fetch(); }).then(function (res) { return _this.beautify(res); }).then(function (res) { return _this.handle(res); }).catch(function (err) { return _this.serverless.cli.log(util.format('Cannot process Stack Output: %s!', err.message)); });
};
return StackOutputPlugin;
}());
exports.default = StackOutputPlugin;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "serverless-stack-output",
"description": "Serverless plugin to process AWS CloudFormation Stack Output",
"version": "0.2.6",
"license": "MIT",
"author": "Sebastian Müller <mail@sbstjn.com>",
"main": "dist",
Expand Down
15 changes: 9 additions & 6 deletions src/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,30 @@ import * as fs from 'fs'

export default class StackOutputFile {
constructor (
public path: string
public path: string,
public format: string
) { }

public format (data: object) {
public formatData (data: object) {
const ext = this.path.split('.').pop() || ''

switch (ext.toUpperCase()) {
const format = this.format || ext;

switch (format.toUpperCase()) {
case 'JSON':
return JSON.stringify(data, null, 2)
case 'TOML':
return require('tomlify-j0.4')(data, null, 0)
return require('tomlify-j0.4')(data, null, 0).replace(/ /g, "")
case 'YAML':
case 'YML':
return require('yamljs').stringify(data)
default:
throw new Error('No formatter found for `' + ext + '` extension')
throw new Error('No formatter found for `' + format + '` extension')
}
}

public save (data: object) {
const content = this.format(data)
const content = this.formatData(data)

try {
fs.writeFileSync(this.path, content)
Expand Down
2 changes: 1 addition & 1 deletion src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default class StackOutputPlugin {
}

private saveFile (data: object) {
const f = new StackOutputFile(this.file)
const f = new StackOutputFile(this.file, this.output.format)

return f.save(data)
}
Expand Down
1 change: 1 addition & 0 deletions vendor/main.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ declare interface StackDescriptionList {
declare interface OutputConfig {
handler: string
file: string
format: string
}