in tools/vscode-azurewebpubsub/src/workflows/hubSetting/localTunnel/AttachLocalTunnelStep.ts [21:98]
public async execute(context: IPickHubSettingContext, progress: Progress<{ message?: string; increment?: number }>): Promise<void> {
if (!context.subscription || !context.serviceName || !context.resourceGroupName || !context.hubName) {
throw new Error(localize("invalidIPickHubSettingContext", "Invalid IPickHubSettingContext, subscription = {0}, serviceName = {1}, resourceGroupName = {2}, hubName = {3}",
context.subscription?.subscriptionId, context.serviceName, context.resourceGroupName, context.hubName));
}
progress.report( { message: localize("retrievingInfoForTunnel", "Retrieving information for tunnel tool on hub setting {0}", context.hubName) });
const resource = await this.client.webPubSub.get(context.resourceGroupName, context.serviceName);
const hub = await this.client.webPubSubHubs.get(context.hubName, context.resourceGroupName, context.serviceName);
// Step 1: Check if tunnel event handler exists. If not, add one
if (hub.properties.eventHandlers?.filter(e => e.urlTemplate === LOCAL_TUNNEL_TYPICAL_EVENT_HANDLER.urlTemplate).length === 0) {
const selection = await vscode.window.showInformationMessage(
localize("askAddTunnelEventHandler", "Hub {0} doesn't have a tunnel-enabled event handler. Do you want to add one?", hub.name),
...[ YES_LABEL, NO_LABEL ]
);
if (selection === NO_LABEL) {
// eslint-disable-next-line
vscode.window.showInformationMessage(localize(`noEventHandlerForTunnel`, `Event handler for tunnel is NOT found on target hub setting.`));
return ;
}
progress.report({ message: localize("configuringEventHandlerForTunnel", `Configuring event handler for tunnel tool on hub setting ${context.hubName}`)});
const tunnelEventHandler = {
urlTemplate: LOCAL_TUNNEL_TYPICAL_EVENT_HANDLER.urlTemplate,
userEventPattern: await inputUserEvents(context.ui),
systemEvents: await selectSystemEvents(context.ui)
};
const updatedEventHandlers = (hub.properties.eventHandlers ?? []).concat(tunnelEventHandler);
progress.report({ message: localize("creatingEventHandlerForTunnel", `Creating event handler for tunnel tool on hub setting ${context.hubName}`)});
await this.client.webPubSubHubs.beginCreateOrUpdateAndWait(context.hubName, context.resourceGroupName, context.serviceName,
{
properties: {
eventHandlers: updatedEventHandlers,
}
});
}
// Step 2: decide use connection string or credential
const tunnelOptionalParameter = { connectionString: "", endpoint: "" };
if (!resource.disableLocalAuth) {
progress.report({ message: localize(`retrievingConnectionString`, `Retrieving connection string, please wait...`)});
const connString = (await this.client.webPubSub.listKeys(context.resourceGroupName, context.serviceName)).primaryConnectionString;
if (!connString) {
throw new Error(localize(`noConnectionString`, `No connection string found for service {0}`, context.serviceName));
}
tunnelOptionalParameter.connectionString = connString;
}
else if (resource.hostName) {
// eslint-disable-next-line
vscode.window.showInformationMessage(localize(`confirmLocalTunnelAad`, `You have disabled access key. The tool will use Azure Identity.`));
tunnelOptionalParameter.endpoint = createEndpointFromHostName(resource.hostName);
} else {
throw new Error(localize(`noHostName`, `No host name found for service {0}`, context.serviceName));
}
// Step 3: create a new terminal to run tunnel tool. If exists, dispose the old one.
const terminal = createTerminalForTunnel(context.serviceName, context.hubName, true);
// Step 4: run the tunnel tool command
const upstreamPort = await context.ui.showInputBox({
prompt: localize(`inputUpstreamPort`, `Please input the port number of the upstream server`),
value: "3000",
validateInput: (value: string) => Number(value).toString() !== value ? localize(`invalidPortNumber`, `The port number should be a valid port number.`) : ""
});
const runTunnelCommand = getLocalTunnelParameterCommand(Number(upstreamPort), context.subscription.subscriptionId, context.resourceGroupName, context.hubName, tunnelOptionalParameter.connectionString, tunnelOptionalParameter.endpoint);
terminal.sendText(`node -e "${LOCAL_TUNNEL_INSTALL_OR_UPDATE_COMMAND}"`)
terminal.sendText(runTunnelCommand);
progress.report({ message: localize(`runningTunnelTool`, `Running tunnel tool. Please ensure Node.js is available in your terminal environment. If not, install Node.js from ${NODEJS_DOWNLOAD_URL}`)});
// Step 5: ask user if open the tunnel portal
const selection = await vscode.window.showInformationMessage(
localize("promptOpenTunnelPortal", "After the local tunnel is started, you could click the button below to open its Web portal"),
...[ localize("openTunnel", "Open Local Tunnel Portal"), localize("ignore", "Ignore") ]
);
if (selection === localize("openTunnel", "Open Local Tunnel Portal")) {
await vscode.env.openExternal(vscode.Uri.parse(`http://localhost:${(Number(upstreamPort) ?? 3000) + 1000}`));
}
}