diff --git a/src/commands/link.ts b/src/commands/link.ts index 40dece6d8..89a22cee4 100644 --- a/src/commands/link.ts +++ b/src/commands/link.ts @@ -48,11 +48,6 @@ export default class Link extends CustomCommand { )} flag to switch from the current ${ColorifyConstants.ID('account')} and ${ColorifyConstants.ID('workspace')}.`, required: false, }), - debug: oclifFlags.boolean({ - description: `Starts a debug tunnel (alpha)`, - default: false, - required: false, - }), } static args = [] @@ -60,9 +55,9 @@ export default class Link extends CustomCommand { async run() { const { flags, - flags: { account, setup, clean, unsafe, workspace, debug }, + flags: { account, setup, clean, unsafe, workspace }, } = this.parse(Link) const noWatch = flags['no-watch'] - await appLink({ account, workspace, setup, clean, unsafe, noWatch, debug }) + await appLink({ account, workspace, setup, clean, unsafe, noWatch }) } } diff --git a/src/modules/apps/debugger.ts b/src/modules/apps/debugger.ts deleted file mode 100644 index de5efbfe9..000000000 --- a/src/modules/apps/debugger.ts +++ /dev/null @@ -1,132 +0,0 @@ -import streamToString from 'get-stream' -import net from 'net' -import WebSocket from 'ws' -import { cluster } from '../../api/env' -import { Headers } from '../../api/constants/Headers' -import { ManifestEditor } from '../../api/manifest' -import { SessionManager } from '../../api/session/SessionManager' -import { versionMajor } from '../../api/locator' -import log from '../../api/logger' -import userAgent from '../../user-agent' - -const keepAliveDelayMs = 3 * 60 * 1000 -const THIRTY_SECONDS_MS = 30 * 1000 - -const wsCloseCodeGoingAway = 1001 -const wsCloseCodeError = 1011 -const DEFAULT_DEBUGGER_PORT = 9229 -const MAX_RETRY_COUNT = 40 - -function getErrorMessage(raw: string): string { - try { - const errJson = JSON.parse(raw) - return errJson.message || errJson.code || raw - } catch (err) { - return raw - } -} - -function webSocketTunnelHandler(host: string, path: string, server: net.Server): (socket: net.Socket) => void { - return (socket: net.Socket) => { - socket.setKeepAlive(true, keepAliveDelayMs) - const ws = new WebSocket(`wss://${host}${path}`, { - headers: { - Authorization: SessionManager.getSingleton().checkAndGetToken(true), - Host: host, - 'user-agent': userAgent, - [Headers.VTEX_RUNTIME_API]: 'true', - ...(cluster() ? { [Headers.VTEX_UPSTREAM_TARGET]: cluster() } : null), - }, - }) - - const interval = setInterval(ws.ping, THIRTY_SECONDS_MS) - - const end = () => { - clearInterval(interval) - ws.removeAllListeners() - socket.removeAllListeners() - socket.destroy() - } - - ws.on('close', end) - - ws.on('error', err => { - end() - log.error(`Debugger websocket error: ${err.name}: ${err.message}`) - }) - - ws.on('unexpected-response', async (_, res) => { - end() - const errMsg = getErrorMessage(await streamToString(res)) - log.warn(`Unexpected response from debugger hook (${res.statusCode}): ${errMsg}`) - - if (res.statusCode === 401 || res.statusCode === 403) { - log.warn(`Got unauthorized error from remote debugger, finalizing local debugger...`) - server.close() - } - }) - - ws.on('message', data => { - try { - socket.write(data) - } catch (err) { - end() - ws.close(wsCloseCodeError) - } - }) - - ws.on('open', () => { - socket.on('data', data => { - if (ws.readyState !== ws.OPEN) { - log.debug(`Tried to write to debugger websocket but it is not opened`) - return - } - ws.send(data, err => { - if (err) { - log.error(`Error writing to debugger websocket: ${err.name}: ${err.message}`) - } - }) - }) - - socket.on('close', hadError => { - end() - ws.close(hadError ? wsCloseCodeError : wsCloseCodeGoingAway) - }) - }) - } -} - -export default function startDebuggerTunnel( - manifest: ManifestEditor, - port: number = DEFAULT_DEBUGGER_PORT -): Promise { - const { name, vendor, version, builders } = manifest - const { node, 'service-js': serviceJs } = builders - if (!node && !serviceJs) { - return - } - - const { account, workspace } = SessionManager.getSingleton() - const appMajor = versionMajor(version) - const host = 'app.io.vtex.com' - const path = `/${vendor}.${name}/v${appMajor}/${account}/${workspace}/_debug/attach` - - return new Promise((resolve, reject) => { - const server = net.createServer() - server.on('connection', webSocketTunnelHandler(host, path, server)) - - server.on('error', err => { - if (port < DEFAULT_DEBUGGER_PORT + MAX_RETRY_COUNT) { - log.warn(`Port ${port} in use, will try to open tunnel on port ${port + 1}`) - resolve(startDebuggerTunnel(manifest, port + 1)) - } else { - reject(err) - } - }) - - server.listen(port, () => { - const addr = server.address() as net.AddressInfo - resolve(addr.port) - }) - }) -} diff --git a/src/modules/apps/link.ts b/src/modules/apps/link.ts index a75a9ce13..68a10c0e9 100644 --- a/src/modules/apps/link.ts +++ b/src/modules/apps/link.ts @@ -35,7 +35,6 @@ import debounce from 'debounce' import log from '../../api/logger' import moment from 'moment' import retry from 'async-retry' -import startDebuggerTunnel from './debugger' import workspaceUse from '../../api/modules/workspace/use' import { BatchStream } from '../../api/typings/types' import { Messages } from '../../lib/constants/Messages' @@ -54,7 +53,6 @@ interface LinkOptions { clean?: boolean setup?: boolean noWatch?: boolean - debug?: boolean } const DELETE_SIGN = chalk.red('D') @@ -315,36 +313,6 @@ export async function appLink(options: LinkOptions) { initial_link_required: () => warnAndLinkFromStart(root, projectUploader, unsafe), } - let debuggerStarted = false - const onBuild = async () => { - if (debuggerStarted) { - return - } - const startDebugger = async () => { - const port = await startDebuggerTunnel(manifest) - if (!port) { - throw new Error('Failed to start debugger.') - } - return port - } - if (options.debug && shouldStartDebugger(manifest)) { - // TODO: Add some sort of log here to know if devs are actually interested - // in this feature - try { - const debuggerPort = await retry(startDebugger, RETRY_OPTS_DEBUGGER) - // eslint-disable-next-line require-atomic-updates - debuggerStarted = true - log.info( - `Debugger tunnel listening on ${chalk.green(`:${debuggerPort}`)}. Go to ${chalk.blue( - 'chrome://inspect' - )} in Google Chrome to debug your running application.` - ) - } catch (e) { - log.error(e.message) - } - } - } - log.info(`Linking app ${appId}`) let unlistenBuild @@ -356,9 +324,7 @@ export async function appLink(options: LinkOptions) { await listenBuild(subject, buildTrigger, { waitCompletion: true }) return } - unlistenBuild = await listenBuild(subject, buildTrigger, { waitCompletion: false, onBuild, onError }).then( - prop('unlisten') - ) + unlistenBuild = await listenBuild(subject, buildTrigger, { waitCompletion: false, onError }).then(prop('unlisten')) } catch (e) { if (e.response) { const { data } = e.response