orchestrating 0.1.32 → 0.1.33
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/bin/orch +110 -46
- package/package.json +1 -1
package/bin/orch
CHANGED
|
@@ -106,63 +106,127 @@ function isTokenExpired() {
|
|
|
106
106
|
return Date.now() / 1000 > auth.expires_at - 300;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
// --- Login: save auth from a base64-encoded code ---
|
|
110
|
+
function saveAuthFromCode(code) {
|
|
111
|
+
try {
|
|
112
|
+
const decoded = JSON.parse(Buffer.from(code.trim(), "base64").toString());
|
|
113
|
+
if (decoded.access_token) {
|
|
114
|
+
saveAuth({
|
|
115
|
+
access_token: decoded.access_token,
|
|
116
|
+
refresh_token: decoded.refresh_token || "",
|
|
117
|
+
expires_at: decoded.expires_at || 0,
|
|
118
|
+
});
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
} catch {}
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// --- Login: read a line from stdin ---
|
|
126
|
+
function readLine(prompt) {
|
|
127
|
+
return new Promise((resolve) => {
|
|
128
|
+
process.stdout.write(prompt);
|
|
129
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false });
|
|
130
|
+
rl.once("line", (line) => { rl.close(); resolve(line); });
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
109
134
|
// --- Login command ---
|
|
110
135
|
async function handleLogin() {
|
|
111
136
|
const loginUrl = process.env.ORC_LOGIN_URL || "https://orchestrat.ing/cli-auth";
|
|
112
137
|
|
|
138
|
+
// Try to start a local callback server (works when browser is on same machine)
|
|
139
|
+
let resolved = false;
|
|
140
|
+
|
|
113
141
|
return new Promise((resolve) => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
142
|
+
let server;
|
|
143
|
+
let codePromise;
|
|
144
|
+
|
|
145
|
+
function done() {
|
|
146
|
+
if (resolved) return;
|
|
147
|
+
resolved = true;
|
|
148
|
+
if (server) try { server.close(); } catch {}
|
|
149
|
+
resolve();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
try {
|
|
153
|
+
server = http.createServer((req, res) => {
|
|
154
|
+
const url = new URL(req.url, `http://localhost`);
|
|
155
|
+
if (url.pathname === "/callback") {
|
|
156
|
+
const accessToken = url.searchParams.get("access_token");
|
|
157
|
+
const refreshToken = url.searchParams.get("refresh_token");
|
|
158
|
+
const expiresAt = url.searchParams.get("expires_at");
|
|
159
|
+
|
|
160
|
+
if (accessToken) {
|
|
161
|
+
saveAuth({
|
|
162
|
+
access_token: accessToken,
|
|
163
|
+
refresh_token: refreshToken || "",
|
|
164
|
+
expires_at: expiresAt ? Number(expiresAt) : 0,
|
|
165
|
+
});
|
|
166
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
167
|
+
res.end('<html><head><meta http-equiv="refresh" content="0;url=https://app.orchestrat.ing"></head><body><p>Redirecting to dashboard...</p></body></html>');
|
|
168
|
+
console.log("\x1b[32mLogged in successfully.\x1b[0m");
|
|
169
|
+
} else {
|
|
170
|
+
res.writeHead(400, { "Content-Type": "text/html" });
|
|
171
|
+
res.end("<html><body><h2>Authentication failed. Please try again.</h2></body></html>");
|
|
172
|
+
console.error("Authentication failed — no token received.");
|
|
173
|
+
}
|
|
174
|
+
done();
|
|
130
175
|
} else {
|
|
131
|
-
res.writeHead(
|
|
132
|
-
res.end(
|
|
133
|
-
console.error("Authentication failed — no token received.");
|
|
176
|
+
res.writeHead(404);
|
|
177
|
+
res.end();
|
|
134
178
|
}
|
|
179
|
+
});
|
|
135
180
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
res.end();
|
|
140
|
-
}
|
|
141
|
-
});
|
|
181
|
+
server.listen(0, "127.0.0.1", () => {
|
|
182
|
+
const port = server.address().port;
|
|
183
|
+
const authUrl = `${loginUrl}?port=${port}`;
|
|
142
184
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
185
|
+
// Try to open browser
|
|
186
|
+
const openCmd = process.platform === "darwin" ? "open"
|
|
187
|
+
: process.platform === "win32" ? "start"
|
|
188
|
+
: "xdg-open";
|
|
189
|
+
try {
|
|
190
|
+
execSync(`${openCmd} "${authUrl}"`, { stdio: "ignore" });
|
|
191
|
+
console.log(`Opened browser for authentication.`);
|
|
192
|
+
} catch {
|
|
193
|
+
// Browser open failed
|
|
194
|
+
}
|
|
148
195
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
196
|
+
console.log(`\nVisit this URL to log in:\n\n ${authUrl}\n`);
|
|
197
|
+
console.log(`Or for headless/VM, visit:\n\n ${loginUrl}\n`);
|
|
198
|
+
|
|
199
|
+
// Also accept pasted code
|
|
200
|
+
codePromise = readLine("Paste auth code here (or wait for browser): ").then((code) => {
|
|
201
|
+
if (resolved) return;
|
|
202
|
+
if (code && saveAuthFromCode(code)) {
|
|
203
|
+
console.log("\x1b[32mLogged in successfully.\x1b[0m");
|
|
204
|
+
done();
|
|
205
|
+
} else if (code) {
|
|
206
|
+
console.error("Invalid code. Try again.");
|
|
207
|
+
}
|
|
208
|
+
});
|
|
158
209
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
210
|
+
// Timeout after 5 minutes
|
|
211
|
+
setTimeout(() => {
|
|
212
|
+
if (!resolved) {
|
|
213
|
+
console.error("Login timed out.");
|
|
214
|
+
done();
|
|
215
|
+
}
|
|
216
|
+
}, 300_000);
|
|
217
|
+
});
|
|
218
|
+
} catch {
|
|
219
|
+
// Can't start server — code-paste only
|
|
220
|
+
console.log(`Visit this URL to log in:\n\n ${loginUrl}\n`);
|
|
221
|
+
readLine("Paste auth code here: ").then((code) => {
|
|
222
|
+
if (code && saveAuthFromCode(code)) {
|
|
223
|
+
console.log("\x1b[32mLogged in successfully.\x1b[0m");
|
|
224
|
+
} else {
|
|
225
|
+
console.error("Invalid code.");
|
|
226
|
+
}
|
|
227
|
+
done();
|
|
228
|
+
});
|
|
229
|
+
}
|
|
166
230
|
});
|
|
167
231
|
}
|
|
168
232
|
|