relionhq 2.0.0 → 2.0.2

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.
Files changed (2) hide show
  1. package/dist/index.js +86 -28
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ var path = __toESM(require("path"));
32
32
  var os = __toESM(require("os"));
33
33
  var GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".relion");
34
34
  var GLOBAL_CONFIG_PATH = path.join(GLOBAL_CONFIG_DIR, "config.json");
35
- var DEFAULT_API_URL = "https://relion.dev";
35
+ var DEFAULT_API_URL = "https://relionapi.com";
36
36
  function readGlobalConfig() {
37
37
  try {
38
38
  const raw = fs.readFileSync(GLOBAL_CONFIG_PATH, "utf8");
@@ -600,35 +600,89 @@ async function verifyToken(token, apiUrl) {
600
600
  }
601
601
 
602
602
  // src/commands/login.ts
603
+ var http = __toESM(require("http"));
604
+ var net = __toESM(require("net"));
605
+ var import_child_process2 = require("child_process");
606
+ var DEFAULT_API_URL2 = "https://relionapi.com";
603
607
  async function loginCommand(flags) {
604
- const apiUrl = flags.url ?? process.env.RELION_API_URL ?? "https://relion.dev";
608
+ const apiUrl = (flags.url ?? process.env.RELION_API_URL ?? DEFAULT_API_URL2).replace(/\/$/, "");
605
609
  if (flags.token) {
606
- await saveToken(flags.token, apiUrl);
610
+ await saveAndVerifyToken(flags.token, apiUrl);
607
611
  return;
608
612
  }
609
- const loginUrl = `${apiUrl}/settings/tokens`;
613
+ await browserLogin(apiUrl);
614
+ }
615
+ async function browserLogin(apiUrl) {
616
+ const port = await getFreePort();
617
+ const callbackUrl = `http://localhost:${port}`;
618
+ const authUrl = `${apiUrl}/cli-auth?callback=${encodeURIComponent(callbackUrl)}`;
610
619
  console.log(`
611
620
  ${color.bold("Relion Login")}
612
621
  `);
613
- console.log(`Create an API token at:
614
- ${color.cyan(loginUrl)}
615
- `);
616
- console.log(`Then run:
617
- ${color.dim("relion login --token <your-token>")}
618
- `);
619
- }
620
- async function saveToken(token, apiUrl) {
622
+ printInfo("Opening browser for authentication\u2026");
621
623
  console.log(`
622
- ${color.bold("Relion Login")}
624
+ ${color.dim("If it doesn't open automatically, visit:")}`);
625
+ console.log(` ${color.cyan(authUrl)}
623
626
  `);
624
- printInfo("Verifying token...");
627
+ openBrowser(authUrl);
628
+ const token = await waitForCallback(port);
629
+ if (!token) {
630
+ printError("Login timed out or was cancelled.", "Run relion login again.");
631
+ process.exit(1);
632
+ }
633
+ await saveAndVerifyToken(token, apiUrl);
634
+ }
635
+ function getFreePort() {
636
+ return new Promise((resolve3, reject) => {
637
+ const server = net.createServer();
638
+ server.unref();
639
+ server.listen(0, "127.0.0.1", () => {
640
+ const addr = server.address();
641
+ server.close(() => resolve3(addr.port));
642
+ });
643
+ server.on("error", reject);
644
+ });
645
+ }
646
+ function openBrowser(url) {
647
+ const cmd = process.platform === "win32" ? `start "" "${url}"` : process.platform === "darwin" ? `open "${url}"` : `xdg-open "${url}"`;
648
+ (0, import_child_process2.exec)(cmd, () => {
649
+ });
650
+ }
651
+ function waitForCallback(port, timeoutMs = 5 * 60 * 1e3) {
652
+ return new Promise((resolve3) => {
653
+ const timer = setTimeout(() => {
654
+ server.closeAllConnections();
655
+ server.close();
656
+ resolve3(null);
657
+ }, timeoutMs);
658
+ const server = http.createServer((req, res) => {
659
+ const url = new URL(req.url ?? "/", `http://localhost:${port}`);
660
+ const token = url.searchParams.get("token");
661
+ const html = `<!DOCTYPE html><html><head><meta charset="utf-8">
662
+ <style>body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#070a12;color:#e2e8f0}
663
+ .box{text-align:center;padding:2rem;max-width:320px}h1{font-size:1.1rem;margin-bottom:.5rem;color:#4fd1c5}p{font-size:.85rem;color:#94a3b8}</style>
664
+ </head><body><div class="box"><h1>${token ? "\u2713 Authenticated" : "\u2717 No token received"}</h1>
665
+ <p>${token ? "You can close this tab and return to your terminal." : "Something went wrong. Run relion login again."}</p></div></body></html>`;
666
+ res.writeHead(200, { "Content-Type": "text/html", "Connection": "close" });
667
+ res.end(html, () => {
668
+ clearTimeout(timer);
669
+ server.closeAllConnections();
670
+ server.close();
671
+ resolve3(token ?? null);
672
+ });
673
+ });
674
+ server.listen(port, "127.0.0.1");
675
+ });
676
+ }
677
+ async function saveAndVerifyToken(token, apiUrl) {
678
+ printInfo("Verifying token\u2026");
625
679
  let email;
626
680
  try {
627
- const res = await fetch(`${apiUrl.replace(/\/$/, "")}/api/cli/whoami`, {
681
+ const res = await fetch(`${apiUrl}/api/cli/whoami`, {
628
682
  headers: { Authorization: `Bearer ${token}` }
629
683
  });
630
684
  if (res.status === 401 || res.status === 403) {
631
- printError("Token is invalid or revoked.", "Create a new token at " + apiUrl + "/settings/tokens");
685
+ printError("Token is invalid or revoked.", `Create a new token at ${apiUrl}/settings/tokens`);
632
686
  process.exit(1);
633
687
  }
634
688
  if (res.ok) {
@@ -639,12 +693,16 @@ ${color.bold("Relion Login")}
639
693
  console.warn(color.yellow(" Could not verify token (network issue). Saving anyway."));
640
694
  }
641
695
  const existing = readGlobalConfig();
642
- writeGlobalConfig({ ...existing, token, apiUrl: apiUrl !== "https://relion.dev" ? apiUrl : void 0, email });
643
- console.log(`${color.green("\u2713")} ${color.bold("Authenticated")}${email ? ` as ${email}` : ""}`);
644
- console.log(`${color.dim(" Token saved to ~/.relion/config.json")}
645
- `);
646
- console.log(`Run: ${color.cyan("relion scan .")}
647
- `);
696
+ writeGlobalConfig({
697
+ ...existing,
698
+ token,
699
+ apiUrl: apiUrl !== DEFAULT_API_URL2 ? apiUrl : void 0,
700
+ email
701
+ });
702
+ console.log(`
703
+ ${color.green("\u2713")} ${color.bold("Authenticated")}${email ? ` as ${color.cyan(email)}` : ""}`);
704
+ console.log(color.dim(" Token saved to ~/.relion/config.json\n"));
705
+ process.exit(0);
648
706
  }
649
707
  async function logoutCommand() {
650
708
  writeGlobalConfig({});
@@ -654,13 +712,13 @@ async function logoutCommand() {
654
712
  async function whoamiCommand(flags) {
655
713
  const config = readGlobalConfig();
656
714
  const token = process.env.RELION_TOKEN ?? config.token;
657
- const apiUrl = flags.url ?? config.apiUrl ?? "https://relion.dev";
715
+ const apiUrl = (flags.url ?? config.apiUrl ?? DEFAULT_API_URL2).replace(/\/$/, "");
658
716
  if (!token) {
659
717
  printError("Not logged in.", "Run: relion login");
660
718
  process.exit(1);
661
719
  }
662
720
  try {
663
- const res = await fetch(`${apiUrl.replace(/\/$/, "")}/api/cli/whoami`, {
721
+ const res = await fetch(`${apiUrl}/api/cli/whoami`, {
664
722
  headers: { Authorization: `Bearer ${token}` }
665
723
  });
666
724
  if (!res.ok) {
@@ -670,9 +728,9 @@ async function whoamiCommand(flags) {
670
728
  const data = await res.json();
671
729
  console.log(`
672
730
  ${color.bold("Relion identity")}`);
673
- if (data.email) console.log(` Email: ${data.email}`);
674
- if (data.workspace) console.log(` Workspace: ${data.workspace}`);
675
- console.log(` API: ${apiUrl}
731
+ if (data.name) console.log(` Name: ${data.name}`);
732
+ if (data.email) console.log(` Email: ${data.email}`);
733
+ console.log(` API: ${apiUrl}
676
734
  `);
677
735
  } catch {
678
736
  printError("Could not reach Relion API.", `URL: ${apiUrl}`);
@@ -984,7 +1042,7 @@ ${color.bold("Environment variables:")}
984
1042
  RELION_COMMIT Git commit SHA
985
1043
  RELION_BRANCH Branch name
986
1044
 
987
- ${color.dim("https://relion.dev/docs/cli")}
1045
+ ${color.dim("https://relionapi.com/predeploy-review/guide")}
988
1046
  `);
989
1047
  }
990
1048
  async function main() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "relionhq",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "Relion CLI — pre-deploy API risk detection and monitoring client.",
5
5
  "license": "MIT",
6
6
  "bin": {