nbound 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/nbound.js +226 -91
- package/dist/index.js +227 -92
- package/dist/index.js.map +7 -9
- package/package.json +8 -3
package/dist/index.js
CHANGED
|
@@ -5221,7 +5221,7 @@ var require_websocket = __commonJS((exports, module) => {
|
|
|
5221
5221
|
var http = __require("http");
|
|
5222
5222
|
var net = __require("net");
|
|
5223
5223
|
var tls = __require("tls");
|
|
5224
|
-
var { randomBytes:
|
|
5224
|
+
var { randomBytes: randomBytes3, createHash } = __require("crypto");
|
|
5225
5225
|
var { Duplex, Readable } = __require("stream");
|
|
5226
5226
|
var { URL: URL2 } = __require("url");
|
|
5227
5227
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -5630,7 +5630,7 @@ var require_websocket = __commonJS((exports, module) => {
|
|
|
5630
5630
|
}
|
|
5631
5631
|
}
|
|
5632
5632
|
const defaultPort = isSecure ? 443 : 80;
|
|
5633
|
-
const key =
|
|
5633
|
+
const key = randomBytes3(16).toString("base64");
|
|
5634
5634
|
const request2 = isSecure ? https.request : http.request;
|
|
5635
5635
|
const protocolSet = new Set;
|
|
5636
5636
|
let perMessageDeflate;
|
|
@@ -6439,7 +6439,8 @@ var {
|
|
|
6439
6439
|
} = import__.default;
|
|
6440
6440
|
|
|
6441
6441
|
// src/commands/login.ts
|
|
6442
|
-
import {
|
|
6442
|
+
import { createServer } from "node:http";
|
|
6443
|
+
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
6443
6444
|
|
|
6444
6445
|
// ../../node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
|
|
6445
6446
|
import process7 from "node:process";
|
|
@@ -6938,36 +6939,6 @@ defineLazyProperty(apps, "browser", () => "browser");
|
|
|
6938
6939
|
defineLazyProperty(apps, "browserPrivate", () => "browserPrivate");
|
|
6939
6940
|
var open_default = open;
|
|
6940
6941
|
|
|
6941
|
-
// ../../node_modules/.pnpm/nanoid@5.1.6/node_modules/nanoid/index.js
|
|
6942
|
-
import { webcrypto as crypto } from "node:crypto";
|
|
6943
|
-
|
|
6944
|
-
// ../../node_modules/.pnpm/nanoid@5.1.6/node_modules/nanoid/url-alphabet/index.js
|
|
6945
|
-
var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
|
|
6946
|
-
|
|
6947
|
-
// ../../node_modules/.pnpm/nanoid@5.1.6/node_modules/nanoid/index.js
|
|
6948
|
-
var POOL_SIZE_MULTIPLIER = 128;
|
|
6949
|
-
var pool;
|
|
6950
|
-
var poolOffset;
|
|
6951
|
-
function fillPool(bytes) {
|
|
6952
|
-
if (!pool || pool.length < bytes) {
|
|
6953
|
-
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
|
|
6954
|
-
crypto.getRandomValues(pool);
|
|
6955
|
-
poolOffset = 0;
|
|
6956
|
-
} else if (poolOffset + bytes > pool.length) {
|
|
6957
|
-
crypto.getRandomValues(pool);
|
|
6958
|
-
poolOffset = 0;
|
|
6959
|
-
}
|
|
6960
|
-
poolOffset += bytes;
|
|
6961
|
-
}
|
|
6962
|
-
function nanoid(size = 21) {
|
|
6963
|
-
fillPool(size |= 0);
|
|
6964
|
-
let id = "";
|
|
6965
|
-
for (let i = poolOffset - size;i < poolOffset; i++) {
|
|
6966
|
-
id += urlAlphabet[pool[i] & 63];
|
|
6967
|
-
}
|
|
6968
|
-
return id;
|
|
6969
|
-
}
|
|
6970
|
-
|
|
6971
6942
|
// src/lib/config.ts
|
|
6972
6943
|
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, renameSync, chmodSync } from "node:fs";
|
|
6973
6944
|
import { homedir } from "node:os";
|
|
@@ -7164,20 +7135,6 @@ async function createEndpoint(token, input) {
|
|
|
7164
7135
|
});
|
|
7165
7136
|
return result;
|
|
7166
7137
|
}
|
|
7167
|
-
async function exchangeCliCode(sessionId, code) {
|
|
7168
|
-
const apiUrl = getApiUrl();
|
|
7169
|
-
const response = await fetch(`${apiUrl}/api/auth/cli-exchange`, {
|
|
7170
|
-
method: "POST",
|
|
7171
|
-
headers: { "Content-Type": "application/json" },
|
|
7172
|
-
body: JSON.stringify({ sessionId, code }),
|
|
7173
|
-
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
7174
|
-
});
|
|
7175
|
-
const json = await response.json();
|
|
7176
|
-
if (!response.ok || !json.success) {
|
|
7177
|
-
throw new ApiError(response.status, json.error?.code ?? "UNKNOWN_ERROR", json.error?.message ?? "Failed to exchange code");
|
|
7178
|
-
}
|
|
7179
|
-
return json.data;
|
|
7180
|
-
}
|
|
7181
7138
|
async function revokeCliToken(token) {
|
|
7182
7139
|
const apiUrl = getApiUrl();
|
|
7183
7140
|
try {
|
|
@@ -8553,18 +8510,130 @@ function createSpinner(text) {
|
|
|
8553
8510
|
}
|
|
8554
8511
|
|
|
8555
8512
|
// src/commands/login.ts
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8513
|
+
var DEFAULT_PORT = 9847;
|
|
8514
|
+
var PORT_RANGE_START = 9800;
|
|
8515
|
+
var PORT_RANGE_END = 9900;
|
|
8516
|
+
var AUTH_TIMEOUT_MS = 2 * 60 * 1000;
|
|
8517
|
+
function tryPort(port) {
|
|
8561
8518
|
return new Promise((resolve) => {
|
|
8562
|
-
|
|
8563
|
-
|
|
8564
|
-
|
|
8519
|
+
const server = createServer();
|
|
8520
|
+
server.once("error", (err) => {
|
|
8521
|
+
if (err.code === "EADDRINUSE") {
|
|
8522
|
+
resolve(null);
|
|
8523
|
+
} else {
|
|
8524
|
+
resolve(null);
|
|
8525
|
+
}
|
|
8526
|
+
});
|
|
8527
|
+
server.listen(port, "127.0.0.1", () => {
|
|
8528
|
+
resolve(server);
|
|
8565
8529
|
});
|
|
8566
8530
|
});
|
|
8567
8531
|
}
|
|
8532
|
+
async function findAvailablePort() {
|
|
8533
|
+
const defaultServer = await tryPort(DEFAULT_PORT);
|
|
8534
|
+
if (defaultServer) {
|
|
8535
|
+
return { server: defaultServer, port: DEFAULT_PORT };
|
|
8536
|
+
}
|
|
8537
|
+
for (let i = 0;i < 10; i++) {
|
|
8538
|
+
const port = PORT_RANGE_START + Math.floor(Math.random() * (PORT_RANGE_END - PORT_RANGE_START));
|
|
8539
|
+
const server = await tryPort(port);
|
|
8540
|
+
if (server) {
|
|
8541
|
+
return { server, port };
|
|
8542
|
+
}
|
|
8543
|
+
}
|
|
8544
|
+
return null;
|
|
8545
|
+
}
|
|
8546
|
+
function generateState() {
|
|
8547
|
+
return randomBytes2(16).toString("hex");
|
|
8548
|
+
}
|
|
8549
|
+
var SUCCESS_HTML = `<!DOCTYPE html>
|
|
8550
|
+
<html>
|
|
8551
|
+
<head>
|
|
8552
|
+
<title>Authenticated - nbound</title>
|
|
8553
|
+
<style>
|
|
8554
|
+
body {
|
|
8555
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
8556
|
+
display: flex;
|
|
8557
|
+
justify-content: center;
|
|
8558
|
+
align-items: center;
|
|
8559
|
+
min-height: 100vh;
|
|
8560
|
+
margin: 0;
|
|
8561
|
+
background: #0a0a0a;
|
|
8562
|
+
color: #fafafa;
|
|
8563
|
+
}
|
|
8564
|
+
.container {
|
|
8565
|
+
text-align: center;
|
|
8566
|
+
padding: 2rem;
|
|
8567
|
+
}
|
|
8568
|
+
.icon {
|
|
8569
|
+
font-size: 4rem;
|
|
8570
|
+
margin-bottom: 1rem;
|
|
8571
|
+
}
|
|
8572
|
+
h1 {
|
|
8573
|
+
font-size: 1.5rem;
|
|
8574
|
+
font-weight: 600;
|
|
8575
|
+
margin: 0 0 0.5rem;
|
|
8576
|
+
}
|
|
8577
|
+
p {
|
|
8578
|
+
color: #a1a1aa;
|
|
8579
|
+
margin: 0;
|
|
8580
|
+
}
|
|
8581
|
+
</style>
|
|
8582
|
+
</head>
|
|
8583
|
+
<body>
|
|
8584
|
+
<div class="container">
|
|
8585
|
+
<div class="icon">✓</div>
|
|
8586
|
+
<h1>Authenticated!</h1>
|
|
8587
|
+
<p>You can close this tab and return to your terminal.</p>
|
|
8588
|
+
</div>
|
|
8589
|
+
<script>window.close()</script>
|
|
8590
|
+
</body>
|
|
8591
|
+
</html>`;
|
|
8592
|
+
function errorHtml(message) {
|
|
8593
|
+
return `<!DOCTYPE html>
|
|
8594
|
+
<html>
|
|
8595
|
+
<head>
|
|
8596
|
+
<title>Authentication Failed - nbound</title>
|
|
8597
|
+
<style>
|
|
8598
|
+
body {
|
|
8599
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
8600
|
+
display: flex;
|
|
8601
|
+
justify-content: center;
|
|
8602
|
+
align-items: center;
|
|
8603
|
+
min-height: 100vh;
|
|
8604
|
+
margin: 0;
|
|
8605
|
+
background: #0a0a0a;
|
|
8606
|
+
color: #fafafa;
|
|
8607
|
+
}
|
|
8608
|
+
.container {
|
|
8609
|
+
text-align: center;
|
|
8610
|
+
padding: 2rem;
|
|
8611
|
+
}
|
|
8612
|
+
.icon {
|
|
8613
|
+
font-size: 4rem;
|
|
8614
|
+
margin-bottom: 1rem;
|
|
8615
|
+
color: #ef4444;
|
|
8616
|
+
}
|
|
8617
|
+
h1 {
|
|
8618
|
+
font-size: 1.5rem;
|
|
8619
|
+
font-weight: 600;
|
|
8620
|
+
margin: 0 0 0.5rem;
|
|
8621
|
+
}
|
|
8622
|
+
p {
|
|
8623
|
+
color: #a1a1aa;
|
|
8624
|
+
margin: 0;
|
|
8625
|
+
}
|
|
8626
|
+
</style>
|
|
8627
|
+
</head>
|
|
8628
|
+
<body>
|
|
8629
|
+
<div class="container">
|
|
8630
|
+
<div class="icon">✗</div>
|
|
8631
|
+
<h1>Authentication Failed</h1>
|
|
8632
|
+
<p>${message}</p>
|
|
8633
|
+
</div>
|
|
8634
|
+
</body>
|
|
8635
|
+
</html>`;
|
|
8636
|
+
}
|
|
8568
8637
|
async function loginCommand(options) {
|
|
8569
8638
|
const existingConfig = loadConfig();
|
|
8570
8639
|
if (existingConfig && !options.token) {
|
|
@@ -8574,15 +8643,15 @@ async function loginCommand(options) {
|
|
|
8574
8643
|
const expiry = checkTokenExpiry(existingConfig);
|
|
8575
8644
|
if (expiry === "expiring_soon") {
|
|
8576
8645
|
const daysLeft = getDaysUntilExpiry(existingConfig);
|
|
8577
|
-
log.warning(`Your token expires in ${daysLeft} day${daysLeft === 1 ? "" : "s"}. Run: nbound
|
|
8646
|
+
log.warning(`Your token expires in ${daysLeft} day${daysLeft === 1 ? "" : "s"}. Run: nbound logout && nbound login`);
|
|
8578
8647
|
}
|
|
8579
8648
|
log.dim("Run: nbound logout to switch accounts");
|
|
8580
8649
|
return;
|
|
8581
8650
|
} catch {}
|
|
8582
8651
|
}
|
|
8583
8652
|
if (options.token) {
|
|
8584
|
-
const
|
|
8585
|
-
|
|
8653
|
+
const spinner = createSpinner("Validating token...");
|
|
8654
|
+
spinner.start();
|
|
8586
8655
|
try {
|
|
8587
8656
|
const user = await getUser(options.token);
|
|
8588
8657
|
const apiUrl2 = getApiUrl();
|
|
@@ -8592,21 +8661,70 @@ async function loginCommand(options) {
|
|
|
8592
8661
|
apiUrl: apiUrl2,
|
|
8593
8662
|
wsUrl: apiUrl2.replace("https://", "wss://").replace("http://", "ws://") + "/ws"
|
|
8594
8663
|
});
|
|
8595
|
-
|
|
8664
|
+
spinner.succeed(`Logged in as ${user.email}`);
|
|
8596
8665
|
} catch (error) {
|
|
8597
|
-
|
|
8666
|
+
spinner.fail("Invalid token");
|
|
8598
8667
|
if (error instanceof ApiError) {
|
|
8599
8668
|
log.error(error.message);
|
|
8600
8669
|
}
|
|
8601
|
-
process.exit(
|
|
8670
|
+
process.exit(1);
|
|
8602
8671
|
}
|
|
8603
8672
|
return;
|
|
8604
8673
|
}
|
|
8605
|
-
const sessionId = nanoid(21);
|
|
8606
|
-
const apiUrl = getApiUrl();
|
|
8607
|
-
const appUrl = apiUrl.replace("://api.", "://app.");
|
|
8608
|
-
const authUrl = `${appUrl}/cli/auth?session=${sessionId}`;
|
|
8609
8674
|
log.blank();
|
|
8675
|
+
const portResult = await findAvailablePort();
|
|
8676
|
+
if (!portResult) {
|
|
8677
|
+
log.error("Could not find an available port for authentication callback.");
|
|
8678
|
+
log.dim("Try closing other applications or run: nbound login --token <token>");
|
|
8679
|
+
process.exit(1);
|
|
8680
|
+
}
|
|
8681
|
+
const { server, port } = portResult;
|
|
8682
|
+
const state = generateState();
|
|
8683
|
+
const apiUrl = getApiUrl();
|
|
8684
|
+
const redirectUrl = `http://localhost:${port}/callback`;
|
|
8685
|
+
const authUrl = `${apiUrl}/api/cli/auth?redirect=${encodeURIComponent(redirectUrl)}&state=${state}`;
|
|
8686
|
+
const timeoutHandle = setTimeout(() => {
|
|
8687
|
+
server.close();
|
|
8688
|
+
log.blank();
|
|
8689
|
+
log.error("Authentication timed out after 2 minutes.");
|
|
8690
|
+
log.dim("Please try again: nbound login");
|
|
8691
|
+
process.exit(1);
|
|
8692
|
+
}, AUTH_TIMEOUT_MS);
|
|
8693
|
+
const authPromise = new Promise((resolve, reject) => {
|
|
8694
|
+
server.on("request", (req, res) => {
|
|
8695
|
+
const url = new URL(req.url || "/", `http://localhost:${port}`);
|
|
8696
|
+
if (url.pathname !== "/callback") {
|
|
8697
|
+
res.writeHead(404);
|
|
8698
|
+
res.end("Not found");
|
|
8699
|
+
return;
|
|
8700
|
+
}
|
|
8701
|
+
const receivedState = url.searchParams.get("state");
|
|
8702
|
+
const token = url.searchParams.get("token");
|
|
8703
|
+
const error = url.searchParams.get("error");
|
|
8704
|
+
const expiresAt = url.searchParams.get("expiresAt");
|
|
8705
|
+
if (error) {
|
|
8706
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
8707
|
+
res.end(errorHtml(error));
|
|
8708
|
+
reject(new Error(error));
|
|
8709
|
+
return;
|
|
8710
|
+
}
|
|
8711
|
+
if (receivedState !== state) {
|
|
8712
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
8713
|
+
res.end(errorHtml("Security validation failed. Please try again."));
|
|
8714
|
+
reject(new Error("State mismatch - possible CSRF attack"));
|
|
8715
|
+
return;
|
|
8716
|
+
}
|
|
8717
|
+
if (!token) {
|
|
8718
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
8719
|
+
res.end(errorHtml("No authentication token received."));
|
|
8720
|
+
reject(new Error("No token received"));
|
|
8721
|
+
return;
|
|
8722
|
+
}
|
|
8723
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
8724
|
+
res.end(SUCCESS_HTML);
|
|
8725
|
+
resolve({ token, expiresAt: expiresAt || undefined });
|
|
8726
|
+
});
|
|
8727
|
+
});
|
|
8610
8728
|
log.info("Opening browser to authenticate...");
|
|
8611
8729
|
log.dim(authUrl);
|
|
8612
8730
|
log.blank();
|
|
@@ -8617,31 +8735,37 @@ async function loginCommand(options) {
|
|
|
8617
8735
|
log.info("Please open this URL in your browser:");
|
|
8618
8736
|
log.info(authUrl);
|
|
8619
8737
|
}
|
|
8620
|
-
log.
|
|
8621
|
-
const code = await prompt("Enter the code from the browser: ");
|
|
8622
|
-
if (!code) {
|
|
8623
|
-
log.error("No code provided");
|
|
8624
|
-
process.exit(4);
|
|
8625
|
-
}
|
|
8626
|
-
const spinner = createSpinner("Verifying code...");
|
|
8627
|
-
spinner.start();
|
|
8738
|
+
log.dim("Waiting for authentication...");
|
|
8628
8739
|
try {
|
|
8629
|
-
const { token,
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8637
|
-
|
|
8638
|
-
|
|
8639
|
-
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8740
|
+
const { token, expiresAt } = await authPromise;
|
|
8741
|
+
clearTimeout(timeoutHandle);
|
|
8742
|
+
server.close();
|
|
8743
|
+
const spinner = createSpinner("Verifying token...");
|
|
8744
|
+
spinner.start();
|
|
8745
|
+
try {
|
|
8746
|
+
const user = await getUser(token);
|
|
8747
|
+
saveConfig({
|
|
8748
|
+
token,
|
|
8749
|
+
user: { id: user.id, email: user.email },
|
|
8750
|
+
apiUrl,
|
|
8751
|
+
wsUrl: apiUrl.replace("https://", "wss://").replace("http://", "ws://") + "/ws",
|
|
8752
|
+
expiresAt
|
|
8753
|
+
});
|
|
8754
|
+
spinner.succeed(`Logged in as ${user.email}`);
|
|
8755
|
+
log.blank();
|
|
8756
|
+
} catch (error) {
|
|
8757
|
+
spinner.fail("Failed to verify token");
|
|
8758
|
+
if (error instanceof ApiError) {
|
|
8759
|
+
log.error(error.message);
|
|
8760
|
+
}
|
|
8761
|
+
process.exit(1);
|
|
8643
8762
|
}
|
|
8644
|
-
|
|
8763
|
+
} catch (error) {
|
|
8764
|
+
clearTimeout(timeoutHandle);
|
|
8765
|
+
server.close();
|
|
8766
|
+
log.blank();
|
|
8767
|
+
log.error(error instanceof Error ? error.message : "Authentication failed");
|
|
8768
|
+
process.exit(1);
|
|
8645
8769
|
}
|
|
8646
8770
|
}
|
|
8647
8771
|
|
|
@@ -12794,7 +12918,7 @@ function getBackoffDelay(attempt, baseMs = 1000, maxMs = 30000, jitter = true) {
|
|
|
12794
12918
|
// src/lib/ws-client.ts
|
|
12795
12919
|
var PING_INTERVAL_MS = 30000;
|
|
12796
12920
|
var PONG_TIMEOUT_MS = 1e4;
|
|
12797
|
-
var
|
|
12921
|
+
var AUTH_TIMEOUT_MS2 = 1e4;
|
|
12798
12922
|
|
|
12799
12923
|
class WebSocketClient {
|
|
12800
12924
|
ws = null;
|
|
@@ -12849,10 +12973,15 @@ class WebSocketClient {
|
|
|
12849
12973
|
this.options.onError(new Error(`Connection closed during auth: ${reasonStr}`));
|
|
12850
12974
|
} else if (this.shouldReconnect && prevState === "connecting") {
|
|
12851
12975
|
this.scheduleReconnect();
|
|
12976
|
+
} else if (this.shouldReconnect && prevState === "authenticated") {
|
|
12977
|
+
this.scheduleReconnect();
|
|
12852
12978
|
}
|
|
12853
12979
|
});
|
|
12854
12980
|
this.ws.on("error", (error) => {
|
|
12855
12981
|
if (this.state !== "subscribed" && this.shouldReconnect) {
|
|
12982
|
+
if (this.state === "authenticated" || this.state === "authenticating") {
|
|
12983
|
+
this.options.onDisconnected(`Connection error: ${error.message}`);
|
|
12984
|
+
}
|
|
12856
12985
|
this.scheduleReconnect();
|
|
12857
12986
|
} else {
|
|
12858
12987
|
this.options.onError(error);
|
|
@@ -12907,6 +13036,12 @@ class WebSocketClient {
|
|
|
12907
13036
|
this.disconnect();
|
|
12908
13037
|
break;
|
|
12909
13038
|
}
|
|
13039
|
+
case "session_replaced": {
|
|
13040
|
+
this.shouldReconnect = false;
|
|
13041
|
+
this.options.onError(new Error("Another CLI session connected to this endpoint."));
|
|
13042
|
+
this.disconnect();
|
|
13043
|
+
break;
|
|
13044
|
+
}
|
|
12910
13045
|
case "plan_changed": {
|
|
12911
13046
|
const payload = message.payload;
|
|
12912
13047
|
this.plan = payload.plan;
|
|
@@ -13012,7 +13147,7 @@ class WebSocketClient {
|
|
|
13012
13147
|
this.options.onError(new Error("Authentication timed out"));
|
|
13013
13148
|
this.disconnect();
|
|
13014
13149
|
}
|
|
13015
|
-
},
|
|
13150
|
+
}, AUTH_TIMEOUT_MS2);
|
|
13016
13151
|
}
|
|
13017
13152
|
clearAuthTimeout() {
|
|
13018
13153
|
if (this.authTimeout) {
|
|
@@ -13578,7 +13713,7 @@ async function createCommand2(nameArg, options) {
|
|
|
13578
13713
|
}
|
|
13579
13714
|
|
|
13580
13715
|
// src/index.ts
|
|
13581
|
-
program.name("nbound").description("Forward webhooks to localhost for development").version("1.0
|
|
13716
|
+
program.name("nbound").description("Forward webhooks to localhost for development").version("1.1.0");
|
|
13582
13717
|
program.command("login").description("Authenticate with nbound").option("--token <token>", "Use an existing API token").action(loginCommand);
|
|
13583
13718
|
program.command("logout").description("Clear stored credentials").action(logoutCommand);
|
|
13584
13719
|
program.command("whoami").description("Show current authenticated user").action(whoamiCommand);
|
|
@@ -13587,5 +13722,5 @@ program.command("endpoints").description("List your endpoints").option("--json",
|
|
|
13587
13722
|
program.command("create [name]").description("Create a new endpoint").option("-n, --name <name>", "Endpoint name").option("-d, --description <description>", "Endpoint description").action(createCommand2);
|
|
13588
13723
|
program.parse();
|
|
13589
13724
|
|
|
13590
|
-
//# debugId=
|
|
13725
|
+
//# debugId=C24205CDBF507F4264756E2164756E21
|
|
13591
13726
|
//# sourceMappingURL=index.js.map
|