apiblaze 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/README.md +1 -0
- package/dist/index.js +39 -18
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -39,6 +39,7 @@ var ApiError = class extends Error {
|
|
|
39
39
|
// src/commands/login.ts
|
|
40
40
|
var import_chalk = __toESM(require("chalk"));
|
|
41
41
|
var import_ora = __toESM(require("ora"));
|
|
42
|
+
var crypto = __toESM(require("crypto"));
|
|
42
43
|
|
|
43
44
|
// src/lib/auth.ts
|
|
44
45
|
var fs = __toESM(require("fs"));
|
|
@@ -76,17 +77,28 @@ function getApiblazeDir() {
|
|
|
76
77
|
// src/commands/login.ts
|
|
77
78
|
var AUTH_BASE = "https://auth.apiblaze.com";
|
|
78
79
|
var CLIENT_ID = "emdE4-Pt9LGOAXL5MA1zEQ";
|
|
80
|
+
var SCOPE = "openid email profile offline_access";
|
|
81
|
+
function generateCodeVerifier() {
|
|
82
|
+
return crypto.randomBytes(32).toString("base64url");
|
|
83
|
+
}
|
|
84
|
+
function generateCodeChallenge(verifier) {
|
|
85
|
+
return crypto.createHash("sha256").update(verifier).digest("base64url");
|
|
86
|
+
}
|
|
79
87
|
function openBrowser(url) {
|
|
80
88
|
const { exec } = require("child_process");
|
|
81
|
-
const cmd = process.platform === "darwin" ? `open "${url}"` : process.platform === "win32" ? `start "${url}"` : `xdg-open "${url}"`;
|
|
82
|
-
exec(cmd
|
|
83
|
-
});
|
|
89
|
+
const cmd = process.platform === "darwin" ? `open "${url}"` : process.platform === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
|
|
90
|
+
exec(cmd);
|
|
84
91
|
}
|
|
85
|
-
async function requestDeviceCode() {
|
|
86
|
-
const res = await fetch(`${AUTH_BASE}/
|
|
92
|
+
async function requestDeviceCode(codeChallenge) {
|
|
93
|
+
const res = await fetch(`${AUTH_BASE}/device_authorization`, {
|
|
87
94
|
method: "POST",
|
|
88
95
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
89
|
-
body: new URLSearchParams({
|
|
96
|
+
body: new URLSearchParams({
|
|
97
|
+
client_id: CLIENT_ID,
|
|
98
|
+
scope: SCOPE,
|
|
99
|
+
code_challenge: codeChallenge,
|
|
100
|
+
code_challenge_method: "S256"
|
|
101
|
+
})
|
|
90
102
|
});
|
|
91
103
|
if (!res.ok) {
|
|
92
104
|
const body = await res.text();
|
|
@@ -94,17 +106,19 @@ async function requestDeviceCode() {
|
|
|
94
106
|
}
|
|
95
107
|
return res.json();
|
|
96
108
|
}
|
|
97
|
-
async function pollForToken(deviceCode, intervalSecs) {
|
|
109
|
+
async function pollForToken(deviceCode, codeVerifier, intervalSecs) {
|
|
110
|
+
const DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
98
111
|
let pollInterval = intervalSecs * 1e3;
|
|
99
112
|
while (true) {
|
|
100
113
|
await new Promise((r) => setTimeout(r, pollInterval));
|
|
101
|
-
const res = await fetch(`${AUTH_BASE}/
|
|
114
|
+
const res = await fetch(`${AUTH_BASE}/token`, {
|
|
102
115
|
method: "POST",
|
|
103
116
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
104
117
|
body: new URLSearchParams({
|
|
105
|
-
grant_type:
|
|
118
|
+
grant_type: DEVICE_GRANT,
|
|
106
119
|
device_code: deviceCode,
|
|
107
|
-
client_id: CLIENT_ID
|
|
120
|
+
client_id: CLIENT_ID,
|
|
121
|
+
code_verifier: codeVerifier
|
|
108
122
|
})
|
|
109
123
|
});
|
|
110
124
|
const body = await res.json();
|
|
@@ -126,17 +140,24 @@ async function pollForToken(deviceCode, intervalSecs) {
|
|
|
126
140
|
}
|
|
127
141
|
async function runLogin() {
|
|
128
142
|
console.log(import_chalk.default.bold("\nLogging in to APIblaze...\n"));
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
const codeVerifier = generateCodeVerifier();
|
|
144
|
+
const codeChallenge = generateCodeChallenge(codeVerifier);
|
|
145
|
+
const deviceAuth = await requestDeviceCode(codeChallenge);
|
|
146
|
+
const verifyUrl = deviceAuth.verification_uri_complete ?? deviceAuth.verification_uri;
|
|
147
|
+
console.log(`${import_chalk.default.cyan("\u2192")} Open this URL in your browser to confirm login:`);
|
|
148
|
+
console.log(` ${import_chalk.default.bold.underline(verifyUrl)}
|
|
132
149
|
`);
|
|
133
|
-
|
|
134
|
-
console.log(`${import_chalk.default.cyan("\u2192")} Enter code: ${import_chalk.default.bold(deviceAuth.user_code)}
|
|
150
|
+
console.log(`${import_chalk.default.cyan("\u2192")} Your code: ${import_chalk.default.bold(deviceAuth.user_code)}
|
|
135
151
|
`);
|
|
152
|
+
openBrowser(verifyUrl);
|
|
153
|
+
const spinner = (0, import_ora.default)("Waiting for authorization in browser...").start();
|
|
154
|
+
let token;
|
|
155
|
+
try {
|
|
156
|
+
token = await pollForToken(deviceAuth.device_code, codeVerifier, deviceAuth.interval);
|
|
157
|
+
} catch (err) {
|
|
158
|
+
spinner.fail("Login failed.");
|
|
159
|
+
throw err;
|
|
136
160
|
}
|
|
137
|
-
openBrowser(deviceAuth.verification_uri_complete ?? deviceAuth.verification_uri);
|
|
138
|
-
const spinner = (0, import_ora.default)("Waiting for authorization...").start();
|
|
139
|
-
const token = await pollForToken(deviceAuth.device_code, deviceAuth.interval);
|
|
140
161
|
saveCredentials({
|
|
141
162
|
accessToken: token.access_token,
|
|
142
163
|
refreshToken: token.refresh_token,
|