@expo/ngrok
Version:
node wrapper for ngrok
85 lines (75 loc) • 1.87 kB
JavaScript
const { NgrokClient, NgrokClientError } = require("./src/client");
const uuid = require("uuid");
const {
getProcess,
getActiveProcess,
killProcess,
setAuthtoken,
getVersion,
} = require("./src/process");
const { defaults, validate, isRetriable } = require("./src/utils");
let processUrl = null;
let ngrokClient = null;
async function connect(opts) {
opts = defaults(opts);
validate(opts);
if (opts.authtoken) {
await setAuthtoken(opts);
}
processUrl = await getProcess(opts);
ngrokClient = new NgrokClient(processUrl);
return connectRetry(opts);
}
async function connectRetry(opts, retryCount = 0) {
opts.name = String(opts.name || uuid.v4());
try {
const response = await ngrokClient.startTunnel(opts);
return response.public_url;
} catch (err) {
if (!isRetriable(err) || retryCount >= 100) {
throw err;
}
await new Promise((resolve) => setTimeout(resolve, 200));
return connectRetry(opts, ++retryCount);
}
}
async function disconnect(publicUrl) {
if (!ngrokClient) return;
const tunnels = (await ngrokClient.listTunnels()).tunnels;
if (!publicUrl) {
const disconnectAll = tunnels.map((tunnel) =>
disconnect(tunnel.public_url)
);
return Promise.all(disconnectAll);
}
const tunnelDetails = tunnels.find(
(tunnel) => tunnel.public_url === publicUrl
);
if (!tunnelDetails) {
throw new Error(`there is no tunnel with url: ${publicUrl}`);
}
return ngrokClient.stopTunnel(tunnelDetails.name);
}
async function kill() {
if (!ngrokClient) return;
await killProcess();
ngrokClient = null;
tunnels = {};
}
function getUrl() {
return processUrl;
}
function getApi() {
return ngrokClient;
}
module.exports = {
connect,
disconnect,
authtoken: setAuthtoken,
kill,
getUrl,
getApi,
getVersion,
getActiveProcess,
NgrokClientError
};