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.
- package/dist/index.js +86 -28
- 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://
|
|
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 ??
|
|
608
|
+
const apiUrl = (flags.url ?? process.env.RELION_API_URL ?? DEFAULT_API_URL2).replace(/\/$/, "");
|
|
605
609
|
if (flags.token) {
|
|
606
|
-
await
|
|
610
|
+
await saveAndVerifyToken(flags.token, apiUrl);
|
|
607
611
|
return;
|
|
608
612
|
}
|
|
609
|
-
|
|
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
|
-
|
|
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.
|
|
624
|
+
${color.dim("If it doesn't open automatically, visit:")}`);
|
|
625
|
+
console.log(` ${color.cyan(authUrl)}
|
|
623
626
|
`);
|
|
624
|
-
|
|
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
|
|
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.",
|
|
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({
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
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 ??
|
|
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
|
|
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.
|
|
674
|
-
if (data.
|
|
675
|
-
console.log(` API:
|
|
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://
|
|
1045
|
+
${color.dim("https://relionapi.com/predeploy-review/guide")}
|
|
988
1046
|
`);
|
|
989
1047
|
}
|
|
990
1048
|
async function main() {
|