@twilio/plugin-microvisor
Version:
Interact with your Twilio Microvisor devices
133 lines (132 loc) • 6.03 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TwilioClientCommand = void 0;
const tslib_1 = require("tslib");
const { TwilioClientCommand } = require('@twilio/cli-core').baseCommands;
exports.TwilioClientCommand = TwilioClientCommand;
const device_log_client_1 = tslib_1.__importDefault(require("../../../lib/logs/device-log-client"));
const core_1 = require("@oclif/core");
const node_url_1 = require("node:url");
const node_process_1 = tslib_1.__importDefault(require("node:process"));
const { TwilioCliError } = require('@twilio/cli-core').services.error;
class MicrovisorLogsStream extends TwilioClientCommand {
async run() {
await super.run();
if (!/^UV[\da-z]{32}$/.test(this.args.deviceSid)) {
throw new TwilioCliError('DEVICESID must be a sid starting with UV');
}
const apiBaseUrlString = this.flags['microvisor-api-url']; // defaults to 'https://microvisor.twilio.com/'
const logEnableUrl = new node_url_1.URL(`v1/Devices/${this.args.deviceSid}`, apiBaseUrlString);
const tokenUrl = new node_url_1.URL(`v1/Devices/${this.args.deviceSid}/LoggingToken`, apiBaseUrlString);
const baseWsUrlString = this.flags['microvisor-debug-url'];
let baseWsUrl = new node_url_1.URL(baseWsUrlString);
// Check configured tunnel domain ends in twilio.com. If it does, perform the same mangling as the http
// client. If not, leave things alone (this is probably a Twilion trying to hit a test endpoint)
if (/^[^:]+:\/\/[^/]+\.twilio\.com/.test(baseWsUrlString)) {
baseWsUrl.hostname = this.twilioClient.getHostname(baseWsUrl.hostname, this.twilioClient.edge, this.twilioClient.region);
}
const websocketUrl = new node_url_1.URL('logging', baseWsUrl);
// If the configured logging token domain ends in twilio.com, use the twilio client,
// otherwise use a simpler http client which doesn't mangle the domain
let apiClient = null;
let tokenRequestOpts = {
method: 'POST',
uri: tokenUrl.toString()
};
let enableLoggingRequestOpts = {
method: 'POST',
uri: logEnableUrl.toString(),
data: { LoggingEnabled: true }
};
if (/^[^:]+:\/\/[^/]+\.twilio\.com/.test(apiBaseUrlString)) {
apiClient = this.twilioClient;
}
else {
apiClient = this.httpClient;
tokenRequestOpts.username = this.currentProfile.apiKey;
enableLoggingRequestOpts.username = this.currentProfile.apiKey;
tokenRequestOpts.password = this.currentProfile.apiSecret;
enableLoggingRequestOpts.password = this.currentProfile.apiSecret;
}
const streamOptions = {
twilioClient: apiClient,
tokenRequestOpts: tokenRequestOpts,
enableLoggingRequestOpts: enableLoggingRequestOpts,
websocketUrl: websocketUrl
};
this.stream = new device_log_client_1.default(streamOptions);
this.stream.on('open', () => {
this.logger.debug('Websocket connected');
});
this.stream.on('connectFailed', (message) => {
this.logger.error(message);
});
this.stream.on('log', (logLine) => {
const output = formatLogMessage(logLine, this.flags['cli-output-format']);
console.log('%s', output);
});
this.stream.on('error', (error) => this.logger.error(error.message));
process.on('SIGINT', async () => {
this.logger.debug('Shutting down...');
setTimeout(node_process_1.default.exit, 1000);
this.stream.close();
});
}
async runCommand() {
return this.run();
}
}
exports.default = MicrovisorLogsStream;
MicrovisorLogsStream.args = [
{
name: 'deviceSid',
required: true,
description: 'The Sid of the device you wish to stream logging from'
}
];
function formatLogMessage(jsonLog, format) {
var logLine;
switch (format) {
case 'json':
logLine = `${jsonLog}`;
break;
default:
logLine = formatForTextOutput(jsonLog);
}
return logLine;
}
function formatForTextOutput(jsonLog) {
var logData = JSON.parse(jsonLog);
// the longest category we publish is "[app_logging]" so 13 chars is the optimal padding
var paddedCategory = `[${logData.category}]`.padEnd(13, ' ');
// special case app crash lines, they arrive as json, add a header and pretty print
switch (logData.category) {
case 'app_crash':
// parse the embedded json, and pretty print
var crashStructured = JSON.parse(logData.message);
return `${logData.timestamp} ${paddedCategory} Crash Report:\n${JSON.stringify(crashStructured, null, 2)}`;
default:
// strip trailing newlines off, unlikely to be intentional when used in text mode
return `${logData.timestamp} ${paddedCategory} ${logData.message.trim()}`;
}
}
// remove some of the base output implementations
delete MicrovisorLogsStream.flags['cli-output-format'];
delete MicrovisorLogsStream.flags.silent;
MicrovisorLogsStream.flags = Object.assign({
// replace the base output flag format, we only support json or text (text)
'cli-output-format': core_1.Flags.string({
char: 'o',
helpLabel: '-o',
default: 'text',
options: ['json', 'text'],
description: 'Format of command output.'
}), 'microvisor-debug-url': core_1.Flags.string({
description: 'First part of the url for the microvisor-debug endpoint',
default: 'wss://microvisor-debug.us1.twilio.com',
hidden: true
}), 'microvisor-api-url': core_1.Flags.string({
description: 'First part of the url for microvisor api',
default: 'https://microvisor.twilio.com/',
hidden: true
}) }, TwilioClientCommand.flags);