relayax-cli 0.1.0 → 0.1.1
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/commands/login.js +70 -21
- package/package.json +1 -1
package/dist/commands/login.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.registerLogin = registerLogin;
|
|
4
|
-
const
|
|
7
|
+
const http_1 = __importDefault(require("http"));
|
|
5
8
|
const child_process_1 = require("child_process");
|
|
6
9
|
const config_js_1 = require("../lib/config.js");
|
|
7
10
|
function openBrowser(url) {
|
|
@@ -21,15 +24,6 @@ function openBrowser(url) {
|
|
|
21
24
|
// ignore browser open errors
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
|
-
async function readLine(prompt) {
|
|
25
|
-
const rl = (0, readline_1.createInterface)({ input: process.stdin, output: process.stderr });
|
|
26
|
-
return new Promise((resolve) => {
|
|
27
|
-
rl.question(prompt, (answer) => {
|
|
28
|
-
rl.close();
|
|
29
|
-
resolve(answer.trim());
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
27
|
async function verifyToken(apiUrl, token) {
|
|
34
28
|
try {
|
|
35
29
|
const res = await fetch(`${apiUrl}/api/auth/me`, {
|
|
@@ -43,10 +37,63 @@ async function verifyToken(apiUrl, token) {
|
|
|
43
37
|
return null;
|
|
44
38
|
}
|
|
45
39
|
}
|
|
40
|
+
function waitForToken(port) {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const server = http_1.default.createServer((req, res) => {
|
|
43
|
+
const url = new URL(req.url ?? '/', `http://localhost:${port}`);
|
|
44
|
+
if (url.pathname === '/callback') {
|
|
45
|
+
const token = url.searchParams.get('token');
|
|
46
|
+
// Send a nice HTML response that auto-closes
|
|
47
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
48
|
+
res.end(`<!DOCTYPE html>
|
|
49
|
+
<html><head><title>RelayAX</title></head>
|
|
50
|
+
<body style="font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;background:#f6f5f2;color:#111318">
|
|
51
|
+
<div style="text-align:center">
|
|
52
|
+
<h2>로그인 완료!</h2>
|
|
53
|
+
<p>터미널로 돌아가세요. 이 창은 닫아도 됩니다.</p>
|
|
54
|
+
<script>setTimeout(()=>window.close(),2000)</script>
|
|
55
|
+
</div>
|
|
56
|
+
</body></html>`);
|
|
57
|
+
server.close();
|
|
58
|
+
if (token) {
|
|
59
|
+
resolve(token);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
reject(new Error('토큰이 전달되지 않았습니다'));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
res.writeHead(404);
|
|
67
|
+
res.end('Not found');
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
server.listen(port, '127.0.0.1');
|
|
71
|
+
// Timeout after 5 minutes
|
|
72
|
+
setTimeout(() => {
|
|
73
|
+
server.close();
|
|
74
|
+
reject(new Error('로그인 시간이 초과되었습니다 (5분)'));
|
|
75
|
+
}, 5 * 60 * 1000);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
function findAvailablePort() {
|
|
79
|
+
return new Promise((resolve, reject) => {
|
|
80
|
+
const server = http_1.default.createServer();
|
|
81
|
+
server.listen(0, '127.0.0.1', () => {
|
|
82
|
+
const addr = server.address();
|
|
83
|
+
if (addr && typeof addr !== 'string') {
|
|
84
|
+
const port = addr.port;
|
|
85
|
+
server.close(() => resolve(port));
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
server.close(() => reject(new Error('포트를 찾을 수 없습니다')));
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
46
93
|
function registerLogin(program) {
|
|
47
94
|
program
|
|
48
95
|
.command('login')
|
|
49
|
-
.description('
|
|
96
|
+
.description('RelayAX 계정에 로그인합니다')
|
|
50
97
|
.option('--token <token>', '직접 토큰 입력 (브라우저 없이)')
|
|
51
98
|
.action(async (opts) => {
|
|
52
99
|
const pretty = program.opts().pretty ?? false;
|
|
@@ -55,15 +102,18 @@ function registerLogin(program) {
|
|
|
55
102
|
const apiUrl = config?.api_url ?? 'https://relayax.com';
|
|
56
103
|
let token = opts.token;
|
|
57
104
|
if (!token) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
105
|
+
try {
|
|
106
|
+
const port = await findAvailablePort();
|
|
107
|
+
const loginUrl = `${apiUrl}/auth/cli-login?port=${port}`;
|
|
108
|
+
console.error('브라우저에서 로그인을 진행합니다...');
|
|
109
|
+
openBrowser(loginUrl);
|
|
110
|
+
token = await waitForToken(port);
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
const msg = err instanceof Error ? err.message : '로그인 실패';
|
|
114
|
+
console.error(JSON.stringify({ error: 'LOGIN_FAILED', message: msg }));
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
67
117
|
}
|
|
68
118
|
const user = await verifyToken(apiUrl, token);
|
|
69
119
|
const updatedConfig = {
|
|
@@ -81,7 +131,6 @@ function registerLogin(program) {
|
|
|
81
131
|
console.log(`\x1b[32m✓ 로그인 완료\x1b[0m`);
|
|
82
132
|
if (user?.email)
|
|
83
133
|
console.log(` 계정: \x1b[36m${user.email}\x1b[0m`);
|
|
84
|
-
console.log(` 토큰이 ~/.relay/config.json에 저장되었습니다.`);
|
|
85
134
|
}
|
|
86
135
|
else {
|
|
87
136
|
console.log(JSON.stringify(result));
|