@twilio/plugin-microvisor
Version:
Interact with your Twilio Microvisor devices
106 lines (105 loc) • 5.29 kB
JavaScript
"use strict";
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 protobuf2tunnel_1 = require("../../lib/debug/proxy/protobuf2tunnel");
const encryption2tunnel_1 = require("../../lib/debug/proxy/encryption2tunnel");
const tunnel_1 = tslib_1.__importDefault(require("../../lib/debug/tunnel/tunnel"));
const gdb2protobuf_1 = require("../../lib/debug/proxy/gdb2protobuf");
const gdbserver_1 = require("../../lib/debug/proxy/gdbserver");
const hpke_1 = require("../../lib/debug/proxy/hpke");
const core_1 = require("@oclif/core");
const node_url_1 = require("node:url");
const node_process_1 = tslib_1.__importDefault(require("node:process"));
const node_fs_1 = tslib_1.__importDefault(require("node:fs"));
class MicrovisorDebugProxy extends TwilioClientCommand {
async run() {
await super.run();
const baseUriString = this.flags['microvisor-debug-url'];
let baseUri = new node_url_1.URL(baseUriString);
// 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(baseUriString)) {
baseUri.hostname = this.twilioClient.getHostname(baseUri.hostname, this.twilioClient.edge, this.twilioClient.region);
}
let debugKey;
try {
debugKey = new hpke_1.EcdhPrivateKey(node_fs_1.default.readFileSync(this.args.debugKey));
}
catch (error) {
this.logger.error('Failed to load private key: ' + error);
node_process_1.default.exit(1);
}
const uri = new node_url_1.URL('debug', baseUri);
var tunnelOptions = {
client: this.twilioClient,
deviceSid: this.args.deviceSid,
tunnelUrl: uri,
tokenBaseUrl: this.flags['microvisor-api-url'],
tokenUrl: this.flags['microvisor-api-token-url'] // defaults to undefined
};
this.tunnel = new tunnel_1.default(tunnelOptions);
this.tunnel.on('error', (error) => this.logger.error(error.message));
this.encryptionToTunnel = new encryption2tunnel_1.EncryptionToTunnel(this.tunnel, debugKey);
this.encryptionToTunnel.on('debug', (message) => this.logger.debug(message));
this.encryptionToTunnel.on('error', (message) => this.logger.error(message));
this.protobufToTunnel = new protobuf2tunnel_1.ProtobufToTunnel(this.encryptionToTunnel);
this.gdbToProtobuf = new gdb2protobuf_1.GdbToProtobuf(this.protobufToTunnel);
this.gdbToProtobuf.on('debug', (message) => this.logger.debug(new Date().toISOString() + message));
this.gdbToProtobuf.on('latency', (millis) => this.logger.debug('Round-trip latency measured as ' + millis + 'ms'));
this.gdbToProtobuf.on('telemetry', (type, data) => this.gdbToProtobuf.telemetry(type, data));
const port = this.flags['listen-port'];
this.gdbServer = new gdbserver_1.GdbServer(port, this.gdbToProtobuf);
this.gdbServer.on('info', (message) => this.logger.info(message));
this.gdbServer.on('debug', (message) => this.logger.debug(new Date().toISOString() + message));
process.on('SIGINT', async () => {
this.logger.debug('Shutting down...');
// Let GDB server close, exit anyway on timeout
setTimeout(node_process_1.default.exit, 1000);
await this.gdbToProtobuf.goodbye().catch((_error) => { });
this.tunnel.close();
});
this.gdbServer.on('close', () => {
this.logger.debug('GDB server stopped, shutting down');
this.tunnel.close();
node_process_1.default.exit();
});
}
async runCommand() {
return this.run();
}
}
exports.default = MicrovisorDebugProxy;
MicrovisorDebugProxy.args = [
{
name: 'deviceSid',
required: true,
description: 'The Sid of the device you wish to debug'
},
{
name: 'debugKey',
required: true,
description: 'Filename containing debug authentication private key'
}
];
MicrovisorDebugProxy.flags = Object.assign({ 'listen-port': core_1.Flags.integer({
description: 'The port on which the debug tunnel should listen',
default: 8001
}), '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
}), 'microvisor-api-token-url': core_1.Flags.string({
description: 'Full url to request an auth token',
hidden: true
}) }, TwilioClientCommand.flags);
// output format doesnt make sense here
delete MicrovisorDebugProxy.flags['cli-output-format'];
// nor does silent
delete MicrovisorDebugProxy.flags.silent;