161 lines
4.6 KiB
JavaScript

'use strict';
const os = require('os');
const BbPromise = require('bluebird');
const fdk = require('@serverless/fdk');
const path = require('path');
const stdin = require('get-stdin');
const getAuthToken = require('../../utils/getAuthToken');
const userStats = require('../../utils/userStats');
const chalk = require('chalk');
const spaceSmall = ' ';
const spaceLarge = ' ';
const colorDim = chalk.hex('#777777');
const colorPrefix = chalk.hex('#bdb018');
const prefix = colorPrefix(` Serverless ${spaceSmall}`);
const prettifyValue = value => {
const prettified = JSON.stringify(value, null, 2).replace(
new RegExp('\\n', 'g'),
`\n${spaceLarge}`
);
return `${spaceLarge}${colorDim(prettified)}`;
};
class Emit {
constructor(serverless, options) {
this.serverless = serverless;
this.options = options || {};
this.data = null;
this.commands = {
emit: {
usage: 'Emits an event to a running Event Gateway',
lifecycleEvents: ['emit'],
options: {
name: {
usage: 'Event type',
required: true,
shortcut: 'n',
},
path: {
usage: 'Path to JSON or YAML file holding input data',
shortcut: 'p',
},
data: {
usage: 'Input data',
shortcut: 'd',
},
url: {
usage: 'Event Gateway address',
shortcut: 'u',
},
datatype: {
usage: 'Data type for the input data. By default set to application/json',
shortcut: 't',
},
},
platform: true,
},
};
this.hooks = {
'emit:emit': () =>
BbPromise.bind(this)
.then(this.retrieveData)
.then(this.parseData)
.then(this.emitEvent),
};
}
retrieveData() {
return new BbPromise((resolve, reject) => {
if (this.options.data) {
if (this.options.datatype) {
this.data = this.options.data;
resolve();
} else {
try {
this.data = JSON.parse(this.options.data);
resolve();
} catch (exception) {
reject(new Error("Couldn't parse the provided data to a JSON structure."));
}
}
} else if (this.options.path) {
const absolutePath = path.isAbsolute(this.options.path)
? this.options.path
: path.join(this.serverless.config.servicePath, this.options.path);
if (!this.serverless.utils.fileExistsSync(absolutePath)) {
reject(new Error('The file you provided does not exist.'));
}
this.data = this.serverless.utils.readFileSync(absolutePath);
resolve();
} else {
try {
stdin().then(input => {
if (this.options.datatype) {
this.data = this.options.data;
resolve();
} else {
try {
this.data = JSON.parse(input);
resolve();
} catch (exception) {
reject(new Error("Couldn't parse the provided data to a JSON structure."));
}
resolve();
}
});
} catch (exception) {
reject(
new Error(
'Event data is missing. Please provide it either via stdin or the args: data or path.'
)
);
}
}
});
}
emitEvent() {
const authToken = getAuthToken();
if (!authToken) {
return BbPromise.reject(new this.serverless.classes
.Error('Must be logged in to use this command. Please run "serverless login".'));
}
userStats.track('service_emitted');
const url = this.options.url || 'http://localhost:4000';
const eventGateway = fdk.eventGateway({
url,
});
const name = this.options.name;
const data = this.data;
const emitParams = {
event: name,
data,
};
if (this.options.datatype) {
emitParams.dataType = this.options.datatype;
}
return eventGateway
.emit(emitParams)
.then(() => {
const msg = `${prefix}Emitted the event ${name} as datatype ${emitParams.dataType ||
'application/json'}:`;
this.serverless.cli.consoleLog(`${msg}${os.EOL}${prettifyValue(data)}`);
})
.catch(() => {
const msg = `${prefix}Failed to emit the event ${name} as datatype ${emitParams.dataType ||
'application/json'}:`;
this.serverless.cli.consoleLog(`${msg}${os.EOL}${prettifyValue(data)}`);
throw new Error(`Failed to emit the event ${name}`);
});
}
}
module.exports = Emit;